作者:LoRexxar’@知道創宇404區塊鏈安全研究團隊
時間:2018年8月22日
本系列上一篇:《以太坊合約審計 CheckList 之“以太坊智能合約規範問題”影響分析報告》
一、 簡介
在知道創宇404區塊鏈安全研究團隊整理輸出的《知道創宇以太坊合約審計CheckList》中,把“條件競爭問題”、“循環DoS問題”等問題統一歸類為“以太坊智能合約設計缺陷問題”。
“昊天塔(HaoTian)”是知道創宇404區塊鏈安全研究團隊獨立開發的用於監控、掃描、分析、審計區塊鏈智能合約安全自動化平台。我們利用該平台針對上述提到的《知道創宇以太坊合約審計CheckList》中“以太坊智能合約設計缺陷”類問題在全網公開的智能合約代碼做了掃描分析。詳見下文:
二、漏洞詳情
1、條件競爭
2016年11月29號,Mikhail Vladimirov和Dmitry Khovratovich公開了一篇《ERC20 API: An Attack Vector on Approve/TransferFrom Methods》,在文章中提到了一個在ERC20標準中存在的隱患問題,條件競爭。
這裡舉一個approve函數中會出現的比較典型的例子,approve一般用於授權,比如授權別人可以取走自己的多少代幣,整個流程是這樣的:
- 用戶A授權用戶B 100代幣的額度
- 用戶A覺得100代幣的額度太高了,再次調用approve試圖把額度改為50
- 用戶B在待交易處(打包前)看到了這筆交易
- 用戶B構造一筆提取100代幣的交易,通過條件競爭將這筆交易打包到了修改額度之前,成功提取了100代幣
- 用戶B發起了第二次交易,提取50代幣,用戶B成功擁有了150代幣
想要理解上面這個條件競爭的原理,首先我們得對以太坊的打包交易邏輯有基礎認識。
https://medium.com/blockchannel/life-cycle-of-an-ethereum-transaction-e5c66bae0f6e
簡單來說就是
- 只有當交易被打包進區塊時,他才是不可更改的
- 區塊會優先打包gasprice更高的交易
所以當用戶B在待打包處看到修改的交易時,可以通過構造更高gasprice的交易來競爭,將這筆交易打包到修改交易之前,就產生了問題。
以下代碼就存在條件競爭的問題
function approve(address _spender, uint256 _value) public returns (bool success){
allowance[msg.sender][_spender] = _value;
return true
2、循環DoS問題
在以太坊代碼中,循環是一種很常見的結構,但由於以太坊智能合約的特殊性,在循環也有很多需要特別注意的點,
存在潛在的合約問題與安全隱患。
1) 循環消耗問題
在以太坊中,每一筆交易都會消耗一定的gas,而交易的複雜度越高,則該交易的gasprice越高。而在區塊鏈上,每個區塊又有最大gas消耗值限制,且在礦工最優化收益方案中,如果一個交易的gas消耗過大,就會傾向性把這個交易排除在區塊外,從而導致交易失敗。
所以,對於合約內的循環次數不宜過大,在循環中的代碼不宜過於複雜。
struct Payee {
address addr;
uint256 value;
}
Payee payees[];
uint256 nextPayeeIndex;
function payOut() {
uint256 i = nextPayeeIndex;
while (i < payees.length && msg.gas > 200000) {
payees[i].addr.send(payees[i].value);
i++;
}
nextPayeeIndex = i;
}
如果上述代碼地址列表過長,就有可能導致交易失敗。
2018年7月23日,Seebug Paper發表的《首個區塊鏈 token 的自動化薅羊毛攻擊分析》中攻擊合約就提到了這種gas優化方式。
2) 循環安全問題
在以太坊中,應該盡量避免循環次數受到用戶控制,攻擊者可能會使用過大的循環來完成Dos攻擊。
function distribute(address[] addresses) onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
// transfer code
}
}
當攻擊者通過不斷添加address列表長度,來迫使該函數執行循環次數過多,導致合約無法正常維護,函數無法執行。
2016年,GovernMental合約代幣被爆出惡意攻擊,導致地址列表過長無法執行,超過1100 ETH被困在了合約中。
三、漏洞影響範圍
使用Haotian平台智能合約審計功能可以準確掃描到該類型問題。
Life Cycle of an Ethereum Transaction
https://medium.com/blockchannel/life-cycle-of-an-ethereum-transaction-e5c66bae0f6e
首個區塊鏈 token 的自動化薅羊毛攻擊分析
https://paper.seebug.org/646/
GovernMental’s 1100 ETH :
https://www.reddit.com/r/ethereum/comments/4ghzhv/governmentals_1100_eth_jackpot_payout_is_stuck/