乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

漏洞 區塊鏈大本營 2018-07-24

一文看懂溢出性漏洞所有類型。

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

4月發生的BEC事件以及SMT事件已經沉澱一段時間了,具體的情況也被多方媒體所報道,相關的漏洞根源問題也有很多大神團隊的分析和指正。

近日,有安全團隊將各種已經發生或可能發生的類似溢出漏洞原理進行整理,再次將全方位的原理分析與大家分享,讓大家對溢出型漏洞有全面的認識。

事件回顧

2018年4月22日,黑客對BEC智能合約發起攻擊,憑空取出

57,896,044,618,658,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000.792003956564819968 

個BEC代幣並在市場上進行拋售,BEC隨即急劇貶值,價值幾乎為0,該市場瞬間土崩瓦解。

2018年4月25日,SMT項目方發現其交易存在異常,黑客利用其函數漏洞創造了65,133,050,195,990,400,000,000,000,000,000,000,000,000,000,000,000,000,000,000

+

50,659,039,041,325,800,000,000,000,000,000,000,000,000,000,000,000,000,000,000

的SMT幣,火幣Pro隨即暫停了所有幣種的充值提取業務。

讓我們一起以沉痛的心情緬懷以上一夜歸零的代幣。

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

僅僅在BEC事件過去後的12小時內,就有多達12個項目的智能合約存在類似的整數溢出類型的漏洞,黑客可以利用這一漏洞轉賬“無中生有”的巨大數量代幣,也就是我們所說的“增發”。

代幣增發為什麼就會貶值

人們常說“物以稀為貴”,意思是事物因稀少而且有益,從而顯得珍貴。

黃金被選為最早時期全世界公認的貨幣的原因就是因為它稀缺,地球上儲量有限,易分割,屬性穩定等特點。

中國人首先發明瞭“交子”,來代替不便交易的黃金。

所以就出現了金本位的概念,很多國家發行自己貨幣的時候都是按照其黃金儲量來發行,並不是想發多少就發多少。

試想一下,如果憑空出現了一顆黃金做的大隕石,撞擊地球后黃金撒了一地,黃金還會值錢嗎?

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

所以當一個代幣的數量在有了額定發行總量之後,突然肆意的增加,必然會導致代幣的貶值,甚至失去在市場上流通的意義。這就是“代幣增發”的不良後果。

整數溢出漏洞分析

前面提到,黑客是利用整數溢出漏洞繞過了轉賬數額的相關規則,進而增發代幣。

那什麼是整數溢出呢?為什麼能用整數溢出來實現增發來秀一波空手套白狼的操作?

我來舉個例子:

比如有一個國家的人不會複雜的數學運算,只會從0數到9,每次數到9之後又從0開始數,最後以數到的數作為結果。大家都這樣平安無事的生活著,但有一天,有一個從別的國家來的小黑,他發現了這個問題,於是他去金庫拿金錠,拿出來的個數超過了9個,於是金庫管理員幫他數,數到9之後又從0開始了,最後結算髮現他取出來的結果是0個金錠,但實際上他已經把金庫裡的金錠幾乎都取完了。

黑客利用類似的機制憑空向一個賬戶中轉賬了超級大數額的代幣,而合約中的邏輯只要求他花費很小的代價。

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

我們對過往代幣增發事件漏洞類型進行整理,概括出整型溢出類型漏洞的全面分析。

以太坊虛擬機(EVM)為整數指定固定大小的數據類型。這意味著一個整型變量只能有一定範圍的數字表示。例如,一個 uint8 ,只能存儲在範圍 [0,255] 的數字。試圖存儲 256 到一個 uint8 將變成 0。不加註意的話,只要沒有檢查用戶輸入又執行計算,導致數字超出存儲它們的數據類型允許的範圍,Solidity 中的變量就可以被用來組織攻擊。

整數溢出的類型包括乘法溢出,加法溢出,減法溢出三種。

在對BEC事件進行分析後,發現可將其漏洞歸類於乘法溢出,原理如下:

乘法溢出

•  案例(CVE-2018-10299)

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

上述合約代碼中,存在漏洞的代碼為:

uint256 amount = uint256(cnt) * _value;,

計算轉出總額度amount未使用SafeMath也未對溢出進行檢查,直接將轉賬地址數量乘以轉賬額度,如果輸入極大的_value,那麼amount計算結果就可能產生溢出,導致代幣增發。

在Remix-ide中測試如下:

1、部署合約;

2、調用batchTransfer函數,向batchTransfer函數傳入地址數組

["0xb4D30Cac5124b46C2Df0CF3e3e1Be05f42119033","0x0e823fFE018727585EaF5Bc769Fa80472F76C3d7"],

以及

_value"0x8000000000000000000000000000000000000000000000000000000000000000"

即2*255,

使得amount=2\*255 * 2,超出uint256類型的範圍[0,2**256-1],溢出為0,發送者賬戶餘額不減少,並且,本例中,發送者的代幣可以為零,實現"無中生有"。

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

3、查看餘額:

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

而針對SMT事件進行分析後,發現其漏洞屬於加法溢出類型,其原理如下:

加法溢出

•   案例

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

上述合約代碼中,mintToken函數的功能是owner向指定賬戶增發mintedAmount數量的代幣,但是在對balanceOf[target]與totalSupply進行加法操作未做溢出檢查,導致其可能存在溢出,並且,通過溢出,惡意owner可以任意增減target賬戶的餘額,或者增發實際遠遠超過totalSupply的代幣。

在Remix-ide中測試如下:

1、部署合約;

2、向target預先轉一部分代幣,模擬目標賬戶中已有的代幣:調用transfer函數,傳入target地址:

0x14723a09acff6d2a60dcdf7aa4aff308fddc160c,

以及轉賬額度,比如:

2000000000000000000

(2 * 10**uint256(decimals));

3、如果owner想控制target的餘額減半,那麼,他只需要向target增發

2*256-balanceOf[target]+10\*18=0xfffffffffffffffffffffffffffffffffffffffffffffffff21f494c589c0000,

現在調用mintToken函數,向target地址轉入上述數量的代幣:

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

4、查詢target餘額:

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

另外還有減法溢出的操作,雖然未出現相關的漏洞攻擊事件,我們也提供了相關的原理分析。

減法溢出

•   案例

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

上述合約代碼中,distribute函數的功能是從owner賬戶向指定的地址列表轉入2000 * 10**8代幣,但是在對balances[owner]的計算中未使用SafeMath,也未判斷owner賬戶是否有足夠的代幣,當轉出代幣總量大於owner賬戶餘額的時候,balances[owner]產生減法溢出,變成一個極大值。

在Remix-ide中測試如下:

1、部署合約

2、調用distribute函數,傳入地址數組:

["0x14723a09acff6d2a60dcdf7aa4aff308fddc160c","0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"]

owner分別向這兩個地址發送2000 * 10**8代幣,超過owner餘額,balances[owner]產生減法溢出;

3、查詢owner賬戶餘額,等於2**256-2000*10**8:


乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

黑客雖然無孔不入,但鏈安科技團隊對具有此類漏洞的合約進行綜合性調研後,提出了“亡羊補牢”的修復措施:

漏洞修復

OpenZeppelin提供了一套很好的SafeMath庫,使用SafeMath庫函數能夠有效避免溢出漏洞,SafeMath庫源碼如下:

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

乾貨:史上殺傷力最大的溢出型漏洞到底是什麼?

子曰:吾日三省吾身

我們從這些慘痛的教訓中能總結出:

1. 基於ERC20協議編寫的這些智能合約給予開發者的權力過大了,這些溢出問題本應該放在底層檢測。

    2. 編寫合約的開發者沒有以嚴謹敬業的精神去遵守開發規範,使用SafeMath去做相關功能,或者進行溢出測試,在這裡提出批評。

    3. 沒有嚴謹的邏輯,單單憑藉創造力並不是都能出成果,還是要穩中求勝,能使用庫就使用庫。

    參考資料:

    [1]: http://bc.jrj.com.cn/2018/04/26132824455908.shtml 

    [2]: https://zhuanlan.zhihu.com/p/36116810

    [3]: https://baike.baidu.com/item/%E7%89%A9%E4%BB%A5%E7%A8%80%E4%B8%BA%E8%B4%B5

    [4]: http://www.woshipm.com/blockchain/945232.html