分享二智慧合約自動檢測工具程式碼介紹

搭建MrsFu123發表於2022-04-29

等級: ERROR


描述: 當合約定義ERC20標準的transfer/transferFrom介面時,需要檢查transfer/transferFrom介面的返回值,否則會導致對轉賬狀態的判斷錯誤。


樣例


token.transferFrom(msg.sender, address(this), amount);的返回值需要檢驗。


修復建議: 對所有轉賬函式的結果進行校驗。


2.錯誤的ERC20介面


等級: WARNING


描述: 定義標準的ERC20介面時與標準ERC20介面不完全一致。


樣例


ERC20標準的Transfer事件是event Transfer(address indexed from, address indexed to, uint256 value);。


修復建議: 完全參照ERC20標準設定ERC20事件和介面。


3.錯誤的ERC721介面


等級: WARNING


描述: 定義的標準ERC721介面和標準ERC721介面並不完全相同。


樣例


函式ownerOf(uint256 tokenId)是ERC721的介面,但缺少引數或返回值。


修復建議: 對照ERC721


THREE 
函式呼叫檢測


1 受控的代理呼叫

等級: ERROR


描述: 委託呼叫是呼叫合約的一種方式。委託呼叫的操作空間在呼叫發起這一方,因此沒有任何許可權控制或呼叫地址未知的呼叫是可被入侵的。


樣例

圖片


addr可以被呼叫者任意操控。


修復建議: 為執行delegatecall所在函式設定許可權控制,指定呼叫者。


2.未檢查的底層call

等級: ERROR


描述: 智慧合約的底層呼叫具有返回資料,呼叫合約執行失敗不會導致呼叫發起合約執行失敗,如果呼叫操作失敗且沒有檢查返回值,可能導致預計邏輯與實際狀態出現差異。


樣例

圖片


address(f).call(abi.encodePacked(function_selector)); 實現了對合約Base中函式f()的呼叫。但是使用了call沒有對呼叫的返回值做校驗,將導致無法判斷呼叫狀態。


修復建議: 對所有底層call方法返回值進行校驗。


3.未檢查的send方法


等級: ERROR


描述: 智慧合約的轉賬函式send具有返回值,如果轉賬失敗程式碼會繼續執行,呼叫不會回退狀態。因此使用send進行轉賬時應檢查返回值,並以此判定轉賬是否成功。


樣例


函式f使用send進行轉移ether,由於沒有對send的返回值進行校驗,將不能知曉轉賬是否真實成功。


修復建議: 使用send進行轉賬時,對返回值進行校驗。


4.底層call


等級: INFO


描述: 使用低階呼叫是有風險的。低階呼叫不檢查程式碼是否存在或呼叫成功。


修復建議: 避免底層call


FOUR  
業務邏輯安全檢測


1.轉賬地址未知


等級: ERRO R


描述: 轉賬函式沒有新增任何許可權限制,且轉賬接受者可設定,任何人都可以獲取合約資金。 


樣例


函式f()沒有任何許可權控制,且轉賬接受者是msg.sender。呼叫f()即可獲得合約所有資金。


修復建議: 當合約存在對外轉賬功能時,對包含轉賬函式新增正確的許可權控制。


2.動態陣列長度的修改


等級: ERROR


描述: 在solc 0.6.0版本以下,動態陣列型別的長度資訊可以被直接修改,長度資訊的改變將直接影響儲存的陣列資料。 


樣例


合約部署後,動態陣列a的第20位資料a[20]為1,若呼叫f(10)將a的長度修改為10,則a[20]指向的值將丟失。


修復建議: 避免對動態陣列的長度直接或間接修改。


3.謹慎使用列舉


等級: ERROR


描述: 在0.4.5版本以前,列舉型別的呼叫不會進行溢位判斷。


樣例


E是長度為3的enum型別,即使嘗試讀取E的第10個,bug()函式也不會恢復。


修復建議: 避免使用0.4.0-0.4.4版本的solc編譯器,或對列舉值進行區間判斷。



4.鎖定ETH的合約


等級: ERROR


描述: 在智慧合約中存在收取以太幣的函式,但不存在發出幣的函式,將導致以太幣被鎖定在合約中。


樣例


函式f()有一個payable符號,但合約沒有能力花費/轉移以太幣。


修復建議: 移除收錢函式的payable屬性,或新增可消耗Ether/向外轉Ether的函式。


5.錯誤的修飾器


等級: ERROR


描述: 修飾器起到一個狀態/許可權控制的作用,在修飾器中如果無法到達_;程式碼段,將無法執行函式並引起邏輯錯誤。


樣例


修飾符 bug1() 有一個 if 語句,當bool_test 為 false 時, _; 不會到達,那麼函式 use() 將不會被使用。


修復建議: 保證修飾器可以到達_;程式碼段,正確執行修飾器功能。


6.缺少返回值


等級: ERROR


描述: 在函式返回宣告有返回值,但沒有相應的返回實現。


樣例


函式f()宣告返回一個uint型別的值,而合約在函式體中缺少return關鍵字,這將導致返回0(uint型別的最小值 )。


修復建議: 新增對應的返回值或刪除返回宣告。


7.重入風險


等級: ERROR


描述: 呼叫外部合約的主要危險之一是它們可以接管控制流。在重入攻擊(又名遞 歸呼叫攻擊)中,惡意合約在函式的第一次呼叫完成之前回撥呼叫合約。這可能會導致函式的不同呼叫以不希望的方式互動。在call呼叫後改變關鍵狀態變數容易造成重入危險。


樣例


在函式f()判斷地址擁有的數額大小後,使用call傳送以太幣,最後storage變數book在轉賬操作後發生變化。因此,攻擊者可以迴圈呼叫f()來提取以太幣。


修復建議: 使用檢查-生效-互動模式避免重入攻擊。 


8.合約自毀函式


等級: ERROR


描述: 合約中包含了自毀函式,且沒有使用任何身份認證,將使合約處於不穩定狀態。


樣例


任何人都可以通過呼叫f()將合約銷燬並提取合約中的資金。


修復建議: 儘量避免使用自毀函式,或新增正確的許可權控制。


9.建構函式中存在未初始化的函式指標


等級: ERROR


描述: 在合約的建構函式中存在未初始化的函式指標,直接呼叫這些指標將出現錯誤。


樣例


f是constructor中的函式指標,而在函式指標完全實現之前,它已被呼叫。這種行為會導致部署失敗。


修復建議: 在函式指標完全實現之前不要呼叫函式指標。


10.未初始化的狀態變數


等級: ERROR


描述: 使用未初始化的狀態變數可能導致邏輯錯誤。


樣例


狀態變數a未初始化,將被預設為0地址。在執行轉賬操作時,將導致以太幣丟失(轉賬去0x0地址)。


修復建議: 儘可能在宣告狀態變數時便初始化該狀態變數。


11.可入侵的升級合約


等級: ERROR


描述: 合約包含自毀函式,且初始化函式任何人可呼叫。


樣例


函式initialize()會初始化合約,但任何人都可以呼叫,如果攻擊者在所有者之前呼叫initialize(),攻擊者可以隨時呼叫kill()來使代理合約功能失效。


修復建議: 在合約中將初始化函式功能在建構函式中執行,保證owner不能任意修改。


12.斷言錯誤


等級: ERROR


描述: assert的限制條件是必須滿足的。


修復建議: 請檢視程式碼邏輯尋找問題並修復。


13.整型上溢位


等級: ERROR


描述: 上溢位是指運算的結果超過了結果型別所能表示的上限。


修復建議: 請加上溢位判斷或使用SafeMath庫進行運算。


14.整型下溢位


等級: ERROR


描述: 下溢位表示計算操作中的結果超過了結果型別可以表示的下限。


修復建議: 請加下溢位判斷或使用SafeMath


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70009264/viewspace-2889519/,如需轉載,請註明出處,否則將追究法律責任。

相關文章