WEB3DEV

Cover image for Reentrada | Hack Solidity #1
Arnaldo Pereira Campos Junior
Arnaldo Pereira Campos Junior

Posted on • Atualizado em

Reentrada | Hack Solidity #1

Image description

A motivação por trás deste artigo sou eu tentando aprender algumas das vulnerabilidades em smart contracts. Sou grato ao programador de smart contract por me ajudar nessa jornada. Dê uma olhada no canal dele.

Então. Deixe-nos começar!

Tenho certeza de que você já deve ter ouvido falar sobre o famoso ataque DAO, que levou à criação do Ethereum Classic. A vulnerabilidade explorada pelo invasor é chamada de “Reentrância”.

O que é o ataque de reentrância?

Considere que existem dois Contratos A e B, onde o Contrato A chama o Contrato B. Nesse ataque, o que acontece é que, quando a primeira chamada ainda está em execução, o Contrato B chama o Contrato A, e isso meio que resulta em um loop.

Tentaremos entender melhor o ataque com a ajuda do exemplo abaixo. Temos um smart contract chamado EtherStore, onde se pode depositar, sacar e verificar o saldo atual do smart contract.

EtherStore.sol

EtherStore.sol

Vemos que a função withdraw tem um controle para não permitir que o usuário retire mais fundos do que tem, mas o bug está na linha 16. Sempre que enviamos ether para um endereço de smart contract, definimos o que chamamos de fallback. Na maioria dos casos, esta é apenas uma função vazia, mas o invasor é inteligente o suficiente e é aqui que o código de exploração real é colocado.

O Ataque

O invasor chama o exploit, na qual ele deposita 1 ether no contrato EtherStore para passar na verificação da Linha 14 do contrato EtherStore. Quando o código atinge a Linha 16, a fallback do contrato do invasor é invocada onde o invasor chama a função withdraw na EtherStore, até ele drenar os fundos.

Image description

Reentrancy.sol

A Solução

Este ataque é possível porque o código nunca chega à Linha 20 do EtherStore onde subtraímos o valor sacado do EtherStore. Para corrigir isso, temos duas soluções que podem ajudar. A primeira é a reposição da lógica para subtrair o saldo do usuário antes de transferi-lo.

Image description

função retirada() modificada

A segunda solução seria usar um noReentrancy guard modifer que bloqueia o contrato durante a execução e o desbloqueia no final da execução.

Image description

noReentrancy guard modifer

Tentei explicar o problema usando uma linguagem simples e exemplos práticos. Espero que tenha gostado de lê-lo.

Tchau!!!

Artigo escrito por Zuhaib Mohammed e traduzido por Arnaldo Campos . Você pode encontrar o artigo original aqui.

Oldest comments (1)

Collapse
 
dione_b profile image
Dione Bastos

Show de bola, agora para evitar alguma falha de lógica é interessante usar a lib da Openzeppelin (Reentrancy Guard).