压在透明的玻璃上c-国产精品国产一级A片精品免费-国产精品视频网-成人黄网站18秘 免费看|www.tcsft.com

以太坊 Solidity 未初始化存儲指針安全風險淺析

0x00 引子

看到安比實驗室有篇文章在說《警惕!Solidity缺陷易使合約狀態失控》的問題,原文鏈接可以在參考鏈接中獲取。

這個問題實際上之前在慢霧區中,愛上平頂山(山哥)和 keywolf 就有對一篇外文進行了翻譯,可以在 SlowMist 的 GitHub 中找到(地址見參考鏈接),這篇譯文《Solidity 安全:已知攻擊方法和常見防御模式綜合列表》里面就有講到。

其實就是 Unintialised Storage Pointers(未初始化的存儲指針)的安全問題,EVM中會將數據存儲為 storage 或 memory ,在函數中局部變量的默認類型取決于它們本身的類型,未進行初始化的 storage 變量,會指向合約中的其他變量,從而改變其他變量的值,常見的場景就是指向狀態變量,改變狀態變量的值,導致漏洞的產生。

0x01 分析過程

依據 Solidity 官方手冊上的介紹,以及經過實驗得到了一些總結分析。

這里要注意結構體,數組和映射的局部變量,在官方手冊中有提到這些類型的局部變量默認是放在 storage 中的,因此這些局部變量可能都存在相同的問題。(本文分析了結構體和數組的 Unintialised Storage Pointers 問題,而 mapping 暫未找到存在問題的案例)

而 struct 中在和局部變量進行賦值操作的時候,是保存成一個引用

如下是問題代碼,struct 在函數中被聲明但是沒有初始化,根據官方文檔中可以知道,struct 在局部變量中默認是存放在 storage 中的,因此可以利用 Unintialised Storage Pointers 的問題,p會被當成一個指針,并默認指向slot[0]slot[1] ,因此在進行p.namep.mappedAddress賦值的時候,實際上會修改變量testA,test B的值。

pragma solidity ^0.4.0;
contract  testContract{

    bytes32 public testA; 
    address public testB;

    struct Person { 
        bytes32 name;  
        address mappedAddress;
    }

    function test(bytes32 _name, address _mappedAddress) public{
        Person p;
        p.name = _name;
        p.mappedAddress = _mappedAddress; 

    }
}

同理數組也有同樣的問題,如下是問題代碼

pragma solidity ^0.4.0;

contract C {
    uint public someVariable;
    uint[] data;

    function f() public {
        uint[] x;
        x.push(2);
        data = x;
    }
}

0x02 解決方案

結構體 Unintialised Storage Pointers 問題的正確的解決方法是將聲明的 struct 進行賦值初始化,通過創建一個新的臨時 memory 結構體,然后將它拷貝到 storage 中。

pragma solidity ^0.4.0;
contract  testContract{

    bytes32 public testA; 
    address public testB;

    struct Person { 
        bytes32 name;  
        address mappedAddress;
    }

    mapping (uint => Person) persons;

    function test(uint _id, bytes32 _name, address _mappedAddress) public{
        Person storage p = persons[_id];
        p.name = _name;
        p.mappedAddress = _mappedAddress; 

    }
}

數組 Unintialised Storage Pointers 問題的正確解決方法是在聲明局部變量 x 的時候,同時對 x 進行初始化操作。

pragma solidity ^0.4.0;

contract C {
    uint public someVariable;
    uint[] data;

    function f() public {
        uint[] x = data;
        x.push(2);
    }
}

Solidity 編譯器開發團隊不出意外將在下一個版本(Solidity 0.4.25)中對存在 Unintialised Storage Pointers 問題的代碼進行修復,否則將無法正常通過編譯。

開發人員需要關注 Solidity 0.4.25 版本的發布,并且使用 Solidity 0.4.25 編寫代碼。

最后,本篇未涉及的 mapping 未初始化存儲指針的安全問題和案例,期待能夠和師傅們一起研究討論。

0x03 參考鏈接

《警惕!Solidity 缺陷易使合約狀態失控》
https://mp.weixin.qq.com/s/xex9Eef6Hz5o24sX5vE1Yg

《Solidity 安全:已知攻擊方法和常見防御模式綜合列表》
https://github.com/slowmist/Knowledge-Base/blob/master/solidity-security-comprehensive-list-of-known-attack-vectors-and-common-anti-patterns-chinese.md#%E8%99%9A%E6%8B%9F%E5%8C%96%E5%AD%98%E5%82%A8%E6%8C%87%E9%92%88

《Solidity 官方文檔》
http://solidity.readthedocs.io/en/v0.4.24/frequently-asked-questions.html
http://solidity.readthedocs.io/en/latest/types.html#structs

本文由Thinking@慢霧安全團隊撰寫,這里是原文 GitHub 地址:https://github.com/slowmist/papers/blob/master/Solidity_Unintialised_Storage_Pointers_Security_Risk.pdf
轉自: https://www.anquanke.com/post/id/154407

上一篇:CSS2018將于8月召開 大咖齊聚研討安全驅動力

下一篇:谷歌GCP:最安全的云平臺?