![Penta 洞察|Fomo3D 遊戲被攻破後的反思](http://p2.ttnews.xyz/loading.gif)
本文於Medium首發,為方便中國社區閱讀,進行了中文翻譯
前言:以太坊網絡上備受矚目的、號稱永不結束的資金盤遊戲Fomo3D的第一輪在8月22日戛然結束,出乎大多數人的意外。最終大獎由地址 0xa169 獲得,獎金總額達到了 10469個以太坊。那麼這個玩家是靠運氣獲得了最後一把鑰匙,進而獲得大獎的嗎?顯然不是。這是黑客精心設計並且經過反覆測試的特殊攻擊所取得的結果。這名大獎獲得者巧妙利用了以太坊的技術弱點,採取了獨特的狙擊手段,使得連續多個區塊中礦工打包入區塊內的交易數量驟減,雖然在理論上並不能保證100%成功,但卻起到了大概率提高勝率的作用。
![Penta 洞察|Fomo3D 遊戲被攻破後的反思](http://p2.ttnews.xyz/loading.gif)
攻擊過程
下面讓我們覆盤一下當天黑客進行攻擊的全過程:
➊在區塊高度6191896,攻擊者0xa169 的購買鑰匙的交易被區塊打包。
➋在區塊高度 6191897 到 6191902,攻擊者開始使用垃圾合約來填充區塊,gasPrice被設置為20G wei左右的平均水平。不得不佩服黑客的耐心,以潛伏的方式對網絡中的交易進行監測,結果是之後的6 個區塊的時間內並沒有其他人參與購買 key,競爭者很少。
➌從區塊高度6191903 開始,攻擊者將合約調用交易的 gasprice 突然提高到了 190 GWei,遠高於平均水平,後續交易更是設置了 500 GWei的超高 gasprice,開始了真正的攻擊。直到 6191908 區塊,這 6 個區塊中每個區塊都只包含了不到10筆交易,可用 gas 完全被這些高 gasprice 的無效交易所佔用,以太坊網絡此時已經被堵塞。
➍在區塊高度 6191909,遊戲宣告結束,網絡狀況恢復正常。
圖中標紅區塊為攻擊集中發生區塊
圖中標紅區塊為攻擊集中發生區塊
黑客的整個攻擊過程計劃地非常縝密、高效、也很有耐心,一方面使用高的 gasprice 來吸引礦工打包該筆交易,又通過在以太坊虛擬機執行層面耗費大量的 gas 牢牢佔據區塊,實現堵塞整個 ETH 網絡的目標,從而在短時間內阻止了其他玩家的鑰匙交易的成功確認。
當然攻擊者的計劃並非萬無一失,曾經有一個 gasprice 高達 5559 GWei購買鑰匙的交易闖入了區塊6191907中。但很可惜的是這個交易的 gaslimit僅設置了 379000,gas limit不足導致發生了 out of gas的錯誤導致交易失敗,白白浪費了 2.1 Eth 的手續費,最終也和大獎失之交臂。
唯一突破黑客封鎖
寫入區塊的超高gas price交易
攻擊原理分析
交易可選擇性
➊手續費競爭
在以太坊中,礦工會從選取那些 gasprice 明顯高於其他交易的交易來優先打包執行,即為交易的可選擇性。基於手續費競爭的原理,就允許了黑客通過人為調高包含了無效合約調用交易的 gasprice,在短時間內用這些無意義的交易佔用區塊的可用 gas,以使其他正常交易無法被打包進區塊。
➋gas limit
以太坊中的區塊可包含的交易數是由區塊的 gaslimit 來控制的。區塊內能包含的交易數量,是看這些交易執行所消耗的總 gas 是否達到這個區塊的 gaslimit。目前區塊的 gaslimit 上限一般是 800 萬 gas。
以太坊上每筆交易也有 gas Limit 概念,交易發起者自行設定,代表該筆交易可最多消耗的 gas 上限,實際 gas 消耗以交易具體執行消耗為準。
➌無效指令
你可能要問攻擊者是如何順利地通過少量交易就佔用整個區塊的 gas limit?那就不得不提以太坊的智能合約Solidity 中三個指令可以撤銷合約執行中的所有狀態修改並導致合約執行異常停止的指令,分別是require、revert 和 assert。根據 EVM 的指令設計,調用require 和 revert 實際上最終都是使用了 EVM 操作碼 0xfd, 在程序停止執行時會進行回滾並返還交易執行所剩餘的 gas。而調用assert,則在條件滿足時會使用 EVM 操作碼 0xfe無效指令,從而消耗交易附帶的所有可用 gas。而耗光區塊的gas limit正是攻擊者樂於看到的結果,所以我們看到在遊戲結束前的十幾個區塊中存在很多由0xfe無效指令導致的Bad Instruction 失敗交易,均是由於assert指令觸發所導致的。
圖靈完備智能合約
以太坊提出的圖靈完備智能合約概念與比特幣簡單腳本系統相比有很多優勢,但也存在很大的安全風險,以太坊上線運行三年來,智能合約導致的安全事故屢出不窮。
➊無法預測gas使用量
上述失敗的攻擊者無法有效預測gas limit的原因正是由於fomo3d項目本身僅僅只是部分開源。其主合約0x9da1雖然開源,但查看其代碼發現仍有三個子合約並未對外開源。
➋反編譯
而以太坊Solidity語言目前並無任何的反編譯工具,所以無法通過代碼有效地預測或者驗證執行結果,只能通過跟蹤調用數據來反推。而缺乏形式化驗證也使得合約的安全性也無法得到充分的保證,而正是以太坊代碼層面的圖靈完備使得可以實現種類更多、條款更復雜的合約,當然的代價是複雜的合約內容使其變得更加難以分析,反倒給黑客發起攻擊提供了便利,由此也讓我們看到了限制代碼複雜度和功能性的必要性。
對公鏈項目設計的啟示
➊設計更加合理的手續費模型,而非以太坊僅僅通過EVM執行操作來收取gas。
➋取消0xfe等無效指令,gas消耗以實際使用為限,不允許濫用gas來堵塞區塊。
➌限制高gas消耗的指令在同一交易中可使用的次數,礦工可通過靜態代碼檢查來屏蔽該類交易。
➍採取措施限制未開源的智能合約上鍊。對未開源的智能合約以及對其進行調用的合約進行顯式標記,並且提供有效的智能合約反編譯工具。
➎簡化智能合約指令集。取消跳轉指令,並限制一般性循環指令的使用。同時鼓勵使用可預測的循環指令,從而起到便於對合約進行靜態檢查的目的。
從Fomo3d的大熱到被黑客攻破的遇冷,讓我們看到了以太坊作為區塊鏈交易載體以及目前運行的智能合約的侷限性。POW的共識算法導致了目前以太坊的交易吞吐量和可擴展性十分有限,也就使得攻擊者可以很輕易地便將網絡堵塞,而智能合約的複雜性又使得其安全性不能得到完全的保障,使得黑客有了可趁之機。
而Penta作為下一代公鏈基礎設施,正試圖解決以太坊存在的種種問題,在區塊鏈的性能、可擴展性以及安全性方面不斷改進和完善,比如DSC共識算法,PSG分片模型以及PDW智能合約引擎等等,通過多種途徑共同營造一個更加高效、公平、安全的區塊鏈生態網絡。
閱讀更多 Penta公鏈中文社區 的文章