Estaba leyendo sobre el ataque de dirección corta y decidí replicar y probar las posibles soluciones.
Lo que sé sobre el ataque de dirección corta es que si omite n caracteres de su dirección, termina proporcionando 68-(n/2) bytes a su transfer
función y el evm agrega ceros para hacer 68 bytes. Y el resultado final es que su valor cambia por n<<8
. Esto fue solo una descripción general de alto nivel.
Ahora trato de probar lo mismo con un token de prueba (con decimales = 2). La función de transferencia del contrato pasa por:
function transfer(address _to, uint256 _value) {
require (balanceOf[msg.sender] > _value) ;
require (balanceOf[_to] + _value > balanceOf[_to]);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
Transfer(msg.sender, _to, _value);
}
Usé remix conectado a mi red de prueba privada para verificar este ataque.
yo tenia una 0x7ecd024742458287b9cd97015ff265d04a316f20
direccion Llamé a la función de transferencia del contrato con argumentos:
transfer("0x7ecd024742458287b9cd97015ff265d04a316f2", 1);
Según tengo entendido, esperaba que la dirección proporcionada obtuviera 256 monedas (si se replica el ataque de dirección corta). Pero en lugar de eso, obtuve el error:
transact to browser/TestShortAddAttack.sol:MyToken.transfer error: El gas requerido excede el límite de gas del bloque: 6000000. Una estimación de gas importante también podría ser el signo de un problema en el código del contrato. Verifique los bucles y asegúrese de no enviar valor a una función no pagadera (esa también es la razón de una estimación de gas sólida).
¿Por qué la transacción consume tanto gas? ¿Evm se ha ocupado de este problema o necesitamos implementar la verificación (Comprobación de la longitud de msg.data)?
Traté de replicar también. Sin embargo, no obtuve el error que obtuviste, pero tampoco obtuve una réplica perfecta del ataque. Tengo una implementación de la biblioteca safemath, pero de otra manera como la tuya.
function transfer(address _to, uint _amount) public returns (bool success){
balances[msg.sender] = balances[msg.sender].sub(_amount);
balances[_to] = balances[_to].add(_amount);
Transfer(msg.sender,_to,_amount);
return true;
}
Intenté usar la dirección:
0xe9f341c1b12912b1594afa3885c873c91ec66920
Si ejecuto la transferencia como lo haría normalmente
transfer("0xe9f341c1b12912b1594afa3885c873c91ec66920",1);
obtendría
0x40c10f19000000000000000000000000e9f341c1b12912b1594afa3885c873c91ec6692000000000000000000000000000000000000000000000000000000000000000000000000
como entrada de la transacción firmada. Si en su lugar usé la dirección abreviada
transfer("0xe9f341c1b12912b1594afa3885c873c91ec6692",1);
obtendría
0x40c10f190000000000000000000000000e9f341c1b12912b1594afa3885c873c91ec669200000000000000000000000000000000000000000000000000000000000000000000000
Rellenando la entrada con un cero, pero como el encabezado de la dirección, y no detrás como se pretendía. Esto simplemente transferiría los fondos a una dirección a la que no tengo acceso.
¿Encontraste una manera de replicar el ataque?
0x40c10f1900000000000000000000000e9f341c1b12912b1594afa3885c873c91ec66920000000000000000000000000000000000000000000000000000000000000064
.
Luis Soares
Prashant Prabhakar Singh
ismael
Prashant Prabhakar Singh