智能合約安全——selfdestruct攻擊

selfdestruct函數(shù)(自毀函數(shù))由以太坊智能合約提供,用于銷毀區(qū)塊鏈上的合約系統(tǒng)。當合約執(zhí)行自毀操作時,合約賬戶上剩余的以太幣會發(fā)送給指定的目標,然后其存儲和代碼從狀態(tài)中被移除。

selfdestruct函數(shù)雖然能在緊急情況下幫助開發(fā)人員刪除智能合約并將合約內(nèi)的余額轉(zhuǎn)移到指定的地址,但這一特性也被不法分子利用,使它成為了攻擊手段。

讓我們來看個經(jīng)典游戲“幸運7”的案例:

合約代碼

漏洞分析

在“幸運7”游戲中,玩家每次向 EtherGame 合約中打入一個ETH,第七個成功打入ETH的玩家將成為 winner。winner 可以提取合約中的 7 個ETH。玩家每次玩游戲時都會調(diào)用 EtherGame.deposit 函數(shù)向合約中先打入一個ETH,隨后函數(shù)會檢查合約中的余額(balance)是否小于等于 7 ,只有合約中的余額小于等于 7 時才能繼續(xù)否則將回滾。合約中的余額(balance)是通過 address(this).balance 取到的,這就意味著我們只要有辦法在產(chǎn)生 winner 之前改變 EtherGame 合約中的余額讓他等于 7 就會使該合約癱瘓。這樣我們的攻擊方向就明確了,只要我們強制給 EtherGame 合約打入一筆ETH讓該合約中的余額大于7 這樣后面的玩家將無法通過 EtherGame.deposit 的檢查,從而使 EtherGame 合約癱瘓,永遠無法產(chǎn)生 winner。

但是EtherGame.deposit函數(shù)中存在驗證:require(msg.value == 1 ether, "You can only send 1 Ether"),這里要求我們每次只能打一個ETH進去,所以通過正常路徑是不可能一次向 EtherGame 打入大于 1 枚的ETH的,但是我們又需要打入大于 1 枚的ETH到 EtherGame 合約中,所以selfdestruct函數(shù)就登場了。

攻擊合約

攻擊者調(diào)用攻擊函數(shù)attack()銷毀合約并將合約中的余額強制轉(zhuǎn)賬到“幸運7”的游戲合約地址,制造出游戲合約查詢余額address(this).balance大于7的情況,導致函數(shù)回退,無法正常進行游戲的情況,使得游戲合約癱瘓。

修復建議

我們來分析一下攻擊者的思路:利用selfdestruct函數(shù)強制轉(zhuǎn)賬給游戲地址,導致unit balance = address(this).balance查詢出的balance的值大于7,誘發(fā)require(balance <= targetAmount, "Game is over");無法通過使得游戲合約癱瘓。

我們不難發(fā)現(xiàn)攻擊者是通過影響balance從而達到目的的,那么我們就讓balance不受這個影響,在最初先定義balance,再讓balance的值只受通過游戲規(guī)則內(nèi)的正常途徑的影響,這樣就不會出現(xiàn)balance值異常的情況了。

修復的代碼:

如果想了解更多的智能合約和區(qū)塊鏈知識,歡迎到區(qū)塊鏈交流社區(qū)CHAINPIP,一起交流學習~

社區(qū)地址:https://www.chainpip.com/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容