乐趣区

关于区块链:智能合约安全delegatecall-2

本次,咱们来讲一讲使用 delegatecall 函数时更简单的合约破绽案例。

指标合约

 破绽剖析这次的攻打指标仍然是取得 HackMe 合约中的 owner 权限,咱们能够看到两个合约中除了 HackMe 合约中的构造函数能够批改合约的 owner 其余中央并没有批改 owner 的函数,然而却能够批改地位 slot0 的值,而 HackMe 合约中插槽 slot0 示意的便是 Lib 的地址,那么咱们就先批改 Lib 的地址为咱们的地址,再次调用 HackMe 合约时就会运行咱们合约中的逻辑,那么想改哪个地位插槽的值不就都由咱们管制了吗?

攻打合约
上面是咱们本次的攻打合约:

  接下来咱们来看看攻打的整个逻辑:

  1. Attack.attack() 函数先将本人的地址转换为 uint256 类型(这一步是为了兼容指标合约中的数据类型)第一次调用 HackMe.doSomething() 函数;
  2. HackMe.doSomething() 函数应用 delegatecall 函数带着传入的 Attack 合约的地址调用了 Lib.doSomething() 函数;
  3. 能够看到 Lib.doSomething() 函数将合约中存储地位为 slot0 的参数改为传入的值,这样当 HackMe 合约应用 delegatecall 调用 Lib.doSomething() 函数时也将扭转本人在 slot0 地位存储的变量的值,也就是将 lib 参数(这里存储的是 Lib 合约的地址)改为咱们传入的 Attack 合约的地址。此时之前在 HackMe.lib 参数中存储的 Lib 合约的地址就被批改成咱们传入的 Attack 合约的地址了;
    4. Attack.attack() 函数再次调用 HackMe.doSomething() 函数,因为在上一步咱们曾经将 HackMe.lib 变量批改为 Attack 合约的地址了,这时 HackMe.doSomething() 函数将不再调用之前的 Lib 合约而是用 delegatecall 去调用 Attack.doSomething() 函数。此时咱们再来察看 Attack 合约的写法,发现其变量的存储地位成心和 HackMe 合约保持一致,并且不难发现 Attack.doSomething() 函数的内容也被攻击者写为 owner = msg.sender,这个操作批改了合约中存储地位为 slot1 的变量。所以 HackMe 合约应用 delegatecall 调用 Attack.doSomething() 函数就会将合约中存储地位为 slot1 的变量 owner 批改为 msg.sender 也就是攻击者的地址,至此攻击者实现了他的攻打。

修复倡议
咱们在合约的开发中应用 delegatecall 要时刻留神其被调用的合约地址要始终在咱们设计的逻辑内运行,不能让其有可能超出咱们设计时的适用范围,一旦呈现了超出咱们预期设计的状况,那么合约就有可能被不法之徒利用。
如果想理解更多的智能合约和区块链常识,欢送到区块链交换社区 CHAINPIP 社区,一起交流学习~ 社区地址:https://www.chainpip.com/    

退出移动版