欢迎订阅专栏:3分钟Solidity--智能合约--Web3区块链技术必学
如需获取本内容的最新版本,请参见 Cyfrin.io 上“隐藏带有外部合同的恶意代码(代码示例)”
漏洞
在Solidity中,任何地址都可以被强制转换为特定合约类型,即使该地址上的合约并非目标合约。
这一特性可被利用来隐藏恶意代码。下面我们来看看具体是如何实现的。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/*
假设Alice能看到Foo和Bar的代码,但看不到Mal的代码。
对Alice来说,显然Foo.callBar()会执行Bar.log()中的代码。
然而Eve部署Foo时使用了Mal的地址,因此调用Foo.callBar()
实际上会执行Mal中的代码。
*/
/*
1. Eve部署了恶意程序Mal
2. Eve以Mal的地址部署了Foo
3. Alice阅读代码后判定调用安全,调用了Foo.callBar()
4. 虽然Alice预期会执行Bar.log(),但实际执行的是Mal.log()
*/
contract Foo {
Bar bar;
constructor(address _bar) {
bar = Bar(_bar);
}
function callBar() public {
bar.log();
}
}
contract Bar {
event Log(string message);
function log() public {
emit Log("Bar was called");
}
}
// 这段代码隐藏在一个单独的文件中
contract Mal {
event Log(string message);
// function () external {
// emit Log("Mal was called");
// }
// 实际上,即使这个函数不存在,我们也可以通过使用回退机制来执行相同的攻击
function log() public {
emit Log("Mal was called");
}
}
预防性技术
- 在构造函数内初始化新合约
- 将外部合约的地址设为
public,以便审查外部合约的代码
Bar public bar;
constructor() public {
bar = new Bar();
}