區塊鏈技術 | 應對黑客的進攻——淺談數字貨幣安全問題
摘要:隨著智能合約飛速發展,越來越多的項目基於以太坊發行token,鏈上資產的類別和規模呈指數級增長,「虛擬世界」中的數字資產也點燃了黑客們的「熱情」。以太坊區塊鏈被認為是區塊鏈的2.0時代,各種各樣新的數字資產都基於以太坊發行早期代幣甚至實現部分功能,雖然國外區塊鏈社區甚至認為以太坊體量變得太大,已經不可輕易戰勝,但以太坊也是數字貨幣歷史上產生最多安全問題的幣種,從2016年的The DAO事件,到最近的BEC,EDU,SMT的安全漏洞,以太坊的智能合約可以說充滿安全漏洞。大多數的代幣都在自己主網上線前使用以太坊代幣,作為投資者,為了自身資產的安全著想,熟悉智能合約的漏洞概念變得尤為重要。
【黑客利刃砍出的ETH和ETC】
The DAO作為世界上最大的眾籌項目,一度被寄予了厚望,所謂「成也蕭何,敗也蕭何」,智能合約一度被捧上了天,但在這次The DAO事件當中,其遞歸調用(recursive calling)的漏洞卻成為了黑客入侵的大門。此後出現「黑客」現身談攻擊合法性的戲幕,更是讓人大跌眼鏡,這第一次引出了智能合約代碼監管的問題。
2016年6月17日發生了在區塊鏈歷史上留下沉重一筆的攻擊事件。由於其編寫的智能合約存在著重大缺陷,區塊鏈業界最大的眾籌項目TheDAO(被攻擊前 擁有1億美元左右資產)遭到攻擊,導致300多萬以太幣資產被分離出TheDAO 資產池TheDAO編寫的智能合約中有一個splitDAO函數,攻擊者通過此函數中的漏 洞重複利用自己的DAO資產來不斷從TheDAO項目的資產池中分離DAO資產給自己。
攻擊者組合了2個漏洞攻擊,攻擊者利用的第一個漏洞是遞歸調用splitDAO函數,也就是說splitDAO函數被第一次合法調用後會非法的再次調用自己,然後不斷重複這 個自己非法調用自己的過程。這樣的遞歸調用可以使得攻擊者的DAO資產在被清零之 前,數十次的從TheDAO的資產池裡重複分離出來理應被清零的攻擊者的DAO資產。 攻擊者利用的第二個漏洞是DAO資產分離後避免從heDAO資產池中銷毀。正常情況 下,攻擊者的DAO資產被分離後,TheDAO資產池會銷毀這部分DAO資產。但是攻擊 者在遞歸調用結束前把自己的DAO資產轉移到了其他賬戶,這樣就可以避免這部分 DAO資產被銷毀。在利用第一個漏洞進行攻擊完後把安全轉移走的DAO資產再轉回原 賬戶。這樣攻擊者做到了只用2個同樣的賬戶和同樣DAO資產進行了200多次攻擊。
被攻擊後,Vitalik個人支持分叉的提議,也支持軟分叉的開發工作,支持礦工升級客戶端來進行分叉。然而Vitalik也認識到大家對這個提議有激烈的爭論,無論哪一 方的觀點都有強力的反對。因為分叉不需要回滾交易,不會對用戶和交易所造成不便,這更使Vitalik傾向於採取行動的一方。也有許多人,包括在基金會內部,傾向於另外一方反對分叉。Vitalik不會阻止也不會反對另一方在公開場合宣傳他們的觀 點,甚至是遊說礦工來抵制這個分叉。在這件事情上Vitalik會堅決的不與任何站在 相對他的另一方的人爭辯。
簡而言之,他們所做的是更改以太坊區塊鏈來修正DAO,但只有當大部分運行以太坊區塊鏈網路的計算機同意,軟體才能進行更新,擺脫掉漏洞,就好像攻擊從來沒有發生過。這一過程被稱為硬分叉(hard fork),從此以太坊創造了一個平行世界,現在的以太坊其實是分叉出來的「以太坊」並在一年後狂飆突進的漲到了幾百美元,而原來不願意分叉的包含The DAO漏洞的以太坊則成了以太坊經典(ETC)。這一決定引發了強烈的反應,一年後仍然存在爭議,無論是在以太坊社區還是比特幣用戶都堅持區塊鏈的歷史不能被篡改,有些比特幣用戶認為硬分叉在某些方面違反了最基本的價值觀。
【Binance黑客VIA事件】
2018年在 3 月 7 日深夜(北京時間),有不少用戶發現自己幣安賬戶中持有的各種各樣的代幣、數字貨幣被市價即時幣幣交易成了 BTC。據網友反饋,被盜的賬號不在少數,不少人還以為是幣安系統錯誤導致的,還試圖從幣安客服那裡得到解釋。當他們還沒有反應過來的時候,黑客已經開始了他們有組織、有預謀的行動。
黑客啟動了所有盜竊的賬戶的買賣引擎,買賣規則就是賣掉所有山寨幣,用市場價全倉購買VIA。而恰好黑客手裡持有大量VIA,這樣就相當於高價購買了黑客手裡的VIA。於是,VIA的K線出現了驚人的振幅:2分鐘內爆拉了110倍。從交易量和拉昇價格來看,有大約1000個BTC的買單,把VIA的價格從0.000225btc拉到0.025,價格上漲大約110倍。
但是黑客的行動觸發了幣安的預警系統,黑客沒能直接提出高價賣出所得的比特幣。於是他們轉而以超低價格爆砸比特幣現貨的訂單列表,引起其他交易所期貨價格的連鎖反應。於是黑客預先埋伏的巨量空單獲得巨大收益。黑客的攻擊,已經去中心化了。
【數據溢出】
2018年4月22日中午(北京時間),BEC美蜜遭遇黑客的毀滅性攻擊,天量BEC從兩個地址轉出,引發了市場拋售潮。當日,BEC的價值幾乎歸零。
以太坊區塊數據顯示,黑客利用以太坊 ERC-20 智能合約中數據溢出的漏洞,在攻擊中憑空轉出了57,896,044,618,658,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000.792003956564819968 個 BEC。轉出數量遠遠超過了BEC的發行總數70億枚,市場頓時陷入瘋狂拋售,BEC近65億元人民幣的市值也幾乎瞬間歸零。
而攻擊成功的原因,是因為BEC的一段代碼忘記使用safeMath方法,導致系統產生了整數溢出漏洞。據PeckShield 團隊今日凌晨發布的安全報告,黑客利用 in-the-wild(一種從代碼中抓取漏洞的手段)方法,從BEC的程序中抓取到了漏洞,並發動了攻擊。利用這個漏洞,黑客可以通過轉賬的手段生成合約中不存在的代幣, 並將這些無中生有的數字貨幣轉入正常賬戶。這些憑空產生的代幣在使用上與真實代幣沒有差別。
4月25日,SMT爆發了類似的漏洞問題。SMT的智能合約中proxyTransfer函數存在一個經典的整數溢出問題。_fee 和 _value_ 這兩個輸入參數都能被攻擊者控制,如果 _fee + _value 的結果正好為 0(也就是溢出的情況),第206行的檢查將會失效。
這意味著攻擊者不需要任何Token,就可以向一個地址轉入大量的Token(第214行);同時根據第217行的代碼,相當數量的手續費也將發送給 msg.sender。
要理解數據溢出的漏洞,首先要理解任何類型的數值都已自己的表達範圍,計算機中的整數分為兩類:不帶符號位的整數(unsigned integer,也稱為無符號整數),此類整數一定是正整數;帶符號位的整數(signed integer),此類整數可以表示正整數,又可以表示負整數。無符號整數常用於表示地址、索引等正整數,它們可以是8位、16位、32位、64位甚至更多。8個二進位表示的正整數其取值範圍是0~255( -1),16位二進位位表示的正整數其取值範圍是0~65535( -1),32位二進位位表示的正整數其取值範圍是0~ -1。
一個short 型的數值能表示的數值的範圍是:-32768~32767,有負數有正數,這種是有符號數的表達範圍,無符號數的表達範圍是0~65535。你會發現這2種情況下都有65536個數字,這是2的16次方,也就是說short類型的數字是16位比特位表示的。
那麼當一種操作,使得操作結果最終超出了類型能夠表達的範圍,計算機會如何處理呢,如上圖所示,65535加1之後變成了0,加2變成了1,這就是所謂的數值反轉,所謂的溢出就是超出了數值的表達範圍。BEC的數據類型不是無符號的short類型,而是換成了uint256,不管什麼類型,但只要是固定長度都有其表達範圍,
當cnt 與_value的乘法運算超出了uint256的表達範圍,那麼amount得到值會遠遠小於預期的值,就像上面的例子中65535這麼大的數字加上1結果變成了0.那麼當amount的數值很小,但是cnt和_value很大的時候,簽名紅色箭頭表示的檢查就會全部通過,但是,最後轉賬的時候,不是使用的amount,而是使用的_value,於是造成了可以讓黑客攻擊的數據溢出漏洞。