作者:Al1ex @ 知道創宇404區塊鏈安全研究團隊

時間:2020年8月20日

前言

智慧合約的概念可以追溯到1994年,由Nick Szabo提出,但直到2008年才出現採用智慧合約所需的區塊鏈技術,而最終於2013年,作為以太坊智慧合約系統的一部分,智慧合約首次出現。

智慧合約包含了有關交易的所有資訊,只有在滿足要求後才會執行結果操作,智慧合約和傳統紙質合約的區別在於智慧合約是由計算機生成的,因此,程式碼本身解釋了參與方的相關義務,與此同時,使用者可以根據規則開發自己想要的智慧合約。

而隨著智慧合約普及,合約的安全問題也引起了眾多合約開發者和安全研究人員關注,比較典型的就是隨之建立的DASP Top10(

https://www。

dasp。co/

)。近期,筆者在對一些智慧合約進行程式碼審計時發現有很多合約存在可疑的後門漏洞,具備特殊許可權的地址使用者(合約的owner)或合約賬號具備控制使用者資產的許可權,可對任意使用者的資產進行銷燬操作,本文將對此進行簡要分析。近期,筆者在對一些智慧合約進行程式碼審計時發現有很多合約存在可疑的後門漏洞,具備特殊許可權的地址使用者(合約的owner)或合約賬號具備控制使用者資產的許可權,可對任意使用者的資產進行銷燬操作,本文將對此進行簡要分析。

函式漏洞

burn()

合約地址:

https://

etherscan。io/address/0x

705051bbfd9f287869a412cba8bc7d112de48e69#code

利用條件:合約的owner許可權

漏洞程式碼:

智慧合約中的那些後門漏洞

漏洞分析:如上圖所示在智慧合約中提供了burn函式,該函式主要用於銷燬其它地址的token,當要銷燬的token數量小於目標賬戶所擁有的token值時就可以成功銷燬目標賬戶的token,且這裡的地址可以指定為任意使用者的地址,所以只要我們能夠呼叫該函式即可透過賦予_ from為任意地址賬戶,_ unitAmout為任意數量(不超過from賬戶擁有的數量)就可以銷燬_from賬戶的代幣,下面我們再來看一下此處對於函式呼叫者身份限定的修飾器—onlyOwner

智慧合約中的那些後門漏洞

由以上程式碼可知,當函式的呼叫者為合約的owner地址賬戶時可以銷燬任意地址使用者的代幣,甚至將其歸0

burnFrom()

合約地址:

https://

etherscan。io/address/0x

365542df3c8c9d096c5f0de24a0d8cf33c19c8fd#code

利用條件:合約的owner,同時mintingFinished為“False”

漏洞程式碼:

智慧合約中的那些後門漏洞

漏洞分析:如上圖所示合約中的burnFrom函式用於銷燬代幣,但是該函式只能被合約的owner呼叫,而且由於地址引數可控故合約的owner可以操控任意地址使用者的代幣,銷燬任意地址使用者任意數量的代幣(數量小於等於使用者代幣總量),由於該函式被canMint修飾,所以檢視一下該修飾器

智慧合約中的那些後門漏洞

之後透過“Read Contract”來檢視當前“mintingFinished”的值:

智慧合約中的那些後門漏洞

可以看到“mintingFinished”為“False”,即滿足“canMint”修飾器條件,所以此時的burnFrom函式可被合約的owner呼叫來操控任意使用者的代幣。

burnTokens

合約地址:

https://

etherscan。io/address/0x

662abcad0b7f345ab7ffb1b1fbb9df7894f18e66#code

利用條件:合約的owner許可權

漏洞程式碼:

智慧合約中的那些後門漏洞

漏洞分析:如上圖所示,burnTokens用於銷燬使用者的代幣,由於銷燬的地址引數、銷燬的代幣數量都可控,所以合約的呼叫者可以銷燬任意使用者的代幣,但是該函式只能被合約的ICO地址使用者呼叫,下面跟蹤一下該賬戶看看其實現上是否可以

智慧合約中的那些後門漏洞

從上面可以看到合約在初始化是對icoContract進行了賦值,下面透過

http://

etherscan。io

中的readcontract溯源一下:

智慧合約中的那些後門漏洞

之後再次進入icoContract中跟蹤是否可以成功呼叫:

智慧合約中的那些後門漏洞

從程式碼中可以看到burnTokens(關於修飾器的跟蹤分析與之前類似,這裡不再贅述):

智慧合約中的那些後門漏洞

這裡的cartaxiToken即為之前的合約地址:

智慧合約中的那些後門漏洞

同時發現存在呼叫的歷史記錄:

https://

etherscan。io/tx/0xf5d12

5c945e697966703894a400a311dc189d480e625aec1e317abb2434131f4

智慧合約中的那些後門漏洞

destory()

合約地址:

https://

etherscan。io/address/0x

27695e09149adc738a978e9a678f99e4c39e9eb9#code

利用條件:合約的owner許可權

漏洞程式碼:

智慧合約中的那些後門漏洞

如上圖所示,在智慧合約當中提供了destory函式,用於銷燬目標賬戶的代幣,在該函式當中增加了對msg。sender、accountBalance的判斷,從整個邏輯上可以看到主要有兩種銷燬途徑:

途徑一:合約的owner賦予allowManuallyBurnTokens為“true”的條件下,地址賬戶自我銷燬自己的代幣

途徑二:無需allowManuallyBurnTokens為“true”的條件,合約的owner銷燬任意地址使用者的代幣

自然,途徑一自我銷燬代幣合情合理,但是途徑二卻導致合約的owner可以操控任意地址使用者的代幣,例如:銷燬地址使用者的所有代幣,導致任意地址使用者的代幣為他人所操控,這自然不是地址使用者所期望的。

destroyTokens()

合約地址:

https://

etherscan。io/address/0x

f7920b0768ecb20a123fac32311d07d193381d6f#code

利用條件:Controller地址賬戶

漏洞程式碼:

智慧合約中的那些後門漏洞

如上圖所示,destroyTokens函式用於銷燬代幣,其中地址引數可控,在函式中只校驗了銷燬地址賬戶的代幣是否大於要銷燬的數量以及當前總髮行量是否大於要銷燬的數量,之後進行更新代幣總量和地址賬戶的代幣數量,不過該函式有onlyController修飾器進行修飾,下面看以下該修飾器的具體內容:

智慧合約中的那些後門漏洞

之後透過ReadContract可以看到該controller的地址:

智慧合約中的那些後門漏洞

之後再Etherscan中可以檢視到該地址對應的為一個地址賬戶,故而該地址賬戶可以操控原合約中的任意地址使用者的代幣:

智慧合約中的那些後門漏洞

destroyIBTCToken

合約地址:

https://

etherscan。io/address/0x

b7c4a82936194fee52a4e3d4cec3415f74507532#code

利用條件:合約的owner

漏洞程式碼:

智慧合約中的那些後門漏洞

如上圖所示合約中的destroyIBTCToken是用於銷燬IBTCToken的,但是由於該函式只能被合約的owner呼叫,而且要銷燬的地址引數to可控,所以合約的owner可以傳入任意使用者的地址作為引數to,之後銷燬任意地址賬戶的代幣,onlyOwner修飾器如下所示:

智慧合約中的那些後門漏洞

melt()

合約地址:

https://

etherscan。io/address/0x

abc1280a0187a2020cc675437aed400185f86db6#code

利用條件:合約的owner

漏洞程式碼:

智慧合約中的那些後門漏洞

漏洞分析:如上圖所示合約中的melt函式用於銷燬代幣的token,且該函式只能被合約的CFO呼叫,同時由於地址引數dst可控,故合約的CFO可以銷燬任意地址使用者的代幣,onlyCFO修飾器程式碼如下所示

智慧合約中的那些後門漏洞

onlyCFO修飾器中的_cfo由建構函式初始化:

智慧合約中的那些後門漏洞

Sweep()

合約地址:

https://

etherscan。io/address/0x

4bd70556ae3f8a6ec6c4080a0c327b24325438f3#code

利用條件:合約的owner,同時mintingFinished為“False”

漏洞程式碼:

智慧合約中的那些後門漏洞

如上圖所示,合約中的sweep函式用於轉發代幣,該函式只能被合約的owner呼叫,在L167行優先透過allowance進行授權操作代幣的操作,之後呼叫transferFrom函式,並在transferFrom函式中做了相關的減法操作,由此抵消授權操作代幣:

智慧合約中的那些後門漏洞

之後緊接著又呼叫了_transfer函式:

智慧合約中的那些後門漏洞

在transfer函式中判斷轉賬地址是否為空、進行轉賬防溢位檢查、進行轉賬操作,透過以上邏輯可以發現由於sweep中的地址引數 _ from、_to可控,而且該函式只能被合約的owner呼叫,所以合約的owner可以透過該函式操控任意使用者的balance,並且將其轉向任意使用者的地址或者自己的地址。

zero_fee_transaction

合約地址:

https://

etherscan。io/address/0x

D65960FAcb8E4a2dFcb2C2212cb2e44a02e2a57E#code

利用條件:合約的owner

漏洞程式碼:

智慧合約中的那些後門漏洞

漏洞分析:在智慧合約中常見的轉賬方式大致有2種,一種是直接轉賬,例如常見的Transfer函式,該函式有兩個引數,一個指定代幣接受的地址,另一個為轉賬的額度,例如:

智慧合約中的那些後門漏洞

另外一種為授權其他使用者代為轉賬,這裡的其他使用者類似於一箇中介媒介的作用,其他使用者可以對授權使用者授予的資金額度進行操作,常見的也是transfer函式,不過引數個數不同而已,其中有三個引數,一個為代為轉賬的地址,一個為接受代幣的地址,一個為接受代幣的數量,例如:

智慧合約中的那些後門漏洞

瞭解了常見的兩種轉賬方式,下面我們回過頭來看一下漏洞程式碼:

智慧合約中的那些後門漏洞

可以看到在函式zero_fee_transaction中進行了以下判斷:

1、判斷的當前代為轉賬的額度是否大於當前轉賬的數量

2、判斷當前轉賬的數量是否大於0

3、防溢位檢查

可以發現這裡未對當前函式呼叫者是否具備授權轉賬進行檢查(暫時忽略onlycentralAccount修飾器)以及授權額度進行檢查,只對轉賬額度以及是否溢位進行了檢查,顯然這裡是存在問題的,而且該函式沒有修飾詞進行修飾,故預設為public,這樣一來所有人都可以呼叫該函式,在這裡我們可以看到在不管修飾器onlycentralAccount的情況下我們可以傳遞任意地址賬戶為from、任意地址賬戶為to、以及任意數量(需要小於from地址賬戶的代幣數量),之後即可無限制的從from地址賬戶轉代幣到to賬戶,直到from地址的代幣數量歸0。

下面我們看一下onlycentralAccount修飾器對於函式呼叫者的身份限定:

智慧合約中的那些後門漏洞

之後搜尋central_account發現central_account由函式set_centralAccount進行賦值操作,此處的修飾器為onlyOwner:

智慧合約中的那些後門漏洞

之後檢視onlyOwner修飾器可以看到此處需要msg。sender為owner,即合約的owner,在建構函式中進行初始化:

智慧合約中的那些後門漏洞

文末小結

智慧合約主要依託於公鏈(例如:以太坊)來發行代幣並提供代幣的轉賬、銷燬、增發等其它邏輯功能,但使用者的代幣理應由使用者自我進行控制(透過交易增加或減少),並由使用者自我決定是否銷燬持幣數量,而不是由合約的owner或其他特殊的地址賬戶進行操控。

歡迎關注我和我的專欄:

訪問以下連結免費下載安全技術白皮書

如果你想與我成為朋友,歡迎關注公眾號“安全宇宙”