WEB3DEV

Cover image for Overflow & Underflow de Inteiros em Solidity
Fatima Lima
Fatima Lima

Posted on • Atualizado em

Overflow & Underflow de Inteiros em Solidity

Sumário
  1. Vulnerabilidades
  2. Overflow de Inteiros
  3. Underflow de Inteiros
  4. Ataque Explicado
  5. Estudo do Impacto
  6. Prevenção
  7. Conclusão

A Máquina Virtual Ethereum especifica números inteiros com tipos de dados de tamanho fixo. Isso significa que uma variável integer (número inteiro) só pode representar números em um determinado intervalo. As variáveis na Solidity podem ser exploradas se o input (entrada) do usuário não for verificado e forem feitos cálculos que resultem em números que estejam fora do intervalo do tipo de dados que os contém. Em versões da Solidity anteriores às versões 0,8.x, uma variável integer mudaria automaticamente para um número inferior ou superior quando atingisse o piso ou teto do seu intervalo.

Quando usamos um valor que seja maior do que o valor que um uint possa acomodar, ele empacota de volta a um número que possa ser aceito. Este empacotamento é geralmente para o valor mais baixo ou mais alto absoluto que o uint pode armazenar. Por exemplo, considere um número decimal de dois dígitos sem sinal. Quando o número 99 é atingido e depois aumentado em um, o resultado se torna 00. Em contraste, se pegarmos o número decimal de dois dígitos sem sinal mais baixo, 00, e tentarmos subtrair 1 dele, acabaremos com o valor mais alto deste intervalo de dois dígitos, que é 99.

A declaração "uint8" representa um número inteiro sem sinal com um valor de intervalo inferior a 0 e um valor de intervalo superior a 255 (2⁸ — 1).

Vulnerabilidades

Overflow de Inteiros

Um overflow de número inteiro é um tipo de vulnerabilidade que já existe há muito tempo. A maioria das linguagens de computador usa números inteiros que só podem ir até um determinado valor. Por exemplo, é possível que a soma de dois inteiros extremamente grandes resulte em um número muito pequeno devido à capacidade do tipo de dados subjacente ou às limitações de armazenamento.

Em termos simples, o overflow ocorre quando um inteiro sem sinal (uint) atinge seu valor máximo. Depois disso, qualquer valor adicionado a ele retornará ao valor do início de sua faixa.

Digamos que temos uma variável uint256, que só pode conter valores no intervalo [0, 2²⁵⁶ — 1].

O resultado seria o menor valor nesta faixa uint256, que é 0, se você aumentar o maior número nesta faixa em 1. Isto é um overflow.

 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ 0x000000000000000000000000000000000001
-----------------------------------------
= 0x000000000000000000000000000000000000
Enter fullscreen mode Exit fullscreen mode

Underflow de Inteiros

Como os números inteiros sem sinal não podem suportar números com sinal (negativos), subtrair 1 de seu valor mais baixo que 0 (zero) resultaria no valor máximo em sua faixa, em vez de -1. Isto é um underflow para uint256.

 0x000000000000000000000000000000000000
- 0x000000000000000000000000000000000001
-----------------------------------------
= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
Enter fullscreen mode Exit fullscreen mode

Ataque Explicado

Considere o contrato abaixo IntegerOverflow.sol,

Code editor

Linha 6–10:

Na linha 6 do contrato, declaramos uma variável uint256 chamada number (número). Na linha 8 do contrato, criamos uma função chamada setNumber, com um parâmetro chamado num.

Quando esta função setNumber é chamada passando um valor uint256, será atribuído à variável `num' o valor deste parâmetro que foi passado.

Linhas 12–14:

Vamos assumir que o parâmetro passado para a função setNumber foi o valor mais baixo do tipo de dados uint256, que é 0 (zero).

Depois disto, uma chamada invocada na função decrease (diminuir) do contrato, que intuitivamente pega a variável number e subtrai 1 dela, retornaria o valor mais alto da faixa uint256, que é 2**256-1. Isto cria um underflow.

Linhas 16–18:

Da mesma forma, vamos assumir que o parâmetro passado para a função setNumber seja o valor mais alto da variável uint256, que é 2**256–1.

Depois disso, uma chamada é invocada na função increase (aumentar) do contrato, que intuitivamente pega a variável number definida anteriormente e adiciona 1 a ela, o que retornaria o valor mais baixo na faixa uint256, que é 0 (zero). Isso cria um overflow.

Estudo do Impacto

PoWH Coin Ponzi Scheme

Em 2018, o grupo 4chan lançou a Proof of Weak Hands Coin (Prova da Moeda de Mãos Fracas), uma criptomoeda Ponzi scheme disfarçada de um esquema de pirâmide. Seu valor subiu para mais de $1.000.000; entretanto, logo depois, 866 ETH desapareceram do contrato devido a uma vulnerabilidade em seu código. Uma falha de implementação do ERC-20 no código da PoWH permitiu aos usuários autorizar outros usuários a transferirem tokens em seu nome.

Assim, foi possível a um ator malicioso criar uma segunda conta para vender tokens da primeira conta. Os tokens vendidos da primeira conta seriam, no entanto, retirados do saldo da segunda conta. O underflow de inteiro sem sinal resultante deixaria a segunda conta com um saldo extremamente grande de Moedas PoWH, que foram finalmente vendidas por mais de 866 ETH e valeram aproximadamente 952.600 dólares durante o tempo deste incidente.

Prevenção

Uma abordagem convencional para proteger contra erros de underflow ou overflow é usar ou construir bibliotecas matemáticas que substituam os operadores matemáticos padrão: adição, subtração e multiplicação.

A biblioteca SafeMath da Open Zeppelin fornece as operações aritméticas fundamentais, bem como a capacidade de gerar erros com base nas pré e pós-condições para determinar se ocorreu um overflow ou underflow.

Os compiladores Solidity com versões acima de 0.8.0 podem verificar automaticamente a existência de overflows e underflows e gerar um erro se os valores saírem dos limites. Além disso, também é importante projetar adequadamente o contrato inteligente a fim de evitar possíveis ataques de Negação de Serviço que são baseados em problemas de overflow e underflow de números inteiros.

Conclusão

Assim, quando o valor de um tipo inteiro (integer) excede seu valor máximo, ocorre um overflow de número inteiro e o valor empacota o valor mínimo desse tipo.

Por outro lado, quando o valor de um tipo inteiro (integer) fica abaixo de seu valor mínimo, ocorre um underflow de número inteiro e o valor empacota o valor máximo desse tipo.

Enquanto tanto o overflow quanto o underflow de um número inteiro possam levar a um comportamento inesperado e potencialmente prejudicial em um contrato inteligente, o underflow é geralmente considerado mais perigoso do que o overflow. Isto ocorre porque um underflow pode fazer com que a lógica do programa falhe de tal forma que os invasores possam lucrar enormemente com a exploração.

Por exemplo, suponha que um contrato inteligente utilize uma variável uint256 para rastrear os saldos das contas. Se um invasor for capaz de enganar o contrato inteligente para subtrair incorretamente um valor maior do que seu saldo, ocorrerá um underflow de inteiro, o que levará o valor computado a se aproximar do valor máximo uint256. Isto permite que um invasor retire mais fundos do que deveria, às vezes até mesmo podendo drenar completamente todos os ativos do contrato inteligente.

Sobre Nós

O projeto Neptune Mutual protege a comunidade Ethereum das ameaças cibernéticas. O protocolo utiliza a cobertura paramétrica em oposição ao seguro discricionário. Ele tem um processo de reivindicação on chain fácil e confiável. Isso significa que quando os incidentes são confirmados por nossa comunidade, a resolução é rápida.

Junte-se a nós em nossa missão de cobrir, proteger e assegurar ativos digitais on chain.

Site Oficial: https://neptunemutual.com \
Blog: https://neptunemutual.com/blog/ \
Twitter: https://twitter.com/neptunemutual \
Reddit: https://www.reddit.com/r/NeptuneMutual \
Telegram: https://t.me/neptunemutual \
Discord: https://discord.gg/2qMGTtJtnW \
YouTube: https://www.youtube.com/c/NeptuneMutual \
LinkedIn: https://www.linkedin.com/company/neptune-mutual

Esse artigo foi escrito por Neptune Mutual e traduzido por Fátima Lima. O original pode ser lido aqui.


Abrace a oportunidade de elevar sua jornada de desenvolvimento para um nível superior. Overflow & Underflow de Inteiros em Solidity é apenas o começo; os builds incríveis da WEB3DEV representam a chave de entrada para o emocionante cenário web3. 🚀🧑‍💻

Não perca tempo, 👉inscreva-se👈 agora mesmo e comece a desbravar o universo Blockchain!
 
Seja também WEB3DEV!

Top comments (0)