區塊鏈安全事件回顧之The DAO被黑事件區塊鏈
曲速區:2016年6月17日,加密貨幣和區塊鏈社區發生了一次大地震,theDAO被黑客攻擊了。價值6千萬美元的以太幣被盜!!朋友圈,微信群一下子炸開了鍋。
曲速區:只有不忘歷史才能展望未來,在接下來這段時間里曲速區將帶你一起回顧區塊鏈安全事件總結與區塊鏈技術展望。
二、THE DAO被黑事件詳細回顧
今天我們來說第二個被盜事件: The DAO 被黑事件
二、以太幣組織 The DAO 被黑事件解析
時間:2016年6月
北京時間2016年6月17日發生了在區塊鏈歷史上留下沉重一筆的攻擊事件。由于 其編寫的智能合約存在著重大缺陷,區塊鏈業界最大的眾籌項目TheDAO(被攻擊前 擁有1億美元左右資產)遭到攻擊,目前已導致300多萬以太幣資產被分離出TheDAO 資產池。TheDAO編寫的智能合約中有一個splitDAO函數,攻擊者通過此函數中的漏洞重復利用自己的DAO資產來不斷從TheDAO項目的資產池中分離DAO資產給自己。
TheDAO 被攻擊,攻擊利用兩個代碼漏洞創建子合約提取了360萬個以太幣。因為攻擊者是通過splitDAO開始攻擊。我們從splitDAO代碼開始分析
函數調用者只能是TokenHolder。不能是ether賬戶。這里沒什么問題,符合預期
splitDAO的代碼有點長,我們看到如下的代碼
在這里是計算需要支付的金額,然后調用createTokenProxy函數。我們需要記住這點。根據BLOG 2,在DAO.sol中,function splitDAO函數有這樣一行:
合約中,為msg.sender記錄的dao幣余額歸零、扣減dao幣總量totalSupply等等都發生在將發回msg.sender之后,這里是在Blog 1中指出的一個典型“反模式”。
接下來看withdrawRewardFor函數。目前github中所見最新代碼并非部署于Ethereum livenet的代碼:
paidOut[_account] = reward 在原來代碼里面放在payOut函數調用之后,最新github代碼中被移到了payOut之前。再看payOut函數調用。rewardAccount的類型是ManagedAccount,在ManagedAccount.sol中可以看到:
_recipient.call.value()() 這個函數調用時,轉賬_amount個Wei,call調用默認會使用當前剩余的所有gas,此時call調用所執行的代碼步驟數可能很多,基本只受攻擊者所發消息的可用的gas限制。
把這些拼起來,黑客的攻擊手法就浮現了:
我們現在可以建立一個攻擊合約。
創建一個錢包,調用splitDAO多次,直到到達合約的gas limit,或者stack limit。
創建一個分割提案到一個新的錢包地址。
等待7天。
調用splitDAO
調用了兩次splitDAO,withdrawRewardFor也調用了兩次,并且兩次都是成功。成功竊取ether。
所以一定要先重置變量,再調用發送函數。
從代碼看,本次攻擊得逞的因素有二:一是dao余額扣減和Ether轉賬這兩步操作的順序有誤,二是不受限制地執行未知代碼。
曲速未來實驗室表示:本次黑客事件不意味著以太坊乃至去中心化、區塊鏈的終結。雖然教訓深刻,但如果能夠汲取教訓,那么從中獲益的不僅僅是THE DAO, 以太坊,整個區塊鏈社區都將從中獲益。
1.TMT觀察網遵循行業規范,任何轉載的稿件都會明確標注作者和來源;
2.TMT觀察網的原創文章,請轉載時務必注明文章作者和"來源:TMT觀察網",不尊重原創的行為TMT觀察網或將追究責任;
3.作者投稿可能會經TMT觀察網編輯修改或補充。