短地址漏洞

漏洞条件:

  • 当地址的长度不足 20 byte (40个十六进制字符) 时,以太坊虚拟机 EVM 会进行高位补0x0
  • 转发以太币时没有对地址长度进行验证

1. input 数据

交易的 input 数据分为三个部分:

1)4字节,是方法名的Hash值:a9059cbb

2)32字节,存放以太坊地址,目前以太坊地址是20个字节(40个十六进制字符),高位补0x0,满足32字节,比如 0000000000000000000000001234567890123456789012345678901234567800

3)32字节,是需要传输的代币数量,不足32字节,高位补0x0,满足32字节,比如00000000000000000000000000000000000000000000000000000adba0ce5362

这三部分合起来就是交易数据:

a9059cbb000000000000000000000000123456789012345678901234567890123456780000000000000000000000000000000000000000000000000000000adba0ce5362

2. 补足机制

当以太地址长度不够时,EVM会从下一个参数(代币数量)的高位拿到 00 来补充以补成预期的长度,而代币数量不够后,会在其高位补 0x00

例如:以太地址 0000000000000000000000001234567890123456789012345678901234567800 去掉最后一个字节 0x00 ,EVM 就会将代币数量的前一个字节 0x00 作为地址的内容,后面的代币数量缺少的位数就会用 0x00 补充,也就是代币数量末尾添加了 0x00,这里代币数量末尾为 0x2,补位后变成了 0x200,这样就导致代币数量增加了 2^8 倍:000000000000000000000000000000000000000000000000000adba0ce536200

以太地址变化

0000000000000000000000001234567890123456789012345678901234567800 => 去掉00

00000000000000000000000012345678901234567890123456789012345678 => 补足00

0000000000000000000000001234567890123456789012345678901234567800

代币数量变化

00000000000000000000000000000000000000000000000000000adba0ce5362 => 高位00被借

000000000000000000000000000000000000000000000000000adba0ce5362 => 末尾补足

000000000000000000000000000000000000000000000000000adba0ce536200

pragma solidity ^0.4.11;

contract ShortAddress{
    mapping (address => uint) balances;

    event Transfer(address indexed _from , address indexed _to, uint256 _value);

    function ShortAddress() {
        balances[tx.origin] = 10000;
    }

    function transfer(address to, uint amount) returns(bool success) {
        require(balances[msg.sender] > amount);
        balances[msg.sender] -= amount;
        balances[to] += amount;
        Transfer(msg.sender, to, amount);
        return true;
    }

    function getBalance(address addr) constant returns(uint) {
        return balances[addr];
    }
}

猜你喜欢

转载自blog.csdn.net/SHELLCODE_8BIT/article/details/134996122