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.
A aprovação da Solicitação de Retirada de 1 ETH pela Eve
A aprovação da Solicitação de Retirada de 1 ETH pela Alice
A transferência de 1 ETH para Eve
Agora, vamos considerar o exemplo onde as assinaturas são usadas. Neste caso, apenas uma transação é necessária.
- 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.
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.
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.
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.
Latest comments (0)