智能合約中的那些后門漏洞


前言

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

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

而隨着智能合約普及,合約的安全問題也引起了眾多合約開發者和安全研究人員關注,比較典型的就是隨之建立的DASP Top10( https://www.dasp.co/)。近期,筆者在對一些智能合約進行代碼審計時發現有很多合約存在可疑的后門漏洞,具備特殊權限的地址用戶(合約的owner)或合約賬號具備控制用戶資產的權限,可對任意用戶的資產進行銷毀操作,本文將對此進行簡要分析。近期,筆者在對一些智能合約進行代碼審計時發現有很多合約存在可疑的后門漏洞,具備特殊權限的地址用戶(合約的owner)或合約賬號具備控制用戶資產的權限,可對任意用戶的資產進行銷毀操作,本文將對此進行簡要分析。

函數漏洞

burn()

合約地址:https://etherscan.io/address/0x705051bbfd9f287869a412cba8bc7d112de48e69#code

利用條件:合約的owner權限

漏洞代碼:

1597993651.png!small

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

1597993644.png!small

由以上代碼可知,當函數的調用者為合約的owner地址賬戶時可以銷毀任意地址用戶的代幣,甚至將其歸0

burnFrom()

合約地址:https://etherscan.io/address/0x365542df3c8c9d096c5f0de24a0d8cf33c19c8fd#code

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

漏洞代碼:

3

漏洞分析:如上圖所示合約中的burnFrom函數用於銷毀代幣,但是該函數只能被合約的owner調用,而且由於地址參數可控故合約的owner可以操控任意地址用戶的代幣,銷毀任意地址用戶任意數量的代幣(數量小於等於用戶代幣總量),由於該函數被canMint修飾,所以查看一下該修飾器

1597993662.png!small

之后通過"Read Contract"來查看當前"mintingFinished"的值:

1597993670.png!small

可以看到"mintingFinished"為"False",即滿足"canMint"修飾器條件,所以此時的burnFrom函數可被合約的owner調用來操控任意用戶的代幣。

burnTokens

合約地址:https://etherscan.io/address/0x662abcad0b7f345ab7ffb1b1fbb9df7894f18e66#code

利用條件:合約的owner權限

漏洞代碼:

1597993675.png!small

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

1597993683.png!small

從上面可以看到合約在初始化是對icoContract進行了賦值,下面通過etherscan.io中的readcontract溯源一下:

1597993691.png!small

之后再次進入icoContract中跟蹤是否可以成功調用:

1597993697.png!small

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

1597993814.png!small

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

1597993821.png!small

同時發現存在調用的歷史記錄:https://etherscan.io/tx/0xf5d125c945e697966703894a400a311dc189d480e625aec1e317abb2434131f4

1597993829.png!small

destory()

合約地址:https://etherscan.io/address/0x27695e09149adc738a978e9a678f99e4c39e9eb9#code

利用條件:合約的owner權限

漏洞代碼:

1597993835.png!small

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

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

  • 途徑二:無需allowManuallyBurnTokens為"true"的條件,合約的owner銷毀任意地址用戶的代幣

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

destroyTokens()

合約地址:https://etherscan.io/address/0xf7920b0768ecb20a123fac32311d07d193381d6f#code

利用條件:Controller地址賬戶

漏洞代碼:

1597993840.png!small

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

1597993845.png!small

之后通過ReadContract可以看到該controller的地址:

1597993851.png!small

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

1597993856.png!small

destroyIBTCToken

合約地址:https://etherscan.io/address/0xb7c4a82936194fee52a4e3d4cec3415f74507532#code

利用條件:合約的owner

漏洞代碼:

1597993862.png!small

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

1597993875.png!small

melt()

合約地址:https://etherscan.io/address/0xabc1280a0187a2020cc675437aed400185f86db6#code

利用條件:合約的owner

漏洞代碼:

1597993880.png!small

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

1597993885.png!small

onlyCFO修飾器中的_cfo由構造函數初始化:

1597993891.png!small

Sweep()

合約地址:https://etherscan.io/address/0x4bd70556ae3f8a6ec6c4080a0c327b24325438f3#code

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

漏洞代碼:

1597993897.png!small

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

1597993903.png!small

之后緊接着又調用了_transfer函數:

1597993910.png!small

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

zero_fee_transaction

合約地址: https://etherscan.io/address/0xD65960FAcb8E4a2dFcb2C2212cb2e44a02e2a57E#code

利用條件:合約的owner

漏洞代碼:

1597993916.png!small

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

1597993921.png!small

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

1597993928.png!small

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

1597993934.png!small

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

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

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

3、防溢出檢查

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

下面我們看一下onlycentralAccount修飾器對於函數調用者的身份限定:

1597993940.png!small

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

1597993947.png!small

之后查看onlyOwner修飾器可以看到此處需要msg.sender為owner,即合約的owner,在構造函數中進行初始化:

1597993951.png!small

文末小結

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

原文鏈接:https://paper.seebug.org/1300/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM