作者:yudan@慢霧安全團隊
公眾號:慢霧科技

相關閱讀:

前言

昨日(2019年3月10日)凌晨,EOS游戲 Vegas Town(合約帳號 eosvegasgame)遭受攻擊,損失數千 EOS。慢霧安全團隊及時捕獲這筆攻擊,并同步給相關的交易所及項目方。本次攻擊手法之前沒有相同的案例,但可以歸為假充值類別中的一種。對此慢霧安全團隊進行了深入的分析。

攻擊回顧

根據慢霧安全團隊的持續分析,本次的攻擊帳號為 fortherest12,通過 eosq 查詢該帳號,發現首頁存在大量的錯誤執行交易:

查看其中任意一筆交易,可以發現其中的失敗類型均為 hard_fail:

這立即就讓我想起了不久前的寫過的一篇關于 EOS 黑名單攻擊手法的分析,不同的是實現攻擊的手法,但是原理是類似的,就是沒有對下注交易的狀態進行分析。

攻擊分析

本次攻擊的一個最主要的點有兩個,一個是 hard_fail,第二個是上圖中的延遲。可以看到的是上圖中的延遲竟達到了 2 個小時之久。接下來我們將對每一個要點進行分析。

(1)hard_faild:

參考官方開發文檔(https://developers.eos.io/eosio-nodeos/docs/how-to-monitor-state-with-state-history-plugin)

可以得知 fail 有兩種類型,分別是 soft_fail 和 hard_fail,soft_fail 我們遇見的比較多,我們一般自己遇到合約內執行 eosio_assert 的時候就會觸發 soft_fail ,回看官方對 soft_fail 的描述:客觀的錯誤并且錯誤處理器正確執行,怎么說呢?拿合約內 eosio_assert 的例子來說

{
  //do something
  eosio_assert(0,"This is assert by myself");
  //do others
}

這種用戶自己的錯誤屬于客觀錯誤,并且當發生錯誤之后,錯誤處理器正確執行,后面提示的內容 This is assert by myself 就是錯誤處理器打印出來的消息。

那么 hard_fail 是什么呢?回看官方對 hard_fail 的描述:客觀的錯誤并且錯誤處理器沒有正確執行。那又是什么意思呢?簡單來說就是出現錯誤但是沒有使用錯誤處理器(error handler)處理錯誤,比方說使用 onerror 捕獲處理,如果說沒有 onerror 捕獲,就會 hard_fail。

OK,到這里,我們已經明白了 hard_fail 和 soft_fail 的區別,接下來是怎么執行的問題,傳統的錯誤拋出都是使用 eosio_assert 進行拋出的,自然遇到 hard_fail 機會不多,那怎么拋出一個 hard_fail 錯誤呢?我們繼續關注下一個點---延遲時間

(2)延遲時間:

很多人可能會疑惑,為什么會有延遲時間,我們通過觀察可以知道 fortherest12 是一個普通帳號,我們慣常知道的延時交易都是通過合約發出的,其實通過 cleos 中的一個參數設置就可以對交易進行延遲,即使是非合約帳號也可以執行延遲交易,但是這種交易不同于我們合約發出的 eosio_assert,沒有錯誤處理,根據官方文檔的描述,自然會變成 hard_fail。而且最關鍵的一個點是,hard_fail 會在鏈上出現記錄。

攻擊細節分析

根據 jerry@EOSLive 錢包的講解,本次的攻擊發生和 EOS 的機制相關,當交易的延遲時間不為 0 的時候,不會立馬校驗是否執行成功,對延遲交易的處理是 push_schedule_transaction,而交易的延遲時間等于 0 的時候,會直接 push_transaction。這兩個的處理機制是存在區別的。

攻擊成因

本次攻擊是因為項目方沒有對 trx 的 status 狀態進行校驗,只是對 trx 是否存在作出了判斷。從而導致了本次攻擊的發生。

防御手法

項目方在進行線下開獎的時候,要注意下注訂單的執行狀態,不要只是判斷交易是否存在,還要判斷下注訂單是否成功執行。如下圖

相關參考

引起 object fail 的錯誤類型參考:https://eos.live/detail/16715

官方對交易執行狀態的描述:https://developers.eos.io/eosio-nodeos/docs/how-to-monitor-state-with-state-history-plugin


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/848/