作者:啟明星辰ADLab

一、事件介紹

近期,啟明星辰ADLab聯合電子科技大學的陳廳副教授【1】追蹤到了以太坊token中的首個自動化薅羊毛攻擊事件。被攻擊的合約地址為0x86c8bf8532aa2601151c9dbbf4e4c4804e042571【2】,token名稱為Simoleon (SIM),截止目前有接近57萬賬戶持有該合約的token:

經過深入分析,我們發現攻擊者對以太坊的理解非常深刻,其通過部署攻擊合約獲得了超過700萬的token,從57萬賬戶中脫穎而出,一舉成為該合約token的第四大持有者:

二、被攻擊的合約Simoleon

在token發行過程中,為增加人氣發行方可能會選擇空投,即在一定時間窗口和投放總量的條件下免費給參與地址發送一定數量的token。Simoleon合約也加入了空投能力,在總量發放完之前,任何未接受過該token空投的賬戶都可以調用本合約的transfer函數給指定賬戶地址免費轉賬token:

三、攻擊過程分析

我們分析攻擊賬戶的token來源,通過etherscan查看該賬戶的token交易記錄,一共分為兩項:709萬和1萬,分別來自不同的賬戶地址:

繼續跟蹤709萬token的交易記錄,其來源有三項:550萬,155萬和3萬,都來自同一個賬戶地址0x73fa30b609249166fa425f34b7142591c92b5548:

分析發現地址0x73fa30b609249166fa425f34b7142591c92b5548是一個閉源智能合約,由賬戶0x0075fd99426911b2e9650114bedc1195ad027f21創建,該合約總共有23筆交易:

Simoleon合約對已經發放token的地址都進行了記錄,因此每個地址只能免費獲得1萬的token。要獲得更多的數量,就需要創建很多新賬戶,然后利用這些新賬戶調用Simoleon合約的transfer函數給指定賬戶來獲得大量token。如果通過創建EOA賬戶來進行薅羊毛,則每個賬戶都需要一些以太幣,否則EOA賬戶就沒有gas去調用Simoleon合約的transfer函數,也就無法薅羊毛。顯然,給大量EOA賬戶發送以太幣會增加額外的交易手續費。

攻擊者在這里采用了一種精妙的攻擊手法:首先部署一個惡意的攻擊合約,地址為0x73fa30b609249166fa425f34b7142591c92b5548;然后調用攻擊合約中簽名為0x2b6cab44的函數來動態生成臨時合約;最后臨時合約在構造函數中直接調用Simoleon合約的transfer函數給攻擊合約發送token。因為動態生成的臨時合約都是未領取過token的賬戶,所以都能自動獲得空投份額。攻擊者只需要給攻擊賬戶發送以太幣就有足夠的gas調用攻擊合約,同時攻擊者還能控制臨時合約的生成數量。

通過分析攻擊合約的23個交易數據,得到攻擊者對0x2b6cab44函數的調用過程如下:

其中第一筆的交易(0x7f87268e06b76644ad4b8e162fb76d1c6e2e0480029b14db0e013f7d7d195e2f)細節如下,攻擊者通過0x2b6cab44函數的參數來控制只生成2個臨時合約,2個臨時合約分別獲取1萬的token,然后發送給攻擊合約。臨時合約最后還進行了自動銷毀,使自己的代碼從區塊鏈上消失。

攻擊者前面4筆的交易中,每次生成的臨時合約數量越來越大。其中第4次生成了80個臨時合約,但是執行失敗了,查看原因是gas不足。

攻擊者在后續的交易中,每次都選擇只生成50個臨時合約。理論上攻擊者可以增大允許的gas消耗量,從而一次性創建80個臨時合約來加快薅羊毛,但攻擊者卻選擇一次50個的搬磚模式。通過深入分析,我們發現攻擊者對以太坊的底層機制相當熟悉,比如這里的gas消耗問題。

在以太坊中,每一筆交易都會消耗一定量的gas,實際消耗量由交易的復雜度決定,但不會超過發送者指定該交易能允許的最大消耗量。逆向分析0x2b6cab44函數后發現它是在循環創建臨時合約,顯然循環次數越多,這個函數調用的交易復雜度就越高,實際的gas消耗量就越大,允許的gas消耗量也就必須設置為越大。臨時合約數量設置為50的時候,gas實際消耗量為3096224;臨時合約數量設置為80時,gas實際消耗量為6174290。

然而,每個區塊又有最大gas消耗量的閾值,并且每個區塊至少要容納1筆交易,因此以太坊鏈上任何一筆交易的gas消耗量都不允許超過區塊的閾值。這進一步導致,在礦工最優化收益方案中,如果一個交易允許的gas消耗量過大,就會傾向性把這個交易排除在區塊外,從而導致該交易失敗。攻擊者通過探測嘗試找到最佳臨時合約數量為50(因為80個臨時合約的gas消耗已經超過允許的gas消耗導致交易失敗),從而實現一次調用可以薅更多token,同時又不會觸發gas問題。

行家一出手,就知有沒有!不愧是有知識的攻擊者。

四、暗藏玄機的etherscan

在追蹤分析過程中,我們發現了另外一起問題,即etherscan對token的變化記錄是不準確的,甚至可能完全是錯誤的。如下是攻擊合約的第一筆token收入,2個臨時合約總共獲得2萬token,然后發送給了攻擊合約:

緊接著攻擊合約產生了第一筆token支出,發送了3萬token給攻擊者:

根據etherscan中的交易記錄,攻擊合約的收入只有2萬,結果支持了3萬。多支出的1萬出自哪里,是否憑空產生?為何這1萬的變化,etherscan沒有任何記錄?

經過分析,找到原因就在Simoleon合約的transfer函數,合約在空投的時候也會對目標地址進行免費發送token,但是這個發放卻沒有調用Transfer事件:

于是,攻擊合約的token變化過程如下:

(1)攻擊合約被創建,token為零。

(2)攻擊合約0x2b6cab44函數第一次被調用,創建2個臨時合約:

a)第1個臨時合約初始化時調用Simoleon的transfer函數,該函數首先給臨時合約空投initialize(msg.sender),此時臨時合約的token為1萬;然后給攻擊合約空投initialize(_to),此時攻擊合約的token為1萬;最后把臨時合約的1萬token發送給攻擊合約,同時調用事件Transfer記錄臨時合約給攻擊合約的發送量為1萬。至此,攻擊合約的token總計為2萬,由空投的1萬加上臨時合約發送的1萬構成。

b)第2個臨時合約初始化時調用Simoleon的transfer函數,該函數首先給臨時合約空投initialize(msg.sender),此時臨時合約擁有的token為1萬;然后把臨時合約的1萬token發送給攻擊合約,同時調用事件Transfer記錄臨時合約給攻擊合約的發送量為1萬。至此,攻擊合約的token總計為3萬,由先前2萬加臨時合約發送的1萬構成。

(3)攻擊者從攻擊合約提取全部token,提取總量token為3萬。

因此,從攻擊合約賬戶自身的收支平衡來看,并沒有憑空產生token,只是etherscan未能監控到攻擊合約因為空投獲得的1萬token。這說明了etherscan對token變化的監控是基于Transfer事件,而不是基于每個賬戶的實際token變化。這會帶來一些潛在的威脅,因為Transfer事件在本質上只是一個道德約束,EVM本身對其沒有任何限制能力,攻擊者可以不調用事件,也可以任意修改該事件的參數,實現諸如:實際轉移的token量比事件通知的數量不匹配。對于頻繁交易token的節點來說,這是一個新的挑戰,因為該節點將難以通過鏈上數據追蹤每筆token的來源,因為Transfer事件不再是準確的。

五、總結

Simoleon合約能被自動化的薅羊毛,最根本的原因在于其合約代碼的空投獎勵函數沒有任何權限控制,任意未領過空投的賬戶都可以直接調用Simoleon合約來獲取。因此,攻擊者可以利用攻擊合約來創建大量賬戶來領取。一種緩解辦法是給空投獎勵函數設置權限控制,比如只有合約創建者才能給目標地址發放token。

區塊鏈的特性決定了合約代碼一經部署就無法修改,無論是合約的開發者,還是投資者,還是交易平臺,都應當對合約進行多重安全審計,盡量在上鏈前消除安全風險。

參考鏈接:

【1】Ting Chen, University of Electronic Science and Technology of China.

http://faculty.uestc.edu.cn/chenting/zh_CN/index.htm

【2】Simoleon (SIM).

https://etherscan.io/address/0x86c8bf8532aa2601151c9dbbf4e4c4804e042571


啟明星辰積極防御實驗室(ADLab)

ADLab成立于1999年,是中國安全行業最早成立的攻防技術研究實驗室之一,微軟MAPP計劃核心成員。截止目前,ADLab通過CVE發布Windows、Linux、Unix等操作系統安全或軟件漏洞近400個,持續保持國際網絡安全領域一流水準。實驗室研究方向涵蓋操作系統與應用系統安全研究、移動智能終端安全研究、物聯網智能設備安全研究、Web安全研究、工控系統安全研究、云安全研究。研究成果應用于產品核心技術研究、國家重點科技項目攻關、專業安全服務等。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/646/