本文總結了常見智能合約的安全漏洞及預防措施,並對項目方和一般用戶給出了一些安全建議
作者: Max Cobo 安全總監
封面: Photo by Armand Khoury on Unsplash
此篇是 Cobo Global 的第 24 篇文章
受 Moledao 邀請,Cobo 安全總監 Max 近日通過網絡為社區成員分享了一堂 DeFi 安全課。Max 為大家回顧了過去一年多 Web3 行業遭遇的重大安全事件,並著重探討了這些安全事件發生的原因以及如何規避,總結了常見智能合約的安全漏洞及預防措施,還對項目方和一般用戶給出了一些安全建議。在此,我們將 Max 分享的內容分為兩篇發布,供 DeFi 愛好者收藏。
上篇:《Cobo DeFi 安全課(上):复盤 2022 DeFi 安全大事件》
常見的 DeFi 漏洞類型一般有閃電貸、價格操縱、函數權限問題、任意外部調用、fallback 函數問題、業務邏輯漏洞、私鑰洩漏、重入。
2022 年 11-12 月安全事件統計
重點介紹一下閃電貸、價格操控以及重入攻擊這三種類型。
閃電貸
- 常⻅攻擊往往伴隨著閃電貸,攻擊者喜歡通過閃電貸借出大量資金,對價格進行操縱,攻擊業務邏輯等等;
- 開發者需要考慮,合約功能是否會因為巨額的資金導致功能異常,或通過巨額資金在一筆交易中與合約中多個函數交互獲取獎勵這些場景;
- 經常可以看到合約中一些 Token 數量的值被用於計算獎勵,或是使用 DEX 交易對中的 Token 數量參與各種計算,由於開發者在設計這些功能時沒有考慮到攻擊者可以利用閃電貸操控這些變量,導致合約資金被盜。
閃電貸本身是 DeFi 的一種創新,但是當被黑客利用時,他們不需要花費任何成本就可以藉錢,在執行完整個套利流程後再歸還,剩下的部分就是套利的收益,他們不需要付出任何代價,只需要支付少量的 Gas 費用就可以獲得巨額收益。
在過去的兩年裡,閃電貸出現了很多問題。許多 DeFi 項目看起來收益很高,但實際上項目方的水平參差不齊。比如代碼有可能是買來的,即便代碼本身沒有漏洞,在邏輯上仍然可能存在問題。例如,我們曾經遇到過一個項目,會在固定的時間根據持倉者持有的代幣數量發放獎勵,卻被攻擊者利用閃電貸購買大量代幣,在獎勵發放時,大部分獎勵都流向了攻擊者。此外,還有一些通過 Token 來計算價格的項目,可以通過閃電貸影響價格,作為項目方應該對這些問題提高警惕。
價格操控
價格操控問題與閃電貸關係密切,這個問題主要是由於價格計算時其中一些參數可以被用戶控制,經常出現的問題的類型有兩種。
- 一種是計算價格時使用第三方的數據,但使用方式不正確或檢查缺失導致價格被惡意操控。
- 另外一種是由於使用了一些地址的 Token 數量作為計算變量,而這些地址的 Token 餘額可以被臨時增加或減少。
重入攻擊
調用外部合約的主要危險之一是它們可以接管控制流,並對你的數據進行調用函數未預料到的更改。
“`
mapping (address => uint) private userBalances; function withdrawBalance() public {
uint amountToWithdraw = userBalances[msg.sender];
(bool success, ) = msg.sender.call.value(amountToWithdraw)(“”); // 如果 msg.sender 是一個合約,那麼合約的 fallback 代碼會被執行,並可以再次調用 withdrawBalance 完成重入攻擊
require(success);
userBalances[msg.sender] = 0;
}
“`
由於用戶的餘額直到函數的最後才設置為 0,第二次(和以後的)調用仍然會成功,並且會一遍又一遍地提取餘額。
針對於不同的合約,重入存在的方式很多,可以結合合約的不同函數或多個不同合約的函數,完成重入攻擊,所以我們在解決重入問題時需要注意以下幾點:1. 不只是防止單一函數的重入問題;2. 遵循 Checks-Effects-Interactions 模式進行編碼;3. 使用經過時間驗證的防重入 modifier。
其實最怕的就是重複造輪子,需要什麼都自己寫,在這個圈內有很多最佳安全實踐,我們拿來用就好,完全沒有必要重複造輪子。當你造一個輪子的時候,是沒有通過充分的驗證的,這個時候出問題的概率,很明顯比用一個非常成熟的久經考驗的出問題的概率要大得多。
Omni Protocol 由於重入問題被黑客攻擊,它還有另外一個故事:
Omni Protocol 漏洞背後的故事 — 四個黑客之間的較量
以太坊的 mempool 一直被大量黑客監視,他們不斷的分析交易並對有利可圖的交易進行搶跑,來獲取利潤。Omni Protocol 漏洞發現者提交的攻擊交易,就被兩位黑客捕捉到,他們利用搶跑機器人在 flashbot 發布搶跑交易奪取了 Omni Protocol 協議中的 1200 ETH,而發現漏洞的攻擊者卻只獲得了 480ETH。在此期間,還有一位黑客發現了搶跑黑客在 flashbot 提交的攻擊交易,利用攻擊交易需要購買 Doodle ERC20 代幣的特點,對其進行了三明治攻擊,獲利 151ETH。
發現漏洞的人獲利並不是最多的,獲利更多的是黑暗森林裡其他的獵人。在這個生態中遍地都是獵人,獵人之間可能互為獵物,哪怕是攻擊的發起者,如果是新手的話,可能也拿不走這個項目的大部分錢,除非一筆拿走。還有很多人會用更高的 Gas 費搶先把交易執行,在搶跑的過程中如果涉及到了在 DEX 中的代幣的買賣的話,會涉及到被三明治攻擊,非常的混亂。
安全建議
最後是給項目方和普通參與用戶的安全建議。
項目方安全 Tips
一、合約開發遵循最佳安全實踐。
二、合約可升級、暫停:很多攻擊不是一次性的把幣全轉走,而是分多筆交易去執行,如果有一個相對健全的監控機制的話,是可以發現的,發現之後合約假設是可以暫停的,就可以有效的去降低損失。
三、採用時間鎖:像 Ankr 的案例,如果有時間鎖的話,假設是 48 小時之內才能完成,這個時候在時間鎖的很多人能發現這個創建者重新更新了一個 mint 的方法,且誰都可以用,監控的人就知道項目應該是被黑了,就可以通知項目方去改變,即使假設通知了也沒人管,至少可以先把自己的那部分錢給拿出來,先保證自己的收益不受損。所以說一個項目如果沒有時間鎖的話,理論上來講是增加了出問題的概率。
四、加大安全投入,建立一套完善的安全體系:安全不是一個點,也不是一條線,安全是成體系的。不要覺得作為項目方,合約通過多家公司審計就沒問題了,結果朝鮮黑客把私鑰盜走了,哪怕是多簽,把幾個私鑰全部都盜走了。或者是說經濟模型有問題,業務模式有問題……能導致錢丟的方式有千千萬萬種,就看在事前能不能將安全風險全都規避掉。要盡量做風險建模,然後逐步地將大部分風險規避掉,剩餘風險也是可接受風險,在可承受範圍內。安全和效率是不可能兼得的,要做一定的取捨。但如果完全不管安全,在安全上沒有投入的話,被攻擊是很正常的。
五、提高所有員工的安全意識:提高安全意識並不需要很多技術。在 Twitter 上我們經常能看到很多人被釣魚丟失 NFT,其實釣魚的方式就是利用了人性的弱點,可能多注意一點,就不會中招。在 Web3 這個大環境內,只要稍微多問一些為什麼,稍微多想一點就能規避掉很多問題。
六、預防內部作惡,在提升效率的同時增強⻛控:再拿 Ankr 來舉例。第一,合約的 Owner 是一個單簽而不是多簽,私鑰丟了整個項目就被控制了;第二,沒有用時間鎖,一些關鍵性的操作更新,立馬就更新了,沒有人知道,對於整個協議的參與者是非常不公平的;再就是內部作惡,內部的安全機制沒有起到任何作用。
鏈上的協議如何在保證效率的同時,在安全性上也有一定提升?這裡做一個廣告,推薦 Cobo Safe,假設一個項目採用多簽,我們操作的時候,稍微會影響一下效率。通過 Cobo Safe 可以指定某個人執行某個操作,比如是五分之三多簽;可以指定某一個地址可以做某一個操作,比如可以給到一個非常值得信賴的一個節點做安全風險監控,假設發現到協議正在被攻擊,資金正在逐漸往黑客地址轉的時候,如果這個合約本身有暫停的功能,那我們將暫停功能授予給了某個人,他就可以去做這個操作。
再比如說給 DEX 做市的做市商,如果不去限制 Owner 權限的話,那 Owner 可以把錢給轉到別的地址,通過 Cobo Safe 可以限制轉幣的地址,限制只能操作哪幾個幣對,設置只能把錢提到某個地址。Cobo Safe 在效率提升的同時,保證了一定的安全性。
七、三方引入安全性:作為生態中的一環,項目方都會有自己的上下游。安全上有一個 “默認上下游都是不安全” 的原則。無論對於上游還是下游,都要做校驗。對於三方我們是很難控制,安全的風險敞口實際上特別大,所以要很注意三方的引入。合約是開源的,可以去引入、調用它;如果合約不開源,就絕對不能引用。因為我們不知道裡面的邏輯是什麼,或者是引入這個合約本身就是一個可升級的合約,正常用可能沒問題,但我們無法預知是不是突然有一天會升級變成一個作惡的合約,這是無法控制的。
用戶/LP 如何判斷智能合約是否安全?
對於普通用戶,我們判斷項目是否安全主要看以下六點:
一、合約是否開源:凡是合約不開源的項目,堅決不碰,因為我們無從得知合約寫的是什麼。
二、Owner 是否採用多簽,多簽是否去中心化:如果不用多簽,我們無法判斷項目的業務邏輯和內容,一旦出現安全事件,無法判斷是否為黑客所為。即便採用多簽,也需要判斷一下多簽是不是去中心化的。
三、合約已有的交易情況:尤其市面上有很多搞釣魚詐騙的項目,可能會做一個比較相似的合約,這個時候我們就要看一下合約的部署時間、交互次數等,這些都是判斷合約是否是安全的衡量標準。
四、合約是否為代理合約,是否可升級,是否有時間鎖:如果合約完全不能升級,就太死板了,還是推薦項目的合約是可以升級的。但是升級要講究方法,當升級有升級內容、重要參數更改的時候,要有一個時間鎖定,要有給大家一個時間窗口去判斷真實升級是對用戶有害的還是有利的,這也是公開透明的一種方式。
五、合約是否接受過多家機構審計(不要盲目信任審計公司), Owner 權限是否過大:首先不要只相信一家審計公司,因為不同的審計公司,不同的審計人員,看問題的角度是不一樣的。如果一個項目有多家機構的審計結果,發現了不同的問題,項目方都做了修復的話,相比較只有某一家審計公司審計要更安全。一個負責任的項目方會找多家審計機構做交叉的審計。
其次要看 Owner 的權限是否過大。比如說有一些貔恘盤項目,Owner 可以完全控制用戶的資金,如果代幣買的少可以正常買賣,如果代幣購買量巨大,Owner 立馬可以控制去鎖死,而無法交易。還有一些 NFT 項目也是一樣的。一個正常的項目 Owner 的權限一定是可控的,這樣就不會有太多高危操作,操作也會用時間鎖的方式,讓用戶知道操作的是什麼。尤其是行情不好的時候,有各種各樣的跑路盤,所以大家對於 Ownner 的權限一定要重視。
六、注意預言機:如果項目使用市面上的龍頭預言機,基本上不會有太大問題,但如果使用自建的預言機,或者用一些隨便抵押一些代幣就可以往裡去餵價的預言機,那就要注意了。當發現預言機可能會存在一些問題,或者說存在被操縱可能的時候,即便項目收益再高也不能參與。
免責聲明:作為區塊鏈信息平台,本站所發布文章僅代表作者及嘉賓個人觀點,與 Web3Caff 立場無關。文章內的信息僅供參考,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。