WEB3DEV

Cover image for Signature Replay | Hack Solidity
Adriano P. Araujo
Adriano P. Araujo

Posted on • Atualizado em

Signature Replay | Hack Solidity

Imagine uma Carteira MultiSig com dois proprietários, Alice **e **Eve, se Eve quiser sacar fundos da Carteira MultiSig, então haverá um total de três transações que ocorrerão.

  1. A aprovação da Solicitação de Retirada de 1 ETH pela Eve

  2. A aprovação da Solicitação de Retirada de 1 ETH pela Alice

  3. A transferência de 1 ETH para Eve

image
Nenhuma assinatura é usada

Agora, vamos considerar o exemplo onde as assinaturas são usadas. Neste caso, apenas uma transação é necessária.

  1. Alice assina uma mensagem dizendo que Eve pode retirar 1 ETH e enviá-lo para Eve off-chain (fora da cadeia). Então, Eve chamará uma função de transferência com a assinatura de Alice e sua própria assinatura.

image
Caso de uso de assinatura

Todos sabemos que as taxas de gas na Ethereum são altas, e realizar três transações em uma é uma perda de tempo e gas. A solução acima adiciona eficiência, mas o problema surge se Eve puder reproduzir ou reutilizar a mesma assinatura várias vezes para retirar fundos.

Vamos discutir três cenários para tal evento e uma possível solução para cada um.

O primeiro cenário é se a assinatura pode ser usada no mesmo smart contract várias vezes. Nesse caso, adicionar um valor nonce antes da assinatura resolverá o problema.

O segundo cenário é se o mesmo código foi implementado em vários endereços. Nesse caso, adicione também o endereço do contrato do qual a retirada deve ocorrer antes de assinar e implementar o nonce.

O terceiro cenário é quando o contrato foi implementado usando create2 e existe uma selfdesctruct (função de autodestruição)no contrato. O create2 implementará sempre o contrato no mesmo endereço. Eve pode executar um loop de criação e destruição do contrato e usar a assinatura repetidamente, pois durante cada recriação o nonce é redefinido. Não estou claro sobre o funcionamento da função create2. Provavelmente vou pesquisar e adicionar um link aqui no futuro.

Chega de teoria, vamos a um exemplo.

Exemplo

Temos um contrato MultiSigWallet que possui funções de depósito e transferência. A função de transferência tem um argumento _sigs, que traz a assinatura de Alice e Eva. Uma transação hash (txHash) é gerada, a qual mais tarde será verificada se foi assinada pelos proprietários antes de prosseguir com a retirada. É evidente a partir do  código que não há mecanismo para adicionar aleatoriedade ao txHash ou verificar se as assinaturas foram usadas anteriormente.

image

A solução

Para evitar os ataques de repetição, passamos o nonce como um argumento que é usado na geração do txHash. Além disso, declaramos um mapeamento chamado executed, que basicamente acompanha o txHash anterior e verifica se o txHash atual foi usado anteriormente. Impedindo com sucesso o Signature Attack(Ataque de Assinatura)

Podemos adicionar o endereço do contrato do qual os fundos precisam ser retirados também na criação do txHash para protegê-lo ainda mais.

image

Espero que você tenha aproveitado a leitura.

Ciao!!!


O presente texto é uma tradução de um artigo de Zuhaib Mohammed
feita por Adriano P. Araujo. Você pode encontrar o artigo original aqui.

Top comments (0)