Solidity中tx.origin授权漏洞攻击原理及代码疑问解析
关于tx.origin授权漏洞案例的疑问解答
问题1:TxUserWallet合约的transfer函数如何触发TxAttackWallet合约的receive函数,进而盗走全部资金?
先还原漏洞场景的核心逻辑:TxUserWallet的transfer函数用tx.origin == owner做权限校验,而tx.origin指的是整个交易链的初始发起地址,而非当前调用的直接发起者。
完整攻击流程如下:
- 攻击者诱导TxUserWallet的所有者(用户)调用攻击合约的某个函数(比如
attack(address _userWallet)),此时整个交易的发起者是用户,tx.origin始终为用户地址。 - 攻击合约的
attack函数调用TxUserWallet(_userWallet).transfer(address(this), _userWallet.balance),由于tx.origin匹配owner权限校验,TxUserWallet执行转账,将ETH打给攻击合约。 - 当ETH转入攻击合约地址时,会自动触发攻击合约的
receive()函数(Solidity中合约接收纯ETH时,会触发receive或fallback函数)。 - 在
receive函数中,攻击者再次调用TxUserWallet的transfer函数——此时tx.origin仍是初始发起的用户地址,依然能通过权限校验,继续转走剩余ETH。 - 该循环会持续到TxUserWallet余额不足以支付转账gas,或余额被转空,最终所有资金流入攻击合约。
问题2:攻击合约中TxUserWallet(msg.sender)写法的含义是什么?msg.sender.balance传递的是什么值?
关于TxUserWallet(msg.sender)
这是Solidity的合约地址类型转换:将msg.sender这个地址,转换为TxUserWallet合约类型的实例。只要该地址确实部署了TxUserWallet合约,就能通过这个实例直接调用合约的public/external函数(比如transfer),无需单独导入合约接口(前提是知晓合约函数签名)。
关于msg.sender.balance
msg.sender的值取决于当前调用上下文:
- 若在攻击合约的
attack函数中,用户调用该函数时,msg.sender是用户的钱包地址,此时msg.sender.balance代表用户地址的ETH余额(但攻击场景中通常不会这么用,而是取目标钱包合约的balance)。 - 若在攻击合约的
receive函数中,此时是TxUserWallet合约转ETH触发的调用,msg.sender是TxUserWallet合约的地址,因此msg.sender.balance就是TxUserWallet合约当前的ETH余额——攻击者用这个值一次性转走剩余全部资金。
内容的提问来源于stack exchange,提问作者Brijesh
相关产品推荐
相关产品推荐

