SWC智能合约漏洞库

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器

SWC-124/写入任意存储位置

智能合约的数据(例如,存储合约的所有者)被永久存储在EVM的某个存储位置。合约负责确保只有 授权的用户或合约帐户才能写入敏感的存储位置。如果攻击者能够写入合约的任意存储位置,则可以 很容易地规避授权检查。这可能使攻击者破坏存储;例如,通过覆盖存储合约所有者地址的字段。

CWE漏洞分类

CWE-123:在何处写入的条件

整改方案

作为一般性建议,鉴于所有数据结构共享相同的存储(地址)空间,应确保对一个数据结构的写入 不会无意间覆盖另一数据结构的条目。

参考文献

2017 solidity代码大赛

合约示例

random_location_write_simple.sol

pragma solidity ^0.4.25;

contract Wallet {
    uint[] private bonusCodes;
    address private owner;

    constructor() public {
        bonusCodes = new uint[](0);
        owner = msg.sender;
    }

    function () public payable {
    }

    function PushBonusCode(uint c) public {
        bonusCodes.push(c);
    }

    function PopBonusCode() public {
        require(0 <= bonusCodes.length);
        bonusCodes.length--;
    }

    function UpdateBonusCodeAt(uint idx, uint c) public {
        require(idx < bonusCodes.length);
        bonusCodes[idx] = c;
    }

    function Destroy() public {
        require(msg.sender == owner);
        selfdestruct(msg.sender);
    }
}

random_location_write_simple.yaml

description: Simple variant of write to arbitrary storage location
issues:
- id: SWC-124
  count: 1
  locations:
  - bytecode_offsets:
      '0x4d778370f4fe1789bc427ab08efc768fcb4c6c8b68d2ee41178340423445bd45': [294]
    line_numbers:
      arbitrary_location_write_simple.sol: [26]

random_location_write_simple_fixed.sol

pragma solidity ^0.4.25;

contract Wallet {
    uint[] private bonusCodes;
    address private owner;

    constructor() public {
        bonusCodes = new uint[](0);
        owner = msg.sender;
    }

    function () public payable {
    }

    function PushBonusCode(uint c) public {
        bonusCodes.push(c);
    }

    function PopBonusCode() public {
        require(0 < bonusCodes.length);
        bonusCodes.length--;
    }

    function UpdateBonusCodeAt(uint idx, uint c) public {
        require(idx < bonusCodes.length); //Since you now have to push very codes this is no longer an arbitray write.
        bonusCodes[idx] = c;
    }

    function Destroy() public {
        require(msg.sender == owner);
        selfdestruct(msg.sender);
    }
}

random_location_write_simple_fixed.yaml

description: Simple variant of write to arbitrary storage location
issues:
- id: SWC-124
  count: 0
  locations: []

mapping_write.sol

pragma solidity ^0.4.24;

//This code is derived from the Capture the Ether https://capturetheether.com/challenges/math/mapping/

contract Map {
    address public owner;
    uint256[] map;

    function set(uint256 key, uint256 value) public {
        if (map.length <= key) {
            map.length = key + 1;
        }

        map[key] = value;
    }

    function get(uint256 key) public view returns (uint256) {
        return map[key];
    }
    function withdraw() public{
      require(msg.sender == owner);
      msg.sender.transfer(address(this).balance);
    }
}

mapping_write.yaml

description: Write to arbitrary storage location using dynamic arrays
issues:
- id: SWC-124
  count: 1
  locations:
  - bytecode_offsets:
      '0xb3f8b66f8449fff6ee9ba17ae5534dfb2d8f4c4281c8a9ad56c1354a55c389d3': [395]
    line_numbers:
      mapping_write.sol: [14]