Web3系列教程之高级篇---8:为什么不要使用tx.origin来确定交易的发送者
tx.origin是一个全局变量,用于返回创建原始交易的地址。它有点类似于msg.sender,但有一个重要的注意事项。我们将学习如何因为错误地使用tx.origin导致智能合约的安全漏洞。
开始吧🚀
什么是tx.origin?
tx.origin是一个全局变量,返回发送交易的账户地址。现在你可能想知道什么是msg.sender 🤔。区别在于,tx.origin指的是开始交易的原始外部账户(也就是用户),而msg.sender是调用函数的直接账户,它可以是一个外部账户或另一个调用函数的合约。
因此,例如,如果用户调用合约A,然后在同一交易中调用合约B,当从合约B内部检查时,msg.sender将等于合约A。然而,无论你从哪里检查,tx.origin将是用户。
对智能合约的DOS攻击
将会发生什么?
将有两个智能合约 - Good.sol和Attack.sol。Good.sol。最初,Good.sol的所有者将是一个好的用户。使用攻击功能Attack.sol将能够把Good.sol的所有者变为自己。
建造
让我们构建一个示例,您可以在其中体验攻击是如何发生的。
- 要设置一个Hardhat项目,请打开终端,在一个新的文件夹中执行这些命令
|
|
- 如果你不是在mac上,请做这个额外的步骤,也安装这些库 :)
|
|
- 在你安装Hardhat的同一目录下运行。
|
|
- 选择
Create a basic sample project - 对已指定的
Hardhat Project root按回车键 - 如果你想添加一个
.gitignore,请按回车键。 - 按回车键
Do you want to install this sample project's dependencies with npm (@nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers)?
现在你有一个准备好的hardhat项目了!
首先,让我们创建一个名为Good.sol的合约,它基本上是我们之前使用过的Ownable.sol的一个简单版本。
|
|
现在,在contracts目录下创建一个名为Attack.sol的合约,并编写以下几行代码:
|
|
现在,让我们尝试使用样本测试来模仿攻击,在test文件夹下创建一个名为attack.js的新文件,并在其中添加以下几行代码
|
|
攻击会发生如下情况,最初addr1会部署Good.sol,并成为所有者,但攻击者会以某种方式愚弄拥有addr1私钥的用户,让他用Attack.sol调用attack函数。
当用户用addr1调用attack函数时,tx.origin被设置为addr1。attack函数进一步调用Good.sol的setOwner函数,首先检查tx.origin是否确实是所有者,这是真的,因为原始交易确实是由addr1调用的。在验证了所有者后,它将所有者设置为Attack.sol
因此,攻击者能够成功地改变Good.sol 的所有者 🤯。
要运行测试,在你的终端上指向本级别的根目录,执行以下命令
|
|
当测试通过后,你会注意到Good.sol的所有者现在是Attack.sol。
现实生活中的例子
虽然这对你们中的大多数人来说可能是显而易见的,因为tx.origin根本不是你看到的被使用的东西,但有些开发者确实犯了这个错误。你可以在这里读到THORChain Hack #2,由于攻击者能够通过向用户的钱包发送假的代币来获得对$RUNE代币的批准,而批准该代币在Uniswap上出售,就会将$RUNE从用户的钱包转移到攻击者的钱包,因为THORChain使用tx.origin而不是msg.sender进行转账检查。
预防
你应该使用msg.sender而不是tx.origin来避免这种情况发生。
例如:
|
|
希望你喜欢本文❤️
参考

