以太坊智能合約安全分析工具:Mythril工具使用指南
Mythril 是一個(gè)免費(fèi)的以太坊智能合約的安全分析工具。Mythril 能檢測(cè)以太坊和其他兼容 EVM 的區(qū)塊鏈構(gòu)建的智能合約的安全漏洞,包括整數(shù)溢出、時(shí)間戳依賴、重入攻擊等。
因此,如果要對(duì)一個(gè)商用系統(tǒng)的智能合約進(jìn)行安全分析,我們建議使用成熟的商用化的安全審計(jì)產(chǎn)品,如 MythX、Certik、ChainSulting、OpenZeppelin 等。當(dāng)然,這些產(chǎn)品不是免費(fèi)的。
環(huán)境搭建
目前,Mythril 支持 MacOS 和 Ubuntu,不支持 Windows。
首先安裝 Mythril 的運(yùn)行環(huán)境。我們的操作系統(tǒng)環(huán)境是 Ubuntu(版本18.04),它是安裝在 Windows 10 系統(tǒng)虛擬機(jī) VMware 環(huán)境下的 Linux 系統(tǒng)。
安裝 Mythril 有PyPI 庫(kù)安裝和 Docker 安裝兩種方式,本課程我們以 Docker 安裝方式為例來(lái)詳細(xì)介紹 Mythril 工具的安裝。
Docker 安裝
所有的 Mythril 版本,從 v0.18.3 開(kāi)始,都以 mythril/myth 的名稱作為 Docker images 發(fā)布到 Docker Hub。
安裝 Docker
如果你的系統(tǒng)上已安裝了 Docker,請(qǐng)忽略。否則,通過(guò)下面的命令安裝 Docker:
安裝完成后默認(rèn) Docker 已啟動(dòng),通過(guò)下面的命令查看版本:
如果安裝成功,上面的命令會(huì)輸出 Docker 的版本號(hào),如下圖:

如果需要手動(dòng)啟動(dòng)和停止 Docker,請(qǐng)使用下面的命令:
查看 Docker 服務(wù)是否已啟動(dòng),請(qǐng)使用下面的命令:
如果 Docker 服務(wù)已啟動(dòng),控制臺(tái)輸出如下圖:

安裝 Docker 鏡像
通過(guò)下面的命令安裝最新版本的 Mythril:
安裝完成后,通過(guò)下面的命令查看版本:
如果安裝成功,上面的命令會(huì)輸出 Mythril 的版本號(hào),如下圖:

Mythril 用法
通過(guò)下面的命令查看 Mythril 的幫助:
Mythril 的幫助輸出如下圖:

通過(guò)下面的命令對(duì)合約源代碼進(jìn)行安全分析:
安全分析
用于分析的合約源碼
下面是一個(gè)用于安全分析的智能合約源碼,這個(gè)合約類似于一個(gè)抽獎(jiǎng)系統(tǒng),其邏輯是:(1)玩家向合約發(fā)送 1 個(gè)以太幣;(2)合約進(jìn)行邏輯判斷,在同一個(gè)區(qū)塊中對(duì)區(qū)塊時(shí)間戳除以 15 取模,當(dāng)結(jié)果為零時(shí),向玩家發(fā)送合約中剩余的以太幣作為獎(jiǎng)勵(lì)。
以上這個(gè)智能合約有一個(gè)時(shí)間戳依賴漏洞。時(shí)間戳依賴是指智能合約的執(zhí)行依賴于當(dāng)前區(qū)塊的時(shí)間戳,如果時(shí)間戳不同,那么合約的執(zhí)行結(jié)果也有差別。智能合約中取得時(shí)間戳只能依賴某個(gè)節(jié)點(diǎn)(礦工)來(lái)做到。這就是說(shuō),合約中取得的時(shí)間戳是可以由運(yùn)行其代碼的節(jié)點(diǎn)(礦工)決定的。理論上,這個(gè)時(shí)間是可以由礦工控制的。因此,如果在智能合約中不正確地使用區(qū)塊時(shí)間戳,這將是非常危險(xiǎn)的。
安全分析過(guò)程
接下來(lái),讓我們觀察 Mythril 工具對(duì)這個(gè)合約的檢測(cè)與分析結(jié)果。
首先,我們把這個(gè)合約文件發(fā)送到 Ubuntu 主機(jī)的 "/tmp" 目錄。
然后,通過(guò)以下命令來(lái)對(duì)合約源碼執(zhí)行檢測(cè)分析:
耐心等待幾分鐘后(這個(gè)執(zhí)行時(shí)間取決于主機(jī)的配置),我們看到檢測(cè)結(jié)果如下:
通過(guò)以上的檢測(cè)分析結(jié)果,我們可以看到,Mythril 工具確實(shí)檢測(cè)出了合約中的漏洞。這個(gè)合約代碼共有兩個(gè)時(shí)間戳依賴安全問(wèn)題。
第一個(gè)安全漏洞
漏洞名稱:依賴于可預(yù)測(cè)的環(huán)境變量(時(shí)間戳依賴)
SWC ID: 116 —— 表示該漏洞的分類編號(hào)
Severity: Low ?—— 表示該漏洞的嚴(yán)重性程度
Contract: Roulette —— 表示檢測(cè)的合約名稱
Function name: fallback —— 表示發(fā)現(xiàn)漏洞的函數(shù)名稱
PC address: 70 —— 表示程序計(jì)數(shù)器地址,Program Counter 的簡(jiǎn)稱
Estimated Gas Usage: 889 - 984 —— 表示估算的 Gas 費(fèi)用開(kāi)銷
漏洞描述——控制流的決定是基于區(qū)塊的時(shí)間戳環(huán)境變量。block.timestamp 環(huán)境變量用于確定控制流決策。請(qǐng)注意,coinbase、gaslimit、block number 和 timestramp 等變量的值是可預(yù)測(cè)的,可以被惡意礦工操縱。還要記住,攻擊者知道早期塊的哈希值。請(qǐng)注意,不要使用任何這些環(huán)境變量作為隨機(jī)性的來(lái)源,并且確保使用的這些變量對(duì)礦工是可信任的。
再接下來(lái)是漏洞代碼在合約代碼中的行號(hào),并給出了代碼段,以及合約的初始狀態(tài)和交易序列。
第二個(gè)安全漏洞
漏洞名稱:依賴與可預(yù)測(cè)的環(huán)境變量(時(shí)間戳依賴)
SWC ID: 116
Severity: Low
Contract: Roulette
Function name: fallback
PC address: 102
Estimated Gas Usage: 6105 - 26200
漏洞描述與第一個(gè)漏洞相同,均屬于時(shí)間戳依賴的安全問(wèn)題。
漏洞分類(SWC ID)詳見(jiàn) 智能合約缺陷分類和測(cè)試用例
輸出格式
缺省情況下,分析結(jié)果以文本形式打印到終端。你可以用 -o 參數(shù)改變輸出格式:
可用的格式有 text、markdown、json 和 jsonv2。對(duì)于與其他工具的集成,通常首選 jsonv2 而不是 json,因?yàn)樗c其他 MythX 工具保持一致。