Lição: 088: Ataque de Endereço Curto
Nesta aula, vamos explorar o Ataque de Endereço Curto, uma vulnerabilidade encontrada em contratos inteligentes do Ethereum. Esse ataque permite que atores maliciosos explorarem o comportamento das funções de contrato que lidam com endereços, especialmente quando essas funções não validam adequadamente os tamanhos de entrada.
Entendendo o Ataque de Endereço Curto
O Ataque de Endereço Curto ocorre quando um atacante envia uma transação com um endereço formatado incorretamente para um contrato inteligente. Especificamente, o atacante pode enviar um endereço truncado, o que pode levar a comportamentos ou alterações de estado não intencionais no contrato. Essa vulnerabilidade surge devido à forma como o Solidity lida com os tamanhos dos argumentos e como os dados da transação do Ethereum podem ser alterados.
Como Funciona
Ao invocar uma função de contrato, o Ethereum permite que o remetente especifique o tamanho dos dados que estão sendo enviados. Se uma função espera um endereço (que normalmente requer 20 bytes), mas um atacante envia apenas uma parte dele (por exemplo, 1 byte), o Solidity aceitará a entrada e interpretará os bytes fornecidos de acordo com suas regras de codificação. Como resultado, os bytes restantes na memória serão, por padrão, zero, permitindo que o atacante manipule os estados do contrato.
Vamos ilustrar isso com um exemplo.
Exemplo de um Contrato Vulnerável
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Vulneravel {
mapping(address => uint256) public saldos;
function depositar() public payable {
saldos[msg.sender] += msg.value;
}
function transferir(address para, uint256 quantia) public {
require(saldos[msg.sender] >= quantia, "Saldo insuficiente");
saldos[msg.sender] -= quantia;
saldos[para] += quantia;
}
}
Neste contrato, a função transferir
permite que os usuários transfiram fundos para outro endereço. No entanto, ela não valida o tamanho do endereço que o parâmetro para
pode receber.
Realizando o Ataque
Um atacante poderia enviar uma transação que especifica apenas os primeiros poucos bytes de um endereço corretamente dimensionado, por exemplo:
// Esta seria a entrada para o método de transferir:
const enderecoCurto = "0xabcdef01"; // Apenas 4 bytes em vez de 20
Quando o contrato processa esse endereço, os bytes restantes seriam, por padrão, zero, redirecionando efetivamente os fundos para o endereço 0xabcdef0000000000000000000000000000000000
, que pode ser um alvo não intencionado.
Mitigando a Vulnerabilidade
Para evitar Ataques de Endereço Curto, é essencial realizar uma validação adequada da entrada. No Solidity, você pode alcançar isso verificando o tamanho dos dados de entrada. Aqui está uma versão atualizada da função transferir
que inclui a validação necessária:
contract Seguro {
mapping(address => uint256) public saldos;
function depositar() public payable {
saldos[msg.sender] += msg.value;
}
function transferir(address para, uint256 quantia) public {
require(para != address(0), "Endereço inválido");
require(para == address(uint160(para)), "Formato de endereço inválido");
require(saldos[msg.sender] >= quantia, "Saldo insuficiente");
saldos[msg.sender] -= quantia;
saldos[para] += quantia;
}
}
Melhorias Principais
- Validação de Endereço: O
require(para != address(0))
garante que o endereço de destino não seja um endereço nulo, que é uma proteção comum. - Verificação de Casting de Tipo: A instrução
require(para == address(uint160(para)))
verifica o casting do endereço. Isso garante que o endereço fornecido realmente esteja em conformidade com o formato esperado de um endereço típico do Ethereum.
Conclusão
Nesta aula, discutimos o Ataque de Endereço Curto e demonstramos como ele pode comprometer contratos inteligentes ao aceitar dados de tamanho inadequado. Fornecemos um exemplo de um contrato vulnerável e, em seguida, mostramos como protegê-lo implementando verificações apropriadas.
Lembre-se sempre de validar minuciosamente as entradas em seus contratos inteligentes para protegê-los contra vulnerabilidades comuns, como o Ataque de Endereço Curto.