美链BEC合约漏洞技术分析
這兩天幣圈鏈圈被美鏈BEC智能合約的漏洞導(dǎo)致代幣價(jià)值幾乎歸零的事件刷遍朋友圈。這篇文章就來(lái)分析下BEC智能合約的漏洞
漏洞攻擊交易
我們先來(lái)還原下攻擊交易,這個(gè)交易可以在這個(gè)鏈接查詢(xún)到。
我截圖給大家看一下:
攻擊者向兩個(gè)賬號(hào)轉(zhuǎn)移57896044618…000.792003956564819968個(gè)BEC,相當(dāng)于BEC憑空進(jìn)行了一個(gè)巨大的增發(fā),幾乎導(dǎo)致BEC價(jià)格瞬間歸零。
下面我們來(lái)分析下這個(gè)攻擊過(guò)程。
合約漏洞分析
我們先來(lái)看看BEC智能合約的代碼,
BEC在合約中加入一個(gè)批量轉(zhuǎn)賬的函數(shù),它的實(shí)現(xiàn)如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 | function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { uint cnt = _receivers.length; uint256 amount = uint256(cnt) * _value; require(cnt > 0 && cnt <= 20); require(_value > 0 && balances[msg.sender] >= amount); balances[msg.sender] = balances[msg.sender].sub(amount); for (uint i = 0; i < cnt; i++) { balances[_receivers[i]] = balances[_receivers[i]].add(_value); Transfer(msg.sender, _receivers[i], _value); } return true; |
這個(gè)函數(shù)的作用是,調(diào)用者傳入若干個(gè)地址和轉(zhuǎn)賬金額,在經(jīng)過(guò)一些條件檢查之后,對(duì)msg.sender的余額進(jìn)行減操作,對(duì)每一個(gè)對(duì)每一個(gè)傳入的地址進(jìn)行加操作,以實(shí)現(xiàn)BEC的轉(zhuǎn)移。
問(wèn)題出在?uint256 amount = uint256(cnt) * _value;?這句代碼,當(dāng)傳入值_value過(guò)大時(shí)(接近uint256的取值范圍的最大值),uint256 amount = uint256(cnt) * _value計(jì)算時(shí)會(huì)發(fā)生溢出,導(dǎo)致amount實(shí)際的值是一個(gè)非常小的數(shù)(此時(shí)amount不再是cnt * _value的實(shí)際值),amount很小,也使得后面對(duì)調(diào)用者余額校驗(yàn)可正常通過(guò)(即require(_value > 0 && balances[msg.sender] >= amount)語(yǔ)句通過(guò))。
我們來(lái)結(jié)合實(shí)際攻擊交易使用的參數(shù)來(lái)分析一下:
batchTransfer的參數(shù)_value值為16進(jìn)制的800000000000000000000...,參數(shù)_receivers數(shù)組的大小為2,相乘之后剛好可超過(guò)uint256所能表示的整數(shù)大小上限,引發(fā)溢出問(wèn)題amount實(shí)際的值為0,后面的轉(zhuǎn)賬操作實(shí)際上msg.sender的余額減0, 而對(duì)兩個(gè)賬號(hào)進(jìn)行了加16進(jìn)制的800000000000000000000...,最終的結(jié)果是相當(dāng)于增發(fā)了2 * 16進(jìn)制的800000000000000000000...。
實(shí)際上對(duì)于這種整數(shù)溢出漏洞,最簡(jiǎn)單的方法是采用 SafeMath 數(shù)學(xué)計(jì)算庫(kù)來(lái)避免。有趣的是BEC智能合約代碼中,其實(shí)其他的都使用了SafeMath, 而關(guān)鍵的uint256 amount = uint256(cnt) * _value卻沒(méi)有使用。
心痛程序員,也心痛韭菜。這句代碼改為uint256 amount = _value.mul(uint256(cnt));就可以防止溢出問(wèn)題
所以在做加減乘除的時(shí)候請(qǐng)記得一定使用:SafeMath,代碼在這里
https://learnblockchain.cn/2018/04/25/bec-overflow/#more
總結(jié)
以上是生活随笔為你收集整理的美链BEC合约漏洞技术分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何使用区块链技术进行项目开发
- 下一篇: 如何设计区块链项目的通证(token)模