近一個月內,區塊鏈安全公司 PeckShield 已經發現並披露了 EOSBet、EOSCast、FFgame、EOSDice、EOSWin、MyEosVegas、LuckyGo、EOS Lelego 等超8款 EOS 競猜類遊戲遭到了黑客攻擊,黑客總共獲利170,503.5個 EOS,以此前行情均價35元/個估算,黑客已從此類遊戲上獲利超5,967,662.5元,已嚴重威脅到正常的 EOS 生態秩序。 

PeckShield 安全人員通過對多款遊戲的攻擊特徵進行提取,初步發現:1、攻擊者背後有不同黑客團伙在實施有組織且針對性的攻擊;2、大部分成功攻擊的原因都和隨機數漏洞有關;3、類似的攻擊有可能愈加頻繁,且他們的攻擊效率有逐漸提升的跡象。

由於絕大部分 EOS 競猜類遊戲尚未開源,為了釐清隨機數漏洞背後的技術原理,摸清楚黑客屢屢攻擊得手的原因。PeckShield 安全團隊以較為典型的 EOS.WIN 遊戲為樣本進行了黑客視角還原,帶大家領略下隨機數漏洞攻擊背後的奧祕。

11月12日,據 PeckShield 態勢感知平臺數據顯示:上午08:59至09:00,不到一分鐘時間,黑客共計向 EOS.WIN 遊戲合約(eosluckydice)發起10次攻擊,獲利超9,180個 EOS。PeckShield 安全人員跟蹤分析發現,黑客先是於昨晚22:46實施小額測試攻擊,在攻擊165次掌握攻擊方法後,選擇於次日9時許採用多個關聯賬號實施快速攻擊。儘管該款遊戲也採用了較為穩妥的兩次延遲交易(deferred transaction)的資訊作為隨機數的組成部分,但是黑客仍然巧妙地繞過了這些限制,成功地實施了攻擊。

黑客攻擊原理及開獎過程:

EOS.WIN 主要是由猜數字和21點兩個遊戲組成,猜數字遊戲玩法,使用者可以任意選取一個數字,系統會根據使用者所選大小給出相應賠率,然後系統會隨機給出一個數字,如果結果和使用者的大小選擇匹配則視為中獎,獲得金額為投入金額乘以賠率。

該遊戲的開獎過程為:遊戲合約收到玩家的交易請求,延遲1.5秒後執行開獎方法(resolved 函式),並在開獎方法中使用開獎序號參與隨機數生成,同時通過內聯呼叫方式將開獎結果資訊通知給玩家(receipt 函式),再將開獎序號加1並儲存。開獎流程如下圖所示: 

圖示1:DICE類遊戲開獎流程

PeckShield 安全人員分析發現,該合約的隨機數是通過 get_random 函式獲得,影響該隨機數生成的因素有:txid 為交易雜湊 ID, tapos_block_num成交塊高度, tapos_block_prefix 區塊 ID 字首, bet_id 全域性開獎序號等。

為了進一步深入瞭解,先得科普幾個背景知識:

1、延遲交易與 tapos_block_prefix:常見的隨機數生成方法中,大多使用 tapos_block_num 和 tapos_block_prefix  作為重要的組成部分,在交易中指定未來某個區塊的資訊,來保證不可預測性。如果合約中使用了延遲交易的方式,也就是說在交易時(比如開獎)指定了延遲的間隔,看似是使用未來資訊,其實在發出這個交易時,系統就已經指定使用當前同步到的最新塊(head_block)資訊,進而 tapos_block_num 和 tapos_block_prefix 也是確定的。

2、交易狀態資訊回滾:在 EOS 的交易中,如果一個交易中的某個動作(action)執行異常,會導致整個交易狀態的回滾。例如在自己的帳號中部署合約,在每次收到轉賬通知(transfer receipt)時拋異常,可以導致整個轉賬過程失敗,所有的狀態資訊,包括餘額等都保持原樣。

3、計算交易雜湊 ID:一個交易(transaction)中可以包含多個 action,如果所有 action 引數資訊都確定,那麼再結合前面提到的 tapos_block_prefix (ref_block_prefix) 資訊,就能自己計算出交易雜湊 ID。

簡而言之,攻擊者利用了開獎序號( bet_id)參與隨機數生成和內聯呼叫失敗可導致狀態資訊回滾的特性,在同一時間控制多個合約帳號同時傳送交易請求,來儘量保證最後請求的帳號能夠獲得期望的開獎序號參與生成隨機數,以贏得獎勵。以 EOS.WIN 為例,攻擊者先是用5個賬號佯攻實施小金額投注,在掌握更高概率後,用最後1個金額最大的賬號主攻投注,從而以更高概率斬獲獎金。

具體攻擊過程如下(如下圖):

一、攻擊者部署了6個攻擊合約,呼叫攻擊方法時,在攻擊合約中同時讓這6個帳號傳送交易請求,這樣這些請求將會在同一個塊中開獎,由於過程一致,開獎交易中的 tapos_block_num 和 tapos_block_prefix 是一樣的,只有bet_id可能不同。

二、攻擊者的前5個攻擊合約,在收到開獎通知時,能夠獲取到當前的 bet_id,並判斷此 id 能否讓最後的帳號中獎。

1)如果計算得知最後的帳號不能中獎,則該帳號的開獎通知正常執行,使得後面的帳號使用新的開獎序號來計算隨機數;

2)如果計算得知最後的帳號能中獎,則使該帳號的開獎通知失敗,那麼這個開獎序號被保留下來,直到最後的帳號中獎;

圖示2:攻擊者多賬號實施攻擊過程

獲獎概率:

從上述的開獎和攻擊過程可知,每增加一個佯攻的帳號,就多了一次提前計算最後主攻帳號能否獲獎的機會。按猜數選擇20來算賠率為5倍,6個帳號會提高中獎概率至大約74%,雖然仍無法保證每次攻擊必中獎,但攻擊者10次攻擊能中獎6次,已經是超高且擾亂正常遊戲的秩序的獲獎概率。

安全建議:

在諸如此類 EOS.Win 的遊戲中隨機數受到攻擊者可控制的變數即遊戲開獎序號(bet_id)的影響,因此PeckShield在此建議開發者,在 DApp 的隨機數生成上,需要去除攻擊者可控制的變數如遊戲開獎序號等影響,同時避免開獎動作和通知動作(receipt)在同一個交易中,從而避免交易狀態的回滾,進而阻止來自黑客的攻擊。


--------------------- 
作者:PeckShield 
來源:CSDN 
原文:https://blog.csdn.net/PeckShield/article/details/84335728 
版權宣告:本文為博主原創文章,轉載請附上博文連結!