首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >智能合约安全审计之路-拒绝服务漏洞

智能合约安全审计之路-拒绝服务漏洞

作者头像
字节脉搏实验室
发布2020-03-31 10:11:15
1.5K0
发布2020-03-31 10:11:15
举报

描述:拒绝服务漏洞(DOS)智能合约无法按照设定的方式被调用

核心问题:智能合约中的拒绝服务是一个致命的漏洞,因为漏洞导致的拒绝服务一般为永久性的,无法恢复

拒绝服务的原因

  • 意外执行了SELFDESTRUCT指令
  • 访问控制策略出错
  • Gas达到区块上限
  • 非预期的异常抛出

漏洞分析

selfdestruct()合约自毁函数

  • 指令执行后,合约将拒绝服务,地址对应的字节码将被标注为删除
  • 合约地址中所有的ETH将被发送到指定的新地址
  • 进行ETH转移时,即使目标地址为一个合约地址,也不会触发该地址的fallback函数,因此不需要该合约有任何的payable函数
  • 如果selfdestruct函数被非预期的执行,则整个合约会拒绝服务

selfdestructGame合约分析

pragma solidity ^0.4.24;
 
contract selfdestructGame{
    address owner;
 
    constructor() payable {
        owner = msg.sender;
    }
     
    function ownedEth() public constant returns(uint256){
        return this.balance;
    }
     
 
    function destruct(address _who) public {
        selfdestruct(_who);
    }
}

漏洞点:在address owner处发送地址到_who处,由于调用了selfdestruct()函数对selfdestructGame合约进行自毁,将selfdestructGame合约balance发送到攻击者地址处。

访问控制策略错误

onwer权限变更不需要确认,因此若owner被设置为一个错误地址,合约将彻底失去管理员权限

onwerGame合约分析

pragma solidity ^0.4.24;
 
contract ownerGame{
    address owner;
 
    constructor() {
        owner = msg.sender;
    }
 
    function changeOwner(address _new) public {
        owner = _new;
    }
}

漏洞点:由于owner没有权限控制,导致可以任意调用成为管理员,如果owner地址为无效地址,就会导致合约作废

Gas达到区块上限

对于每一个区块来说,有一个区块的GasLimit,任何交易的gas花费都不超过这个上限,否则无法被打包

GaslimitGame合约分析

pragma solidity ^0.4.24;
 
contract gaslimitGame{
    mapping (uint => uint) count;
     
    event GasLog(uint gas);
 
    function gasUse(uint n) public {
        uint gastmp = gasleft();
        for(uint i=0;i<n;i++)
        {
            count[i]=i;
            emit GasLog(gastmp-gasleft());
            gastmp = gasleft();
        }
    }
}

非预期的异常导致拒绝服务

在竞拍合约中,竞拍进行时,每个人向合约发送自己的竞拍出价对应ETH

如果有人出价高于当前最高出价者,则合约退还当前最高出价者的出价,并且此人成为新的最高出价者

攻击者构造一个fallback函数一定会抛出异常的合约,并将合约地址成为最高出价者,则其他人将永远不能成为新的最高出价者

Auction合约分析

pragma solidity ^0.4.24;
 
contract Auction {
    address public topBidder;
    uint256 public topBid;
 
    constructor() public payable {
        require(msg.value > 0);      
        topBid = msg.value;
        topBidder = msg.sender;
    }
     
    function bid() payable {
        require(msg.value > topBid);
        topBidder.transfer(topBid);
 
        topBidder = msg.sender;
        topBid = msg.value;
 
    }
 
    // finish the auction
    function auction_end() {
        // ...
    }
     
}
 
contract revertContract{
     
    function testBid(address _addr) public payable{
        bytes4 methodHash = bytes4(keccak256("bid()"));
        _addr.call.value(msg.value)(methodHash);
    }
     
    function ownedEth() public constant returns(uint256){
        return this.balance;
    }
     
    function() public payable{
        revert();
    }
}

漏洞点:topBidder的攻击者合约在竞拍成功后的上一个最高价格时候,当后面的竞拍者出更高价格的时候,会触发topBidder.transfer(topBid),然而攻击者合约内使用了fallback函数,在经过transfer函数的时候会发生异常,导致交易回滚,从而使bid()函数拒绝服务。使整个合约没办法正常进行。

漏洞预防

  1. 严格限制selfdestruct指令的权限限制
  2. 设置完善合理的访问控制策略
  3. 如果目标地址可以是一个合约,需要考虑合约的特性
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 拒绝服务的原因
  • 漏洞分析
    • selfdestruct()合约自毁函数
      • selfdestructGame合约分析
    • 访问控制策略错误
      • onwerGame合约分析
    • Gas达到区块上限
      • GaslimitGame合约分析
    • 非预期的异常导致拒绝服务
      • Auction合约分析
  • 漏洞预防
相关产品与服务
区块链
云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档