EOS節點遠程代碼執行漏洞—EOS智能合約WASM函數表數組越界
漏洞報告者
Yuki Chen of Qihoo 360 Vulcan Team
Zhiniang Peng of Qihoo 360 Core Security
漏洞描述
我們發現了EOS區塊鏈系統在解析智能合約WASM文件時的一個越界寫緩衝區溢出漏洞,並驗證了該漏洞的完整攻擊鏈。
使用該漏洞,攻擊者可以上傳惡意的智能合約至節點伺服器,在節點伺服器解析惡意合約後,攻擊者就能夠在節點伺服器上執行任意代碼並完全控制伺服器。
在控制節點伺服器後,攻擊者可以將惡意合約打包進新的區塊,進而攻擊和控制其他新的節點,最終攻擊和控制整個EOS網路。
漏洞報告時間線
2018-5-11 發現EOS越界寫緩衝區溢出漏洞
2018-5-28 測試開發了完整攻破EOS超級節點的漏洞驗證程序
2018-5-28 將漏洞細節報告給廠商
2018-5-29 廠商在Github託管代碼庫中修復漏洞,並關閉問題跟蹤項
2018-5-29 提醒廠商漏洞未完全修復
一些在Telegram上與Daniel Larimer的溝通細節:
我們嘗試和Daniel溝通並報告漏洞,Daniel回應我們在沒有修復漏洞情況下不會發布新版EOS,同時請求我們在有人公開測試漏洞前,先將漏洞報告提交給他。
Daniel給了我們一個官方的郵件地址,讓我們以郵件形式提交漏洞報告。
最後Daniel承諾在EOS的漏洞修復後,將給予我們公開致謝。
漏洞細節
這是一個緩衝區溢出越界寫漏洞
漏洞存在於在 libraries/chain/webassembly/binaryen.cpp文件的78行,
Function binaryen_runtime::instantiate_module:
for (auto& segment : module->table.segments) {
Address offset = ConstantExpressionRunner(globals).visit(segment.offset).value.geti32();
assert(offset + segment.data.size() table.initial);
for (size_t i = 0; i != segment.data.size(); ++i) {
table[offset + i] = segment.data[i];
}
}
這裡的table是一個std :: vector包含在函數表中的名稱,在將元素存儲到table中時,|offset| 欄位沒有被正確檢查。注意在設置該值之前是有一個assert 斷言的,它會檢查偏移量,但不幸的是assert 僅適用於Debug版本,不適用於發布版本。
table.resize(module->table.initial);
|module->table.initial| 這個代碼片段讀取的值是根據函數表聲明,在WASM文件中的讀取的,該欄位的有效值為0?1024。
|offset| 欄位的值是根據數據段從WASM文件中讀取的,它是一個帶符號的32位值。
所以通過這個漏洞,我們可以在table向量之後的內存,越界寫入一定範圍的內容。
重現漏洞過程
1.編譯最新的EOS代碼release版本
./eosio-build.sh
2.啟動EOS節點Start EOS node, 完成如下所有必要的配置
https://github.com/EOSIO/eos/wiki/Tutorial-Getting-Started-With-Contracts
3.設置一個漏洞合約
我們提供了一個會造成程序崩潰的WASM漏洞驗證文件(POC)
在這個PoC中, 我們簡單的設置了 |offset| 欄位引用 0xfffffff地址,所以會觸發越界寫造成程序崩潰
開始測試 PoC:
cd poc
cleos set contract eosio ../poc -p eosio
順利的話我們會看到 nodeos 進程出現 segment fault錯誤
崩潰信息:
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000a32f7c in eosio::chain::webassembly::binaryen::binaryen_runtime::instantiate_module(char const*, unsigned long, std::vector >) ()
(gdb) x/i $pc
=> 0xa32f7c : mov %rcx,(%rdx,%rax,1)
(gdb) p $rdx
$1 = 59699184
(gdb) p $rax
$2 = 34359738360
Here |rdx| points to the start of the |table| vector,
And |rax| is 0x7FFFFFFF8, which holds the value of |offset| * 8.
利用漏洞實現遠程代碼執行
利用此漏洞可以在nodeos進程中實現遠程代碼執行,漏洞利用方法是將惡意合約上傳到受害節點,並讓節點解析惡意合約。而在真正的攻擊中,攻擊者可能會向EOS主網路發布惡意合約。
EOS超級節點解析惡意合約觸發漏洞後,攻擊者將可以完全控制這個節點。
攻擊者可以竊取超級節點的私鑰或控制新區塊的內容,更重要的是攻擊者可以將惡意合約打包成一個新塊並發布進行攻擊,最終整個網路中的所有節點都將受到攻擊並被控制。
我們完成了概念性的漏洞驗證程序,並在基於64位Ubuntu系統的nodeos上進行了測試。這個漏洞的攻擊過程是這樣的:
1.攻擊者將惡意合約上傳到nodeos伺服器。
2.伺服器nodeos進程解析引發漏洞的惡意合約。
3.使用越界寫入的原生代碼,我們可以覆蓋WASM模塊實例的WASM內存緩衝區,在惡意WASM代碼的幫助下,最終可以在nodeos進程中實現了任意內存讀/寫操作,並繞過了64位操作系統上的DEP / ASLR等常見的攻擊緩解技術。
4.漏洞利用一旦成功,會啟動一個反向shell連接攻擊者。
可以參考我們提供的視頻,了解這個概念性的漏洞利用過程,稍後我們可能會提供完整的漏洞利用鏈。
(請移步觀看http://v.youku.com/v_show/id_XMzYzMTg1NjYwMA==.html)
漏洞修復
Bytemaster在EOS的Github託管項目中,為我們報告的漏洞建立了3498編號的issue跟進修復問題。
修復的相關代碼
但是根據此次漏洞發現者Yuki所提交的評論,這個漏洞並沒有完全被修復,在32位進程的處理過程中仍然存在問題。
※2018年第一季度的DDoS攻擊概況
※necp_client_action系統調用中的堆溢出漏洞分析
TAG:嘶吼RoarTalk |