ReGuard:智能合約中可重入漏洞檢測

ReGuard:智能合約中可重入漏洞檢測

論文:Chao Liu, Han Liu, Zhao Cao, Zhong Chen, Bangdao Chen, and Bill Roscoe. 2018.

ReGuard: Finding Reentrancy Bugs in Smart Contracts. In Proceedings of the 40th

International Conference on Software Engineering Companion. IEEE Press.

論文摘要:

智能合約為在區塊鏈上執行加密貨幣交易提供了一種新途徑。儘管這種新技術引入了無衝突機制和透明機制,但智能合約本身是脆弱的。智能合約作為一種特殊的計算機程序,它仍然無法避免產生BUG。更糟糕的是,可利用的安全漏洞可能導致災難性的後果。例如,損失加密貨幣。在這篇演示文章中,我們主要關注智能合約中最常見的安全漏洞類型——可重入漏洞。可重入漏洞曾經導致了著名的DAO攻擊,致使被攻擊者損失高達六千萬美元。我們提出了一種基於Fuzzing來分析智能合約中可重入漏洞的工具,Reguard。具體來說,ReGuard通過迭代生成隨機且不同的交易事務,對智能合約執行模糊測試。基於運行時追蹤,ReGuard將動態識別可重入漏洞。在初步評估中,我們分析了現有的5個Ethereum合同,ReGuard自動標記了7個以前未報告的可重入漏洞。

技術介紹:

文中採用了自己編寫的例子介紹了智能合約中可重入漏洞是什麼,並且如何被利用:

ReGuard:智能合約中可重入漏洞檢測

圖1:可被DAO攻擊的簡單示例

示例代碼是用solidity (Ethereum智能合約的一種編程語言)編寫的,有兩個受害者合約和攻擊者。被害人合約具有一個withdraw()函數,它將以太幣從被調用方發送到調用方(第4行)。DAO攻擊分為一下幾步:

(1)攻擊者通過調用受害者合約的withdraw函數創建一個事務

(2)受害者轉賬(第4行)並調用回調函數(10到12行)

(3)回調函數遞歸調用withdraw函數,即可重入

(4)在一次迭代限制內,額外的億臺幣將被轉賬多次

如上所述,可重入漏洞很容易在已部署的區塊鏈合約上利用,並且已經成為實際中最常見的攻擊之一。不幸的是,我們不僅對如何自動準確地捕捉這些bug知之甚少,而且對工具的支持也非常有限。從實踐的角度來看,檢測智能合約中的可重入漏洞面臨以下挑戰:

挑戰1:覆蓋事務的執行場景。智能合約的執行在不同的事務中,可能產生不同的結果。覆蓋所有的結果不僅是代價昂貴的,而且在一些情況下是不可能的。

挑戰2:代碼可重入特徵。可重入漏洞的特徵在智能合約上下文中缺乏準確的定義。在檢測中引入簡單的檢測模式將產生誤報,而嚴格的檢測模式會漏報錯誤。

ReGuard:智能合約中可重入漏洞檢測

圖2:代碼到代碼的智能合約轉換

為了解決這些挑戰,我們開發了ReGuard,用於檢測智能合約中的可重入漏洞。

ReGuard引入了一個基於翻譯的框架,從特定的智能合約編程語言到c++。的檢測,

ReGuard擴展了已有的fuzzing引擎(例如,AFL和LibFuzzer)生成隨機事務。在運行時期間,ReGuard記錄關鍵的執行跟蹤,並將其提供給可重入漏洞自動檢測機以識別潛在的bug。

ReGuard:智能合約中可重入漏洞檢測

圖3:ReGuard框架圖

ReGuard的架構如圖3所示。在高級圖中,ReGuard將智能合約的代碼作為輸入。具體來說,它同時支持源代碼和二進制代碼。就輸出而言,ReGuard生成一個錯誤報告,該報告是在分析的智能合約中發現的可重入錯誤的集合。對於每一個漏洞檢測報告,ReGuard會標記導致漏洞的源代碼錯誤位置並且標記是什麼事務導致了這個漏洞。

接下來,我們將介紹ReGuard的工作流程。給定智能合約的代碼,ReGuard將其解析為一箇中間表示(IR)。對於源代碼合約,IR是一個抽象語法樹(AST)。對於二進制代碼合約,我們使用一個控制流圖作為它的IR。然後,ReGuard在合約轉換器中執行從IR到c++的源到源的轉換。轉換後的c++合約保持原來的行為。另一方面,ReGuard嵌入了一個fuzzing引擎,它將使用運行時覆蓋信息作為反回信息,迭代地生成隨機字節。ReGuard將字節解釋為事務請求。結合c++智能合約、事務和運行時庫,ReGuard執行合約並轉儲分析相關操作的運行時跟蹤,例如,函數調用和返回、對存儲和區塊鏈參數的訪問、分支操作等。然後將跟蹤傳遞到核心檢測器以進行可重入漏洞分析。最後報告發現的bug。

如上所述,ReGuard執行從IR到c++的源代碼到源代碼的轉換。該轉換在合約轉換器中實現。我們以AST IR為例來解釋這個轉換,它在概念上相當於遍歷AST然後為特定類型的AST節點生成c++代碼。考慮圖2 a中的代碼,這個合約用solidity編寫聲明和初始化了兩個變量flag和amount。除此之外,它定義了兩個回調函數update用來更新存儲的值和withdraw用來轉賬以太幣。圖2b顯示了轉換後的c++合約。具體來說,兩個函數update和withdraw會相應地進行轉換。除了原始的函數參數外,還顯式地將消息對象傳遞到c++函數中,以攜帶事務信息,如發送方的地址和包含的以太幣等。在第14-15行,調用了fallback_call函數來模擬調用地址中的fallback函數的操作。總之,轉換保持原始行為和接口到fuzzing引擎以生成事務。

智能合約的執行高度依賴於事務。也就是說,不同的事務可能會導致不同的合約狀態,其中可能會出現可重入漏洞。為了儘可能地探索智能合約的狀態空間,ReGuard利用精心設計的fuzzing引擎生成隨機事務並覆蓋不同的執行場景,如圖4所示。

ReGuard:智能合約中可重入漏洞檢測

圖4:將隨機字節解釋為事務

ReGuard工具利用fuzzing引擎產生隨機字節,然後解釋為一個三元組集合(from,to,input)。from字段指定消息的發送方地址。to字段指示將事務發送到哪個合約(c++類)(在本例中很簡單,如圖2a所示)。input字段生成對合約中定義的函數的隨機調用(在本例中使用參數10進行更新,如圖2a所示)。接下來,三元組將嵌入到執行c++智能合約的主入口中。在執行期間,運行時利用運行時覆蓋率優化字節的生成。考慮到圖 2c中的情況,fuzzing引擎生成三個事務,這三個事務都是從同一個發送者到Simple合約。並且生成一個調用序{update(10), withdraw(), update(20)}

當fuzzing引擎運行時,ReGuard將執行具有不同事務的智能合約並轉儲運行時追蹤。由核心檢測器分析跟蹤,以識別可重入漏洞。具體地說,檢測是通過在可重入漏洞檢測自動機中解析跟蹤來實現的,如圖5所示。

ReGuard:智能合約中可重入漏洞檢測

圖5:可重入漏洞檢測自動機。entry/exit:函數的進入和退出。call:EVM的調用操作碼。

可重入漏洞檢測自動機是有限狀態機(FSM)的一種形式,其中的狀態指示可重入漏洞的發生,而轉換是在跟蹤中記錄的操作。共指定五種狀態,即,START,FUNC, FUNCCALL,RE和ERROR。START是自動機的入口點。ERROR表示發生了可重入漏洞。FUNC為函數調用建模,FUNC CALL進一步細化以太幣轉賬調用。RE標誌執行引入可重入函數調用。

本文將ReGuard部署為web服務。圖6顯示了ReGuard的屏幕截圖。為了分析一個智能合約,ReGuard採用了“一鍵式”設計。用戶只需要在瀏覽器中輸入合約代碼,ReGuard就會處理所有事情,例如:語法檢查、代碼轉換、模糊化和錯誤檢測。

ReGuard:智能合約中可重入漏洞檢測

圖6: ReGuard屏幕截圖

以圖6中的簡單智能合約為運行示例,我們簡要描述ReGuard的用法。通過單擊“Start”按鈕,啟動ReGuard進行可重入漏洞分析。檢測完成後,將在底部生成一個bug報告,如圖7所示。在這種情況下,第8行突出顯示了一個可重入漏洞,即,以太幣轉賬操作使用call.value() API在withdraw函數。

ReGuard:智能合約中可重入漏洞檢測

圖7:分析結果示例

ReGuard:智能合約中可重入漏洞檢測

表1:可重入漏洞分析結果

除了報告的錯誤之外,ReGuard還進一步顯示瞭解釋可重入漏洞的調用堆棧信息。具體地說,在執行第8行時,將調用消息發送方的回調函數。在回調函數中,發送方再次調用回調函數。由於第8行沒有引入任何保護邏輯,所以可重入調用仍然傳遞,並傳輸額外的以太幣。調用堆棧信息使開發人員能夠更好地理解錯誤並設計修復補丁。

在這篇論文中,我們介紹了ReGuard,一個智能合約中可重入漏洞的動態分析器。ReGuard利用fuzzing的技術來生成隨機且多樣的區塊鏈事務,以作為可能的攻擊。然後,ReGuard通過運行時跟蹤分析執行錯誤檢測。我們已經實現了web工具來實現ReGuard的功能。在5個修改後的智能合約中,ReGuard識別了7個錯誤,並避免了誤報。

本文的主要貢獻:

(1)提出了一個新的檢測智能合約中可重入漏洞的框架,填補了已有工具對於準確檢測可重入漏洞的空白

(2)實現了ReGuard的web端工具

(3)提出了一種由Solidity語言到C++語言的一種漏洞檢測策略

致謝

本文由南京大學軟件學院2016級本科生徐光耀翻譯轉述


分享到:


相關文章: