一行代碼導致幣價歸零!BEC美密智能合約漏洞復盤

一行代碼導致幣價歸零!BEC美密智能合約漏洞復盤

來自專欄 DApps(ETH/EOS)開發者社區

就在4月22日中午,BEC美蜜被黑客攻擊,天量BEC從兩個地址轉出,引發了市場拋售潮。當日,BEC的價值幾乎歸零。

看得懂智能合約交易的用戶可以直接看這條交易記錄

Transaction 0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f?

etherscan.io

如圖所示,黑客調用了BEC美蜜合約的batchTransfer方法,這個方法有兩個參數,一個是接受BEC的地址列表,另外一個是需要轉出多少BEC,正常情況下,合約的開發者是會校驗地址餘額中是否有足夠的BEC可以轉出,並且轉出的量必須是正整數,但是BEC的代碼存在驚天bug,請看下圖

大家請注意第 257 行,cnt 和 _value 的計算結果生成了局部變數。第二個參數,即 _value,,可以是一個任意的 256 位元組整數,就比如是:0x8000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000(63 個 0)。

通過將兩個 _receivers 注入到 batchTranser(),再加上這個極其大的 _value,我們就能使得量溢出,將其 amount 的量變成 0。通過將量回歸到 0,攻擊者就可以繞過 258 行到 259 行的合理性檢測,使得 261 行的差值變得不再相關。

最後,出現了一個非常有趣的結果:你們可以看 262 行到 265 行,兩個 receriver 的餘額上增加了超級大的 _value,而這一切都不會花費錢包里哪怕一毛錢!

同樣受影響的還有SMT

在執行轉賬操作的proxyTransfer()函數中,_fee與_value參數(分別代表轉賬費用和轉賬金額)可以由攻擊者控制,如果二者相加數額為0,第206行的校驗機制就不再生效。根據proxyTransfer()函數中定義的數據類型,_fee與_value參數都為uint256類型,如果設置過大數值導致二者相加後整型溢出,轉帳方實際損失的費用就為0,並且能夠收取巨額資金。

此事又引發了幣圈集體大跳水,有些媒體身體撰文稱此錯誤實習生都不會犯哈哈

我覺得有點「過分」了,不過作為開發者,我們的確應該掌握方法,規避這類問題:

SafeMath

SafeMath to protect from overflows - Ethereum Developers?

ethereumdev.io

上面遇到的兩個問題,其實都是數據溢出導致變數值異常歸0導致的,那麼我們在寫智能合約代碼的時候就應該從根本上杜絕變數溢出的問題SafeMath to protect from overflows - Ethereum Developers上面遇到的兩個問題,其實都是數據溢出導致變數值異常歸0導致的,那麼我們在寫智能合約代碼的時候就應該從根本上杜絕變數溢出的問題

這裡給大家推薦一個庫【SafeMath】

代碼其實很簡單,每個操作都會檢查數據是否異常,這樣就可以保證我們的變數結果可預期。不會出現類似溢出的問題。

我們看到BEC的代碼裡面其實也有SafeMath,不過杯具的是,他定義了一個臨時變數,這個臨時變數的計算並沒有使用SafeMath。

舉個栗子:CET Token

哈哈哈,這方面參考CET Token的轉賬邏輯,所有的運算操作使用SafeMath來操作,宇宙無敵超級安全。各位學會了吧。

支持CET的手留余香

CET 捐贈地址:0x4dfa620f331042a51d3271b401274e55eeaab6b8

推薦閱讀:

MobIM僅為開發者提供即時通訊的消息通道服務
Pycon 2016 小記
唐才林:DAP為開發者供性價比最優的移動變現方案
無需從 App Store 下架,App 便能轉至其他開發者賬號→詳細圖解&附蘋果官方 Q&A

TAG:開發者 | 互聯網 | 智能合約 |