引子
看到安比實(shí)驗(yàn)室有篇文章在說(shuō)《警惕瘾腰!Solidity缺陷易使合約狀態(tài)失控》的問題,原文鏈接可以在參考鏈接中獲取。
這個(gè)問題實(shí)際上之前在慢霧區(qū)中寂殉,愛上平頂山(山哥)和 keywolf 就有對(duì)一篇外文進(jìn)行了翻譯,可以在 SlowMist 的 GitHub 中找到(地址見參考鏈接)原在,這篇譯文《Solidity 安全:已知攻擊方法和常見防御模式綜合列表》里面就有講到友扰。
其實(shí)就是 Unintialised Storage Pointers(未初始化的存儲(chǔ)指針)的安全問題,EVM中會(huì)將數(shù)據(jù)存儲(chǔ)為 storage 或 memory 庶柿,在函數(shù)中局部變量的默認(rèn)類型取決于它們本身的類型村怪,未進(jìn)行初始化的 storage 變量,會(huì)指向合約中的其他變量浮庐,從而改變其他變量的值甚负,常見的場(chǎng)景就是指向狀態(tài)變量,改變狀態(tài)變量的值审残,導(dǎo)致漏洞的產(chǎn)生梭域。
1,分析過(guò)程
依據(jù) Solidity 官方手冊(cè)上的介紹搅轿,以及經(jīng)過(guò)實(shí)驗(yàn)得到了一些總結(jié)分析病涨。
這里要注意結(jié)構(gòu)體,數(shù)組和映射的局部變量璧坟,在官方手冊(cè)中有提到這些類型的局部變量默認(rèn)是放在 storage 中的既穆,因此這些局部變量可能都存在相同的問題赎懦。(本文分析了結(jié)構(gòu)體和數(shù)組的 Unintialised Storage Pointers 問題,而 mapping 暫未找到存在問題的案例)
而 struct 中在和局部變量進(jìn)行賦值操作的時(shí)候循衰,是保存成一個(gè)引用
如下是問題代碼铲敛,struct 在函數(shù)中被聲明但是沒有初始化,根據(jù)官方文檔中可以知道会钝,struct 在局部變量中默 認(rèn)是存放在 storage 中的伐蒋,因此可以利用 Unintialised Storage Pointers 的問題, p 會(huì)被當(dāng)成一個(gè)指針迁酸,并默 認(rèn)指向 slot[0] 和 slot[1] 先鱼,因此在進(jìn)行 p.name 和 p.mappedAddress 賦值的時(shí)候,實(shí)際上會(huì)修改變量 testA 奸鬓, test B 的值焙畔。
同理數(shù)組也有同樣的問題,如下是問題代碼:
2串远,解決方案
結(jié)構(gòu)體 Unintialised Storage Pointers 問題的正確的解決方法是將聲明的 struct 進(jìn)行賦值初始化宏多,通過(guò)創(chuàng)建一 個(gè)新的臨時(shí) memory 結(jié)構(gòu)體,然后將它拷貝到 storage 中澡罚。
數(shù)組 Unintialised Storage Pointers 問題的正確解決方法是在聲明局部變量 x 的時(shí)候伸但,同時(shí)對(duì) x 進(jìn)行初始化操作。
Solidity 編譯器開發(fā)團(tuán)隊(duì)不出意外將在下一個(gè)版本(Solidity 0.4.25)中對(duì)存在 Unintialised Storage Pointers 問題的代碼進(jìn)行修復(fù)留搔,否則將無(wú)法正常通過(guò)編譯更胖。
開發(fā)人員需要關(guān)注 Solidity 0.4.25 版本的發(fā)布,并且使用 Solidity 0.4.25 編寫代碼隔显。
最后却妨,本篇未涉及的 mapping 未初始化存儲(chǔ)指針的安全問題和案例场斑,期待能夠和師傅們一起研究討論溯壶。
3尽超, 參考鏈接
1)《警惕抽高!Solidity 缺陷易使合約狀態(tài)失控》
2)《Solidity 安全:已知攻擊方法和常見防御模式綜合列表》
3) Solidity 官方-常見問題
4)Solidity 官方-結(jié)構(gòu)定義