WF曲速區(qū):Solidity中的重入漏洞分析區(qū)塊鏈
Soildity作為編寫智能合約的語言,已經(jīng)被廣泛的應(yīng)用。但同時,開發(fā)者和用戶也得到了慘痛的教訓(xùn),智能合約的安全問題層出不窮。因此,區(qū)塊鏈安全公司W(wǎng)F曲速未來總結(jié)了一些常見的Solidity安全問題。前車之鑒,后車之師,希望后來者能有所警惕。
前言
Soildity 作為編寫智能合約的語言,已經(jīng)被廣泛的應(yīng)用。但同時,開發(fā)者和用戶也得到了慘痛的教訓(xùn),智能合約的安全問題層出不窮。
因此,區(qū)塊鏈安全公司W(wǎng)F曲速未來總結(jié)了一些常見的Solidity安全問題。前車之鑒,后車之師,希望后來者能有所警惕。
重入漏洞介紹
重入漏洞,按照表面意思就是可以重復(fù)進入。在以太坊的智能合約中,向為外部地址發(fā)送ETH需要調(diào)用外部合約的代碼。黑客通過劫持外部調(diào)用,從而重復(fù)進入以太坊智能合約的轉(zhuǎn)賬函數(shù)進行轉(zhuǎn)賬。
代碼分析
首先是以太坊的智能合約的轉(zhuǎn)賬函數(shù)
假如賬戶有10個幣,你要轉(zhuǎn)9個出去。肯定是可以的,你要轉(zhuǎn)11個,就不行。因為你沒有11個。所以此處要轉(zhuǎn)9個出去肯定是可以的。因為10>=9。最后一步就是減去你賬戶中的9個幣了。此時賬戶里面只有1個幣了。
看看黑客如何進行攻擊的:
.
攻擊者首先構(gòu)造一個惡意合約Mallory,將Mallory部署之后,攻擊者調(diào)用withdraw函數(shù)向Mallory合約捐贈一點以太幣。看似沒什么問題。
但是withdraw函數(shù)中的msg.sender.call.value(amout)()執(zhí)行之后,由于轉(zhuǎn)賬 操作特性 ,會在轉(zhuǎn)賬結(jié)束之后自動調(diào)用Mallory 的 fallback函數(shù),于是再次調(diào)用 withdraw函數(shù)。因為此時credit中并未更新額度,所以依然可以正常取款,便陷入遞 歸循環(huán),每次都提取DAO中的一部分以太幣到Mallory合約中。
在這里,我們上面分析過了,我們是先進行轉(zhuǎn)賬再進行扣款的。那么這樣有什么壞處呢?也就是說,如果在轉(zhuǎn)賬處一直循環(huán)卡住了,那么扣款就不會執(zhí)行。但是轉(zhuǎn)賬操作會一直執(zhí)行
相關(guān)事件
2016年6月以太幣組織 The DAO 被攻擊,攻擊者利用兩個代碼漏洞創(chuàng)建子合約提取了360萬個以太幣。接下來我們詳細分析一下這個事件
從splitDAO代碼開始
函數(shù)調(diào)用者只能是TokenHolder。不能是ether賬戶。這里沒什么問題,符合預(yù)期
splitDAO的代碼有點長,我們看到如下的代碼
在這里是計算需要支付的金額,然后調(diào)用createTokenProxy函數(shù)。我們需要記住這點。根據(jù)BLOG 2,在DAO.sol中,function splitDAO函數(shù)有這樣一行:
合約中,為msg.sender記錄的dao幣余額歸零、扣減dao幣總量totalSupply等等都發(fā)生在將發(fā)回msg.sender之后,這里是在Blog 1中指出的一個典型“反模式”。
接下來看withdrawRewardFor函數(shù)。目前github中所見最新代碼并非部署于Ethereum livenet的代碼:
paidOut[_account] = reward 在原來代碼里面放在payOut函數(shù)調(diào)用之后,最新github代碼中被移到了payOut之前。再看payOut函數(shù)調(diào)用。rewardAccount的類型是ManagedAccount,在ManagedAccount.sol中可以看到:
_recipient.call.value()() 這個函數(shù)調(diào)用時,轉(zhuǎn)賬_amount個Wei,call調(diào)用默認會使用當前剩余的所有g(shù)as,此時call調(diào)用所執(zhí)行的代碼步驟數(shù)可能很多,基本只受攻擊者所發(fā)消息的可用的gas限制。
把這些拼起來,黑客的攻擊手法就浮現(xiàn)了:
我們現(xiàn)在可以建立一個攻擊合約。
創(chuàng)建一個錢包,調(diào)用splitDAO多次,直到到達合約的gas limit,或者stack limit。
創(chuàng)建一個分割提案到一個新的錢包地址。
等待7天。
調(diào)用splitDAO
調(diào)用了兩次splitDAO,withdrawRewardFor也調(diào)用了兩次,并且兩次都是成功。成功竊取ether。
區(qū)塊鏈安全公司W(wǎng)F曲速未來 表示:作為已經(jīng)有過被利用先例的漏洞,開發(fā)者在編寫合約時應(yīng)更小心一些。
1.TMT觀察網(wǎng)遵循行業(yè)規(guī)范,任何轉(zhuǎn)載的稿件都會明確標注作者和來源;
2.TMT觀察網(wǎng)的原創(chuàng)文章,請轉(zhuǎn)載時務(wù)必注明文章作者和"來源:TMT觀察網(wǎng)",不尊重原創(chuàng)的行為TMT觀察網(wǎng)或?qū)⒆肪控熑危?br>
3.作者投稿可能會經(jīng)TMT觀察網(wǎng)編輯修改或補充。