區塊鏈安全————DAO攻擊事件解析
0x00 前言
最近關注了一下區塊鏈方面的安全,因此翻出來之前的DAO攻擊事件研究了一番,形成此文。
之後可能還會發一些其他的安全分析文章。
0x00 基礎知識
1.跨合約呼叫
智慧合約之間的呼叫本質上是外部呼叫,可以使用message call或者建立智慧合約物件的形式進行呼叫。
(1)使用message call
比如合約1呼叫合約2的某個方法:
bytes4 methodId = bytes4(keccak256("increaseAge(string,uint256)"));
return addr.call(methodId,"jack", 1);
(2)還原智慧合約物件
如果已知合約的地址,可以通過如下方式獲取到合約物件:
Contract1 c = Contract1(AddressOfContract1) ;
c.foo() ; //跨合約呼叫
2.智慧合約傳送ETH
我們可以在智慧合約中用程式碼向某個地址(這個地址可以是人,也可以是智慧合約)傳送以太幣,比較常見的兩個方式是:
(1)呼叫send函式
比如:msg.sender.send(100)
(2)使用message call
msg.sender.call.value(100)()
這兩個方式不同的是傳送的gas數量:gas就是執行opcode需要花費的一種幣,稱作為gas也特別形象。當呼叫send方法時,只會傳送一部分gas,準確地來講,是2300gas,一旦gas耗盡就可能丟擲異常。
而使用message call的時候,則是傳送全部的gas,執行完之後剩餘的gas會退還給發起呼叫的合約。
3.fallback函式
智慧合約中可以有唯一的一個未命名函式,稱為fallback函式。該函式不能有實參,不能返回任何值。如果其他函式都不能匹配給定的函式識別符號,則執行fallback函式。
當合約接收到以太幣但是不呼叫任何函式的時候,就會執行fallback函式。如果一個合約接收了以太幣但是內部沒有fallback函式,那麼就會丟擲異常,然後將以太幣退還給傳送方。
下面就是一個fallback函式的程式碼示例。
contract Sample{
function () payable{
// your code here
}
}
一般單純使用message call或者send函式傳送以太幣給合約的時候,沒有指明呼叫合約的某個方法,這種情況下就會呼叫合約的fallback函式。
0x01 攻擊事件還原
我們先用簡單的模擬程式碼來了解下整個攻擊過程。
首先是存在漏洞的智慧合約程式碼,Bank:
使用者可以通過addToBalance方法存入一定量的以太幣到這個智慧合約,通過withdrawBalance方法可以提現以太坊,通過getUserBalance可以獲取到賬戶餘額。
注意到這裡是通過message call的方式來傳送以太幣,所以在呼叫sender的fallback函式的時候我們就會有充足的gas來進行迴圈呼叫。如果是send的方式,gas只有2300,稍微一操作就會耗盡gas丟擲異常,是不夠用來進行巢狀呼叫的。以下是不同操作所需要的gas數量:
出問題的是withdrawBalance方法,特別是在修改儲存在區塊鏈的balances的程式碼是放在了傳送以太幣之後。
攻擊程式碼如下:
這裡的deposit函式是往Bank合約中傳送10wei。withdraw是通過呼叫Bank合約的withdrawBalance函式把以太幣提取出來。注意看這裡的fallback函式,這裡迴圈呼叫了兩次Bank合約的withdrawBalance方法。
攻擊的過程如下:
(1)假設Bank合約中有100wei,攻擊者Attack合約中有10wei
(2)Attack合約先呼叫deposit方法向Bank合約傳送10wei
(3)之後Attack合約呼叫withdraw方法,從而呼叫了Bank的withdrawBalance方法。
(4)Bank的withdrawBalance方法傳送給了Attack合約10wei
(5)Attack收到10wei之後,又會觸發呼叫fallback函式
(6)這時,fallback函式又呼叫了兩次Bank合約的withdrawBalance,從而轉走了20wei
(7)之後Bank合約才修改Attack合約的balance,將其置為0
通過上面的步驟,攻擊者實際上從Bank合約轉走了30wei,Bank則損失了20wei,如果攻擊者多巢狀呼叫幾次withdrawBalance,完全可以將Bank合約中的以太幣全部轉走。
0x02 復現過程
給Bank合約100wei,給Attack合約10wei。
(1)部署Bank,分配100wei
(2)部署Attack
分配給Attack 10wei。
(3)呼叫Attack合約的deposit方法
(4)呼叫Attack合約的withdraw方法
(5)檢視Attack合約的餘額,變成了30wei,即竊取了20wei
0x03 DAO攻擊事件程式碼分析
在DAO原始碼中,有withdrawRewardFor函式:
function withdrawRewardFor(address _account) noEther internal returns (bool _success) {
if ((balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply < paidOut[_account])
throw;
uint reward =
(balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply - paidOut[_account];
if (!rewardAccount.payOut(_account, reward)) //vulnerable
throw;
paidOut[_account] += reward;
return true;
}
這裡呼叫了payOut函式進行付款。function payOut(address _recipient, uint _amount) returns (bool) {
if (msg.sender != owner || msg.value > 0 || (payOwnerOnly && _recipient != owner))
throw;
if (_recipient.call.value(_amount)()) { //vulnerable
PayOut(_recipient, _amount);
return true;
} else {
return false;
}
而payOut中直接使用的是message call的方式傳送以太幣,從而導致了巢狀漏洞。
0x04 總結
在編寫智慧合約進行以太幣傳送的時候,要使用send或者transfer,不要使用message call的方式,而send其實還是有些小問題,以後有時間再分析。DAO事件直接導致了以太坊硬分叉,分為ETH和ETC。可見,區塊鏈領域的安全不容忽視,因為其修復難度和所造成的影響都很高,畢竟是和錢打交道。
相關文章
- 區塊鏈安全 - 以太坊短地址攻擊區塊鏈
- 區塊鏈安全————以太坊短地址攻擊區塊鏈
- 區塊鏈安全:基於區塊鏈網路攻擊的方式原理詳解區塊鏈
- 區塊鏈安全:實現公鏈雙花攻擊的多種方法區塊鏈
- 一文讀懂區塊鏈安全:區塊鏈會帶來哪些衝擊?區塊鏈
- 從SolarWinds攻擊事件中看安全事件
- 區塊鏈安全————區塊鏈技術安全討論區塊鏈
- SolarWinds供應鏈攻擊事件分析事件
- 區塊鏈生態被黑客攻擊的實時統計區塊鏈黑客
- 區塊鏈安全思考區塊鏈
- 區塊鏈生態被駭客攻擊的實時統計區塊鏈
- 縱觀5起大規模軟體供應鏈攻擊事件 安全盲區在這幾方面事件
- 區塊鏈合約安全系列(二):如何認識及預防公鏈合約中的重入攻擊漏洞區塊鏈
- 區塊鏈系列6-區塊鏈安全與大資料區塊鏈大資料
- 區塊鏈鼻祖比特幣之6:詳解比特幣的密碼攻擊與分散式雙花攻擊區塊鏈比特幣密碼分散式
- 區塊鏈應用場景解析區塊鏈
- 區塊鏈(Block Chain)結構解析區塊鏈BloCAI
- 區塊鏈關鍵字的解析區塊鏈
- 區塊鏈有哪些特徵,幣信打造安全好用的區塊鏈區塊鏈特徵
- 【漏洞分析】Vestra DAO 攻擊事件:這個質押專案它取款不核銷呀事件
- 【網路安全知識】DDOS攻擊和CC攻擊有什麼區別?
- 區塊鏈技術公司談以色用區塊鏈改善網路安全區塊鏈
- 最近收藏的區塊鏈課程(定期更新中),全方位解讀區塊鏈,助力論壇『區塊鏈安全』區塊鏈
- 成都鏈安CEO楊霞:打通區塊鏈生態安全資訊屏障,守護區塊鏈生態安全區塊鏈
- Hundred Finance 攻擊事件分析NaN事件
- 區塊鏈100講:區塊鏈為什麼叫“區塊”“鏈”?區塊鏈
- 再現在野0day攻擊--BITTER APT攻擊事件APT事件
- 區塊鏈雲盤的資料安全區塊鏈
- 構建安全程式碼 防止供應鏈攻擊
- Red Pulse俞戴龍:區塊鏈專案方面臨的平臺攻擊和防範區塊鏈
- “區塊鏈+司法” 讓“鏈上法院”更安全、可信、高效區塊鏈
- 區塊鏈知識,區塊鏈簡史區塊鏈
- 區塊鏈系列1-區塊鏈概述區塊鏈
- 區塊鏈 2.0:房地產區塊鏈(四)區塊鏈
- 前端攻擊 XSS 深入解析前端
- 三家機構聯合開發可抵禦量子計算攻擊的區塊鏈區塊鏈
- 騰訊安全領御區塊鏈亮相2020全球區塊鏈創新發展大會區塊鏈
- 區塊鏈區塊鏈