My Avatar

毕竟话少

业精于勤荒于嬉,行成于思毁于随!

智能合约审计-访问控制漏洞

2020年1月9日 星期四, 发表于 合肥

如果你对本文有任何的建议或者疑问, 可以在 这里给我提 Issues, 谢谢! :)

描述:合约没有设置合理的访问控制模型,以及没有对合约有效的校验导致访问控制漏洞的发生

核心问题:public的恶意使用(本次案例合约为例)

漏洞描述

智能合约的访问控制漏洞主要体现在以下俩个方面:

针对函数和变量,限制其所能被修改和调用的作用域

通常针对函数,限制某些特权用户访问

代码层面可见性的函数普及:

默认状态下,可以进行任何形式的调用

可以通过其他合约或者交易来调用,不能在合约内部进行调用

只能在合约(含子合约)内部进行调用

只能在合约(不包含子合约)内部进行调用

逻辑层面的权限约束的函数普及:

1.用于函数执行前的函数检查

2.可以设置参数

3.特殊符号“_”用于指代函数代码的执行位置

modifier noReetrancy() {
   if (locked) throw;
   locked = true;
   _;
   locaked = false;
}

1.前置判断管理员权限

2.前置判断合约是否暂停

3.对原子操作进行加锁、解锁

4….

漏洞合约分析

pragma solidity ^0.4.24;

contract AccessGame{
    
    uint totalSupply=0;
    address public owner;
    mapping (address => uint256) public balances;

    event SendBouns(address _who, uint bouns);

    modifier onlyOwner {
        if (msg.sender != owner)
            revert();
        _;
    }
    
    constructor() public {
        initOwner(msg.sender);  //initOwner()初始化管理员权限
    }

    function initOwner(address _owner) public{
        owner=_owner;
    }

    function SendBonus(address lucky, uint bouns) public onlyOwner returns (uint){
        require(balances[lucky]<1000);
        require(bouns<200);
        balances[lucky]+=bouns;
        totalSupply+=bouns;

        emit SendBouns(lucky, bouns);

        return balances[lucky];
    }
}

漏洞点:第21行,在进行初始化管理员的时候,并没有对init0wner()函数设置合理权限,使用public函数进行调用(默认状态下,可以进行任何形式的调用),攻击者可以自己调用init0wner()函数使自己成为管理员,从而调用SendBonus()增加自己的balances


使用Remix进行进行调试

漏洞预防

  1. 设计合理的访问控制模型,并在代码中进行校验
  2. 合理使用可见性约束和modifier
  3. 使用形式化验证检测智能合约的访问控制漏洞