智能合約平臺共識機制,本質上是將所有的交易【Tx_1 Tx_2 ……. Tx_n】按順序作用到初始State_0上,使全網始終保持相同的狀態。在狀態機復制過程中,我們要求State_n × Tx_èState_是決定性的。State_n × Tx_èState_實質上就是智能合約虛擬機對Tx_的執行過程,如果智能合約虛擬機中存在設計或者實現漏洞,導致虛擬機不一致性執行(對相同的輸入State_n 和Tx_,輸出State_不一致)。則攻擊者可以利用該問題在網絡中產生分叉和并進行雙花攻擊。下面我們介紹多個EOS和NEO上我們發現的虛擬機不一致執行漏洞和其產生原因。
4.1 EOS虛擬機內存破壞RCE漏洞:
此前,我們公開了文章《EOS Node Remote Code Execution Vulnerability --- EOS WASM Contract Function Table Array Out of Bound》(http://blogs.#/post/eos-node-remote-code-execution-vulnerability.html)。在該文中,我們發現了一個EOS WASM虛擬機的一個內存越界寫漏洞,針對該漏洞我們編寫的利用程序可以成功利用該漏洞使EOS虛擬機執行任意指令,從而完全控制EOS所有出塊和驗證節點。
究其本質而言,是在State_n × Tx_{n+1} → State_{n+1}過程中。攻擊者能讓EOS虛擬機完全脫離原本執行路徑,執行任意指令,自然可以完成雙花攻擊。其攻擊流程如下:
步驟1:攻擊者構造能夠實現RCE的惡意智能合約,并將該合約發布到EOS網絡中。
步驟2:EOS超級節點解析到該合約后,觸發漏洞,執行攻擊者自定義的任意指令。
步驟3:攻擊者實現雙花攻擊。
該漏洞的危害非常嚴重,且是第一次智能合約平臺受到遠程代碼執行攻擊事件。讀者可以閱讀該文章了解相關細節,在此不再贅述。
4.2 EOS虛擬機內存未初始化造成雙花攻擊:
我們在編寫《EOS Node Remote Code Execution Vulnerability --- EOS WASM Contract Function Table Array Out of Bound》的利用程序的過程中,還利用了EOS中當時的一個未公開的內存未初始化漏洞。在內存破壞攻擊中,內存未初始化漏洞通常能夠造成信息泄露、類型混淆等進一步問題,從而輔助我們繞過如ASLR之類的現代二進制程序的緩解措施,進一步實現攻擊。然而在智能合約虛擬機中,內存未初始化漏洞有更直接的利用方式,可以直接造成雙花攻擊。以下為我們在EOS RCE中利用的一個內存未初始化漏洞的細節,其可以被用來直接實現EOS智能合約代幣資產雙花攻擊。
當WASM虛擬機通過grow_memory偽代碼來申請內存新的內存。在EOS WASM grow_memory最初的實現中,未對申請到的內存進行清零操作。該塊內存的空間實際上是隨機的(依賴于合約執行機器的內存狀態)。則攻擊者可以構造惡意合約,實現對EOS上任意合約資產的雙花攻擊。其攻擊流程如下:
步驟1: 攻擊者構造惡意智能合約。合約中通過grow_memory獲得一塊新的內存地址。
步驟2:合約中讀取該地址中的某個bit內容(此時該bit可能為0,也可能為1,依賴于合約執行機器的狀態)。
步驟3:合約判斷該bit的內容,如果為1則發送代幣給A用戶,如果為0則發送代幣給B用戶,從而實現雙花攻擊。
4.3 EOS虛擬機內存越界讀造成雙花攻擊:
在傳統的內存破壞中,內存越界讀漏洞主要將會導致信息泄露,從而輔助我們繞過如ASLR之類的現代二進制程序的緩解措施,進一步與其他漏洞一起實現攻擊。然而在智能合約虛擬機中,內存越界讀漏洞有更直接的利用方式,可以直接造成雙花攻擊。下面為一個我們發現的EOS內存越界讀漏洞,我們可以利用該漏洞實現雙花攻擊。
當EOS WASM將一個offset轉換內WASM內存地址時,其邊界檢查過程如下: