日前,互联网爆出AMR合约存在高危安全风险的交易,该合约存在批量转账溢出漏洞,当合约实现批量转账功能时,容易在计算通证增加量时发生溢出漏洞,BUGX.IO安全团队经过研究分析发现,同类漏洞仍在以太坊里面部分存在。
以下为漏洞分析过程:
原理
/**
* @dev Function is used to perform a multi-transfer operation. This could play a significant role in the Ammbr Mesh Routing protocol.
*
* Mechanics:
* Sends tokens from Sender to destinations[0..n] the amount tokens[0..n]. Both arrays
* must have the same size, and must have a greater-than-zero length. Max array size is 127.
*
* IMPORTANT: ANTIPATTERN
* This function performs a loop over arrays. Unless executed in a controlled environment,
* it has the potential of failing due to gas running out. This is not dangerous, yet care
* must be taken to prevent quality being affected.
*
* @param destinations An array of destinations we would be sending tokens to
* @param tokens An array of tokens, sent to destinations (index is used for destination->token match)
*/
function multiTransfer(address[] destinations, uint[] tokens) public returns (bool success){
// Two variables must match in length, and must contain elements
// Plus, a maximum of 127 transfers are supported
assert(destinations.length > 0);
assert(destinations.length < 128);
assert(destinations.length == tokens.length);
// Check total requested balance
uint8 i = 0;
uint totalTokensToTransfer = 0;
for (i = 0; i < destinations.length; i++){
assert(tokens[i] > 0);
totalTokensToTransfer += tokens[i];
}
// Do we have enough tokens in hand?
assert (balances[msg.sender] > totalTokensToTransfer);
// We have enough tokens, execute the transfer
balances[msg.sender] = balances[msg.sender].sub(totalTokensToTransfer);
for (i = 0; i < destinations.length; i++){
// Add the token to the intended destination
balances[destinations[i]] = balances[destinations[i]].add(tokens[i]);
// Call the event...
emit Transfer(msg.sender, destinations[i], tokens[i]);
}
return true;
}
`totalTokensToTransfer += tokens[i];` 这一句溢出,溢出后,totalTokensToTransfer 变小了,从而绕过了 `assert (balances[msg.sender] > totalTokensToTransfer);` 的判断,这样就能花极少的token ,任意增加目标地址的token。
漏洞复现
1. 部署 AMR 合约。
2. 因为需要攻击者 token 数量大于0,所以先使用管理员账户给攻击者地址充 token。
3. 使用漏洞溢出攻击
这里需要两个地址,一个是攻击者,另一个为其它地址,这里设置 0 地址就行。
大型站长资讯类网站! https://www.nzzz.com.cn