激情六月丁香婷婷|亚洲色图AV二区|丝袜AV日韩AV|久草视频在线分类|伊人九九精品视频|国产精品一级电影|久草视频在线99|在线看的av网址|伊人99精品无码|午夜无码视频在线

高校合作1:010-59833514 ?咨詢電話:400-810-1418 服務(wù)與監(jiān)督電話:400-810-1418轉(zhuǎn)接2

類Fomo3D游戲漏洞與修復(fù)方案全解析

發(fā)布時(shí)間:2024-03-07 09:36:52 瀏覽量:249次


摘要:無(wú)論是 Fomo3D 山寨版還是正宗原版都擺脫不了"一輪就涼涼"的宿命,這與其智能合約的設(shè)計(jì)漏洞不無(wú)關(guān)系。本文從合約安全開(kāi)發(fā)的角度出發(fā),詳細(xì)分析了類 Fomo3D 游戲的兩個(gè)問(wèn)題,并提出若干個(gè)可能的解決方案。希望能有所幫助,歡迎感興趣的朋友加入技術(shù)社區(qū)討論。

黑客攻擊之下,類 Fomo3D 游戲一蹶不振

Fomo3D 游戲已正式進(jìn)入第三輪。截止北京時(shí)間 9 月 29 日上午 11 點(diǎn)整,本輪獎(jiǎng)池僅累積了 97.8988 Ether,外加上一輪滾入的 680 Ether,獎(jiǎng)池總金額不足 800 Ether,相較前兩輪的盛況,可謂慘不忍睹。

安比(SECBIT)實(shí)驗(yàn)室曾經(jīng)撰文分析了類 Fomo3D 游戲的衰敗現(xiàn)狀,先來(lái)簡(jiǎn)單回顧一下 [1]。

圖一:Fomo3D 玩家參與度與入場(chǎng)資金狀況

上圖展示了「Fomo3D 玩家參與度與入場(chǎng)資金狀況」。紅色代表調(diào)用合約參與游戲的人次,藍(lán)色則代表進(jìn)入游戲合約的資金量。圖左側(cè)出現(xiàn)數(shù)據(jù)曲線最高峰,對(duì)應(yīng)時(shí)間分別是 7 月 20 日和 7 月 21 日。這兩天恰好大量媒體瘋狂報(bào)道 Fomo3D 這一現(xiàn)象級(jí)游戲。當(dāng)時(shí)眾多玩家跟風(fēng)入場(chǎng),游戲合約的參與次數(shù)和入場(chǎng)資金均達(dá)到了最高峰,入場(chǎng)資金量超過(guò) 40,000 Ether,而參與次數(shù)最高超過(guò) 18,000 次。高峰過(guò)后,F(xiàn)omo3D 游戲熱度驟降,于 8 月 22 日前后結(jié)束第一輪,并隨即進(jìn)入第二輪,但游戲熱度已然無(wú)法恢復(fù)。

盡管如此,黑客卻沒(méi)有停止攻擊。

圖二:Fomo3D 游戲合約被攻擊狀況

上圖是「Fomo3D 游戲合約被攻擊狀況」,第一輪游戲高峰前后以及第二輪開(kāi)始后,有黑客瘋狂地利用"空投漏洞"進(jìn)行攻擊,攫取高額收益 [2]。而在第一輪臨近結(jié)束,以及第二輪倒計(jì)時(shí)快結(jié)束之際,則有黑客瘋狂嘗試"阻塞交易"攻擊,企圖奪取最終大獎(jiǎng) [3]。

不僅僅是 Fomo3D 原版游戲,其他眾多的類 Fomo3D 山寨游戲,也成為黑客的攻擊目標(biāo)。

Fomo3D 類游戲參與形式是用 Ether 購(gòu)買游戲道具,最后一位購(gòu)買者獲得"最終大獎(jiǎng)",平時(shí)參與者有一定概率獲得"空投獎(jiǎng)勵(lì)",分別從主獎(jiǎng)池和副獎(jiǎng)池中獲取。這兩類獎(jiǎng)勵(lì)是游戲設(shè)計(jì)層面對(duì)參與者的重要激勵(lì)。這一設(shè)計(jì),目的在于利用"隨機(jī)"和"競(jìng)爭(zhēng)"提升游戲趣味度,吸引更多人投入資金參與,從而延長(zhǎng)游戲時(shí)間。

然而事與愿違,由于合約代碼存在漏洞,掌握攻擊技巧的黑客能夠以很高的概率持續(xù)獲得"空投獎(jiǎng)勵(lì)",而"最終大獎(jiǎng)"也會(huì)被黑客利用特殊技巧奪走。普通參與者在這類游戲中幾乎無(wú)法獲得這兩種重要獎(jiǎng)勵(lì)。因此,他們僅能幻想在每輪游戲開(kāi)始后第一時(shí)間入場(chǎng),然后靠后續(xù)他人的資金回本。但是,游戲最重要的兩個(gè)激勵(lì)機(jī)制已然失效,無(wú)法持續(xù)吸引新資金,最終形成惡性循環(huán)。

黑客是如何利用這兩個(gè)漏洞的?項(xiàng)目方難道就無(wú)計(jì)可施嗎?

空投漏洞分析

先看看"空投獎(jiǎng)勵(lì)"。

所有投入游戲的 Ether,會(huì)有 1% 數(shù)量進(jìn)到副獎(jiǎng)池??胀兜母怕蕪?0% 開(kāi)始,每增加一筆不小于 0.1 ETH 銷售訂單,空投概率會(huì)增加 0.1%。同時(shí)空投獎(jiǎng)勵(lì)金額與購(gòu)買金額也掛鉤,如果購(gòu)買 0.1 ~ 1 ETH,就有概率贏得 25% 副獎(jiǎng)池獎(jiǎng)金,購(gòu)買越多則比例越大。游戲界面會(huì)鮮明顯示當(dāng)前中獎(jiǎng)概率和獎(jiǎng)池金額。

Fomo3D 空投獎(jiǎng)勵(lì)實(shí)現(xiàn)存在兩處問(wèn)題:

1. 合約中的"隨機(jī)數(shù)"可被預(yù)測(cè)

1. 判斷調(diào)用者是否是合約地址的方法有漏洞

空投獎(jiǎng)勵(lì)依靠智能合約內(nèi)生成的"隨機(jī)數(shù)",在 Fomo3D 源碼中由 airdrop() 函數(shù)控制。

airdrop() 函數(shù)中的"隨機(jī)數(shù)" seed 由各種區(qū)塊信息和交易發(fā)起者地址計(jì)算得來(lái)。這顯然十分容易預(yù)測(cè) [4]。

為了防止合約自動(dòng)化攻擊,F(xiàn)omo3D 開(kāi)發(fā)者還使用 isHuman() 來(lái)防止合約賬戶參與 Fomo3D 游戲,試圖以此方法來(lái)禁止玩家在合約內(nèi)預(yù)測(cè)中獎(jiǎng)隨機(jī)數(shù)。

這里犯了另一個(gè)常見(jiàn)錯(cuò)誤。extcodesize 操作符用來(lái)獲取目標(biāo)地址上的代碼大小。對(duì)于已部署成功的合約,由于其地址對(duì)應(yīng)著特定代碼,extcodesize 的返回值始終大于 0。因此不少人用此方法來(lái)判斷目標(biāo)地址是否是合約,F(xiàn)omo3D 甚至以此為依據(jù)來(lái)阻止合約調(diào)用特定函數(shù)。但該判斷方法存在明顯漏洞,在構(gòu)造新合約的過(guò)程中(即合約構(gòu)造方法里)調(diào)用游戲參與函數(shù)即可繞過(guò)該限制。這是因?yàn)楹霞s在構(gòu)造過(guò)程中,其地址并未對(duì)應(yīng)任何代碼,extcodesize 的返回值為 0 [5]。

上述的兩個(gè)安全問(wèn)題綜合作用,最終導(dǎo)致黑客可以構(gòu)造攻擊合約,通過(guò)合約參與游戲,隨意預(yù)測(cè)隨機(jī)數(shù),進(jìn)而極大提高自己的勝率 [2]。

如何修復(fù)空投漏洞

那么究竟如何解決 Fomo3D 的"空投漏洞"?

黑客能夠成功攻擊,是利用了上文列出的兩個(gè)漏洞,構(gòu)造攻擊合約來(lái)預(yù)測(cè)游戲合約中的"隨機(jī)數(shù)"。因此,我們只需完成以下兩件事之一,使攻擊所需的必要條件不滿足即可:

1. 防止智能合約中的"隨機(jī)數(shù)"預(yù)測(cè)

1. 采取更安全的方式判斷調(diào)用者是否是合約

方案一:防范智能合約中的"隨機(jī)數(shù)"預(yù)測(cè)

讓我們先解決"隨機(jī)數(shù)"預(yù)測(cè)的問(wèn)題。

智能合約環(huán)境內(nèi)"隨機(jī)數(shù)"容易被預(yù)測(cè)的原因在于,"隨機(jī)數(shù)"產(chǎn)生所依賴的"隨機(jī)源"可以被任何人輕易獲得。攻擊者可以構(gòu)造一個(gè)攻擊合約,在相同環(huán)境內(nèi)執(zhí)行"隨機(jī)數(shù)"計(jì)算公式,即可得到需要的"隨機(jī)數(shù)",并以之作為下一步行動(dòng)的判斷依據(jù)。

智能合約內(nèi)幾乎一切可用變量都是公開(kāi)的,并且"隨機(jī)數(shù)"計(jì)算公式需要確保所有節(jié)點(diǎn)執(zhí)行結(jié)果都一致。因此,很難找到十分簡(jiǎn)潔的方法來(lái)產(chǎn)生無(wú)法被預(yù)測(cè)的"隨機(jī)數(shù)"。

但仍有一些稍復(fù)雜但可行的解決方案。如開(kāi)發(fā)者可通過(guò)先提交再披露(commit/reveal)、或延遲若干個(gè)區(qū)塊開(kāi)獎(jiǎng)。此外,還有一些引入外部預(yù)言機(jī)(Oracle)的方案,如 Oraclize 和 BTCRelay [6]。

安比(SECBIT)實(shí)驗(yàn)室結(jié)合 Fomo3D 游戲機(jī)制,介紹一種利用"當(dāng)前/未來(lái)"區(qū)塊的哈希值來(lái)防止"隨機(jī)數(shù)"被預(yù)測(cè)的方案 [7]。

以太坊智能合約中可以通過(guò) block.blockhash() 來(lái)獲取特定區(qū)塊的哈希值。該函數(shù)接受參數(shù)為區(qū)塊高度,可取范圍為除當(dāng)前區(qū)塊外的最近 256 個(gè)區(qū)塊。當(dāng)傳入其他值時(shí),該函數(shù)均返回 0。

常見(jiàn)不安全的"隨機(jī)數(shù)"計(jì)算方法,會(huì)讀取當(dāng)前塊的前一個(gè)塊的哈希 block.blockhash(block.number-1) 作為隨機(jī)源。而在合約內(nèi)執(zhí)行 block.blockhash(block.number) 返回值為 0。我們無(wú)法在合約內(nèi)獲得當(dāng)前區(qū)塊的哈希,這是因?yàn)榈V工打包并執(zhí)行交易時(shí),當(dāng)前區(qū)塊哈希尚未被算出。因此,我們可以認(rèn)為"當(dāng)前區(qū)塊"哈希是"未來(lái)"的,無(wú)法預(yù)測(cè)。

我們可以在用戶首次購(gòu)買道具參與游戲時(shí),記錄其地址、當(dāng)前區(qū)塊高度 N 至一個(gè)數(shù)組中,最終拿到一個(gè)唯一的 id(如下面 _purchase() 函數(shù)所示)。

在接下來(lái)的 255 個(gè)區(qū)塊內(nèi),用戶可以用該 id 再次參與游戲,此時(shí)高度為 N 的區(qū)塊哈??烧+@得,以此來(lái)生成"隨機(jī)數(shù)",判斷用戶是否中獎(jiǎng)(如下面 _airdrop() 函數(shù)所示)。

255 個(gè)區(qū)塊之后,用戶參與游戲時(shí)的區(qū)塊哈希在合約內(nèi)無(wú)法正常獲得。因此,務(wù)必要限制用戶在一定時(shí)間范圍內(nèi)查詢是否中獎(jiǎng),并及時(shí)參與游戲領(lǐng)取獎(jiǎng)勵(lì)。當(dāng)然,為了游戲體驗(yàn),如果用戶錯(cuò)失領(lǐng)獎(jiǎng),也可以參照上面的原理再給他一次機(jī)會(huì)重新抽獎(jiǎng)。結(jié)合游戲規(guī)則,這里仍有一些技術(shù)細(xì)節(jié)需注意,歡迎添加小安同學(xué)微信(secbit_xiaoanbi),加入到「SECBIT 智能合約安全技術(shù)群」參與討論。

這種方法也用在知名的區(qū)塊鏈卡牌游戲 Gods Unchained 中,用來(lái)控制用戶所購(gòu)卡牌稀有程度。當(dāng)然我們也可以用當(dāng)前高度后指定數(shù)量(如五個(gè))的區(qū)塊哈希來(lái)作為隨機(jī)源,原理是一樣的 [8]。

方案二:防止合約自動(dòng)化攻擊

另一個(gè)問(wèn)題,我們?nèi)绾闻袛嗾{(diào)用者是否是合約地址?

有一個(gè)簡(jiǎn)便但是有效的方法。

以太坊安全開(kāi)發(fā)最佳實(shí)踐中推薦盡量不要使用 tx.origin,因?yàn)楹芏嗳藢?tx.orign 和 msg.sender 混淆。tx.orign 代表的是一筆交易的發(fā)起者,而 msg.sender 代表每一次合約調(diào)用(call)的發(fā)起者。

如普通賬戶 A 調(diào)用合約 B,合約 B 再調(diào)用合約 C。在合約 C 內(nèi),msg.sender 是合約 B,而 tx.origin 是賬戶 A。msg.sender 可以是合約地址,但 tx.origin 永遠(yuǎn)不會(huì)是合約。因此,上面的方法可以有效防止合約調(diào)用合約。

"阻塞交易"攻擊分析

再看看"最終大獎(jiǎng)"。

Fomo3D 類游戲存在倒計(jì)時(shí),在每輪游戲結(jié)束前最后一個(gè)購(gòu)買道具的參與者獲勝,可以拿走主獎(jiǎng)池中近半的資金。因此眾多參與者會(huì)在臨近結(jié)束時(shí),發(fā)起購(gòu)買交易參與游戲,如果能幸運(yùn)地在最后一刻被礦工打包入塊,即可獲勝。

普通人在游戲快結(jié)束時(shí)都是類似的策略:緊盯著時(shí)間,調(diào)高 Gas 費(fèi)用,發(fā)起參與游戲的交易,然后閉上眼睛祈禱,希望自己能是最后一個(gè)參與者。然而,采用這種方法幾乎不可能中獎(jiǎng)。

據(jù)安比(SECBIT)實(shí)驗(yàn)室分析,F(xiàn)omo3D 前兩輪獲獎(jiǎng)?wù)呤褂檬址ㄈ绯鲆晦H,均在游戲快結(jié)束時(shí),發(fā)起攻擊交易。

獲獎(jiǎng)?wù)撸ê诳停┩ㄟ^(guò)提前部署好的攻擊合約,在合約內(nèi)調(diào)用 getCurrentRoundInfo() 接口查詢游戲信息,重點(diǎn)關(guān)注剩余時(shí)間最后一位購(gòu)買者地址。當(dāng)游戲剩余時(shí)間達(dá)到一個(gè)閾值,并且最后一個(gè)購(gòu)買者是自己時(shí),則通過(guò) assert() 讓整個(gè)交易失敗,并耗光所有 Gas;當(dāng)剩余時(shí)間很長(zhǎng)或最后一個(gè)購(gòu)買者不是自己時(shí),則不做任何操作,僅消耗很少的 Gas。

獲獎(jiǎng)?wù)撸ê诳停┚褪抢眠@種方法,發(fā)起大量類似的可變神秘交易:在自己極有可能成為中獎(jiǎng)?wù)邥r(shí),利用這些高額手續(xù)費(fèi)的神秘交易,吸引礦池優(yōu)先打包,占滿后續(xù)區(qū)塊,從而使得其他玩家購(gòu)買 key 的交易無(wú)法被正常打包,最終加速游戲結(jié)束,并極大地提高自己的中獎(jiǎng)概率。

普通玩家只能在游戲快結(jié)束時(shí)手動(dòng)調(diào)高 Gas 費(fèi)用參與游戲,也有人試圖使用自動(dòng)腳本在臨近游戲結(jié)束時(shí)調(diào)高 Gas Price 發(fā)起參與游戲交易。與這些盲目的方法相比,黑客的攻擊手法顯然高明許多。

如何防范"阻塞交易"攻擊

其實(shí),這一問(wèn)題不止會(huì)威脅類 Fomo3D 游戲。所有采用類似機(jī)制,即需要玩家搶在某個(gè)時(shí)間范圍內(nèi)完成某種競(jìng)爭(zhēng)操作的智能合約,都會(huì)受此威脅。只要游戲獎(jiǎng)勵(lì)足夠豐厚,攻擊回報(bào)遠(yuǎn)大于投入,就會(huì)有人利用前文提到的方法來(lái)破壞游戲公平性。

方案一:提高攻擊所需成本

要杜絕這一問(wèn)題,安比(SECBIT)實(shí)驗(yàn)室建議游戲開(kāi)發(fā)者,從游戲機(jī)制入手,切斷游戲最終勝利(獲得某個(gè)巨額大獎(jiǎng))和倒計(jì)時(shí)結(jié)束(最后一個(gè)交易被打包)之間的必然聯(lián)系,從而使黑客的攻擊獲利概率攻擊意愿都降到最低。

例如,我們可以修改游戲規(guī)則為:每輪游戲結(jié)束前最后一個(gè)購(gòu)買道具的參與者有概率獲得最終大獎(jiǎng),并將此概率調(diào)整為一個(gè)較低的值,如 5 %。在倒計(jì)時(shí)結(jié)束但大獎(jiǎng)因概率原因沒(méi)有正常開(kāi)出的情況下,合約自動(dòng)給游戲續(xù)一定時(shí)間。這樣一來(lái),前面提到的堵塞區(qū)塊、阻止別人參與游戲的技巧,無(wú)法確保攻擊者一定能獲得最終大獎(jiǎng)。而黑客持續(xù)進(jìn)行"阻塞交易"攻擊需耗費(fèi)大量 Gas 費(fèi)用,成本會(huì)很高,最終會(huì)選擇放棄攻擊。

上面為示例代碼,其中 shouldRndEnd() 函數(shù)用來(lái)在倒計(jì)時(shí)結(jié)束后控制中獎(jiǎng)概率,決定這一輪游戲是否真的結(jié)束。這里的概率同樣依賴"隨機(jī)數(shù)"不能被預(yù)測(cè),具體實(shí)現(xiàn)原理與前文提到的空投概率控制代碼類似。

方案二:禁止合約調(diào)用游戲信息查詢接口

Fomo3D 最終獲勝者可以輕易攻擊成功的另一個(gè)原因是,游戲合約開(kāi)放了一個(gè)完整的游戲進(jìn)度信息查詢接口,并且普通賬戶和合約賬戶都可以任意調(diào)用查詢。這方便了黑客在攻擊合約內(nèi)實(shí)時(shí)查詢游戲狀態(tài),進(jìn)而執(zhí)行不同策略來(lái)降低攻擊成本和提高命中率。

因此,針對(duì) Fomo3D 游戲,還有另一個(gè)簡(jiǎn)易的防范方法。對(duì) getCurrentRoundInfo() 函數(shù)使用前文提到的安全版的 isHuman() 校驗(yàn)來(lái)保護(hù),就可以有效避免合約自動(dòng)化攻擊。

總結(jié)


有安全和公平性問(wèn)題的 Fomo3D 原版以及山寨版,僅是"黑客"掘金的對(duì)象,注定無(wú)法吸引更多普通玩家參加。隨著一輪一輪的進(jìn)行,玩家會(huì)逐漸流失,這些游戲會(huì)進(jìn)一步?jīng)]落。

安比(SECBIT)實(shí)驗(yàn)室呼吁后來(lái)者吸取教訓(xùn),不要再原封不動(dòng)地復(fù)制代碼,不要試圖僅靠"運(yùn)營(yíng)"來(lái)吸引新人入場(chǎng)。作出一些小小的改變,智能合約的安全性會(huì)得到很大的提升,去中心化游戲才能走得更遠(yuǎn)。

參考文獻(xiàn)

· [1] Fomo3D二輪大獎(jiǎng)開(kāi)出,黑客獲獎(jiǎng),機(jī)制漏洞成游戲沒(méi)落主因,
https://zhuanlan.zhihu.com/p/45330743, 2018/09/25

· [2] 智能合約史上最大規(guī)模攻擊手法曝光,盤點(diǎn)黑客團(tuán)伙作案細(xì)節(jié),
https://zhuanlan.zhihu.com/p/42318584, 2018/08/17

· [3] Fomo3D 千萬(wàn)大獎(jiǎng)獲得者"特殊攻擊技巧"最全揭露,
https://zhuanlan.zhihu.com/p/42742004, 2018/08/23

· [4] How to PWN FoMo3D, a beginners guide, https://www.reddit.com/r/ethereum/comments/916xni/howtopwnfomo3dabeginnersguide, 2018/07/23

· [5] Using EVM assembly to get the address' code size, https://ethereum.stackexchange.com/questions/14015/using-evm-assembly-to-get-the-address-code-size, 2017/04/07

· [6] Predicting Random Numbers in Ethereum Smart Contracts, https://blog.positive.com/predicting-random-numbers-in-ethereum-smart-contracts-e5358c6b8620, 2018/02/01

· [7] Random Number Generation on Winsome.io — Future Blockhashes, https://blog.winsome.io/random-number-generation-on-winsome-io-future-blockhashes-fe44b1c61d35, 2017/05/07

· [8] Gods Unchained, https://etherscan.io/address/0x482cf6a9d6b23452c81d4d0f0f139c1414963f89#code, 2018/07/16

熱門課程推薦

熱門資訊

請(qǐng)綁定手機(jī)號(hào)

x

同學(xué)您好!

您已成功報(bào)名0元試學(xué)活動(dòng),老師會(huì)在第一時(shí)間與您取得聯(lián)系,請(qǐng)保持電話暢通!
確定