智能合約安全——溢出漏洞

算術(shù)溢出(arithmetic overflow)或簡稱為溢出(overflow)分為兩種:上溢和下溢。所謂上溢是指在運行單項數(shù)值計算時,當(dāng)計算產(chǎn)生出來的結(jié)果非常大月培,大于寄存器或存儲器所能存儲或表示的能力限制就會產(chǎn)生上溢;

而下溢就是當(dāng)計算產(chǎn)生出來的結(jié)果非常小,小于寄存器或存儲器所能存儲或表示的能力限制就會產(chǎn)生下溢瞭稼。舉個例子:

在solidity 中,uint8 所能表示的范圍是0 - 255這256個數(shù)腻惠。

如果一個合約有溢出漏洞的話會導(dǎo)致計算的實際結(jié)果和預(yù)期的結(jié)果產(chǎn)生非常大的差異环肘,這樣輕則會影響合約的正常邏輯,重則會導(dǎo)致合約中的資金丟失妖枚。但是溢出漏洞是存在版本限制的廷臼,在Solidity < 0.8 時溢出不會報錯,當(dāng) Solidity >= 0.8 時溢出會報錯绝页。所以當(dāng)我們看到 0.8 版本以下的合約時荠商,就要注意這個合約可能出現(xiàn)溢出問題。

漏洞示例

有了以上的講解续誉,相信大家對溢出漏洞都有一定的了解莱没,下面我們來結(jié)合合約代碼來深入了解溢出漏洞:

漏洞分析

TimeLock 合約充當(dāng)了時間保險庫,用戶可以將代幣通過deposit 函數(shù)存入該合約并鎖定酷鸦,且至少一周內(nèi)不能提現(xiàn)饰躲。當(dāng)然用戶也可以通過 increaseLockTime 函數(shù)來增加存儲時間,用戶在設(shè)定的存儲期限到期前是無法提取 TimeLock 合約中鎖定的代幣的臼隔。

首先我們發(fā)現(xiàn)這個合約中的increaseLockTime 函數(shù)和 deposit 函數(shù)具有運算功能嘹裂,并且合約支持的版本是:0.7.6 向上兼容,所以這個合約在算數(shù)溢出時是不會報錯的摔握,那么我們就可以判斷這個合約是可能存在溢出漏洞的寄狼,這里可利用的函數(shù)有兩個,一個是increaseLockTime 函數(shù)氨淌,一個是 deposit 函數(shù)泊愧。我們先來分析這兩個函數(shù)內(nèi)參數(shù)可影響的范圍再來決定如何發(fā)起攻擊:

1. deposit 函數(shù)存在兩個運算操作,第一個是影響用戶存入的余額 balances 的盛正,這里傳入的參數(shù)是可控的所以這里會有溢出的風(fēng)險删咱,另一個是影響用戶的鎖定時間 lockTime 的,但是這里的運算邏輯是每次調(diào)用 deposit 存入代幣時會給 lockTime 增加一周豪筝,由于這里的參數(shù)不可控所以這個運算不會存在溢出風(fēng)險痰滋。

2. increaseLockTime 函數(shù)是根據(jù)用戶傳入的 _secondsToIncrease 參數(shù)來進行運算從而改變用戶的存入代幣的鎖定時間的摘能,由于這里的 _secondsToIncrease 參數(shù)是可控的,所以這里有溢出的風(fēng)險即寡。

綜上所述徊哑,我們發(fā)現(xiàn)可利用的參數(shù)有兩個,分別為deposit 函數(shù)中的 balances 參數(shù)?increaseLockTime 函數(shù)中的 _secondsToIncrease 參數(shù)聪富。

我們先來看balances?參數(shù)莺丑,如果要讓這個參數(shù)溢出我們需要有足夠的資金存入才可以(需要 2^256 個代幣存入才能導(dǎo)致 balances 溢出并歸零),如果要利用這個溢出漏洞的話墩蔓,我們把大量資金存入自己的賬戶并讓自己的賬戶的 balances 溢出并歸零從而清空自己的資產(chǎn)梢莽,我覺得在坐的各位沒有人會這么做吧。所以這個參數(shù)可以認(rèn)為在攻擊者的角度是不可用的奸披。

我們再看_secondsToIncrease?參數(shù)昏名,這個參數(shù)是我們調(diào)用 increaseLockTime 函數(shù)來增加存儲時間時傳入的,這個參數(shù)可以決定我們什么時候可以將自己存入并鎖定的代幣從合約中取出阵面,我們可以看到這個參數(shù)在傳入之后是直接與賬戶對應(yīng)的鎖定時間 lockTime 進行運算的轻局,如果我們操縱 _secondsToIncrease 參數(shù)讓他在與 lockTime 進行運算后得到的結(jié)果產(chǎn)生溢出并歸零的話這樣我們是不是就可以在存儲日期到期前將自己賬戶中的余額取出了呢?

攻擊合約

下面我們來看看攻擊合約:

這里我們將使用Attack 攻擊合約先存入以太后利用合約的溢出漏洞在存儲未到期的情況下提取我們在剛剛 TimeLock 合約中存入并鎖定的以太:

1. 首先部署 TimeLock 合約样刷;

2. 再部署 Attack 合約并在構(gòu)造函數(shù)中傳入 TimeLock 合約的地址仑扑;

3. 調(diào)用 Attack.attack 函數(shù),Attack.attack 又調(diào)用 TimeLock.deposit 函數(shù)向 TimeLock 合約中存入一個以太(此時這枚以太將被 TimeLock 鎖定一周的時間)置鼻,之后 Attack.attack 又調(diào)用 TimeLock.increaseLockTime 函數(shù)并傳入 uint 類型可表示的最大值(2^256 - 1)加 1 再減去當(dāng)前 TimeLock 合約中記錄的鎖定時間镇饮。此時 TimeLock.increaseLockTime 函數(shù)中的 lockTime 的計算結(jié)果為 2^256 這個值,在 uint256 類型中 2^256 這個數(shù)存在上溢所以計算結(jié)果為 2^256 = 0 此時我們剛剛存入 TimeLock 合約中的一個以太的鎖定時間就變?yōu)?0 箕母;

4. 這時 Attack.attack 再調(diào)用 TimeLock. withdraw 函數(shù)將成功通過 block.timestamp > lockTime[msg.sender] 這項檢查讓我們能夠在存儲時間未到期的情況下成功提前取出我們剛剛在 TimeLock 合約中存入并鎖定的那個以太储藐。

下面是攻擊流程圖:


修復(fù)建議

接下來,我們來說說如何修復(fù)這些漏洞嘶是?很明顯地钙勃,防止數(shù)據(jù)數(shù)值溢出就能修復(fù)這些漏洞了,那么我就給大家一些防止數(shù)據(jù)數(shù)值溢出的建議吧聂喇!

1. 使用Solidity 0.8 及以上版本來開發(fā)合約辖源,這里還有一點:需要慎用unchecked,因為在unchecked 修飾的代碼塊里面是不會對參數(shù)進行溢出檢查的授帕;

2. 使用SafeMath方法庫同木,SafeMath只提供簡單的四則運算方法浮梢,但是在計算溢出時跛十,它會拋出錯誤;

除此之外秕硝,作為一名合約編寫者芥映,還需要慎用變量類型強制轉(zhuǎn)換,因為不同的類型,其數(shù)值范圍是不同的奈偏,類型強制轉(zhuǎn)換有可能導(dǎo)致數(shù)值溢出坞嘀。

如果想了解更多的智能合約和區(qū)塊鏈知識,歡迎到區(qū)塊鏈交流社區(qū)CHAINPIP社區(qū)惊来,一起交流學(xué)習(xí)~

社區(qū)地址:https://www.chainpip.com/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丽涩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子裁蚁,更是在濱河造成了極大的恐慌矢渊,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枉证,死亡現(xiàn)場離奇詭異矮男,居然都是意外死亡,警方通過查閱死者的電腦和手機室谚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門毡鉴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秒赤,你說我怎么就攤上這事猪瞬。” “怎么了倒脓?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵撑螺,是天一觀的道長。 經(jīng)常有香客問我崎弃,道長甘晤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任饲做,我火速辦了婚禮线婚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盆均。我一直安慰自己塞弊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布泪姨。 她就那樣靜靜地躺著游沿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肮砾。 梳的紋絲不亂的頭發(fā)上诀黍,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音仗处,去河邊找鬼眯勾。 笑死枣宫,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吃环。 我是一名探鬼主播也颤,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼郁轻!你這毒婦竟也來了翅娶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤好唯,失蹤者是張志新(化名)和其女友劉穎故觅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渠啊,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡输吏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了替蛉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贯溅。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖躲查,靈堂內(nèi)的尸體忽然破棺而出它浅,到底是詐尸還是另有隱情,我是刑警寧澤镣煮,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布姐霍,位于F島的核電站,受9級特大地震影響典唇,放射性物質(zhì)發(fā)生泄漏镊折。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一介衔、第九天 我趴在偏房一處隱蔽的房頂上張望恨胚。 院中可真熱鬧,春花似錦炎咖、人聲如沸赃泡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽升熊。三九已至,卻和暖如春绸栅,著一層夾襖步出監(jiān)牢的瞬間级野,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工阴幌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勺阐,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓矛双,卻偏偏與公主長得像渊抽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子议忽,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容