Skip to main content
Xcapit
Blog
·13 min de leitura·Fernando BoieroFernando Boiero·CTO & Co-Fundador

Segurança de Smart Contracts: 10 Vulnerabilidades Comuns e Como Preveni-las

blockchaincybersecuritysmart-contracts

Desde o hack da DAO em 2016, vulnerabilidades de smart contracts custaram à indústria blockchain mais de US$8 bilhões em fundos roubados ou congelados. A natureza imutável do blockchain significa que uma vez que um contrato com falhas é implantado, ele não pode ser corrigido — o código é lei, bugs e tudo mais. Toda vulnerabilidade que chega à mainnet é uma potencial exploração esperando para acontecer, e os atacantes são sofisticados, bem financiados e implacáveis.

Mapa do panorama de vulnerabilidades de smart contracts
Vulnerabilidades comuns de smart contracts: de ataques de reentrância à manipulação de oráculos

Entender os padrões de vulnerabilidade mais comuns é a primeira linha de defesa. Este guia cobre dez vulnerabilidades críticas de smart contracts, explica como cada uma funciona e fornece estratégias concretas de prevenção que equipes de desenvolvimento devem implementar antes que qualquer código chegue à produção.

1. Ataques de Reentrância

Reentrância é a vulnerabilidade de smart contract mais infame, responsável pelo hack original da DAO que levou ao hard fork do Ethereum. Ela ocorre quando um contrato faz uma chamada externa a outro contrato antes de atualizar seu próprio estado. O contrato chamado pode então chamar de volta a função original antes que a primeira execução seja completada, criando um loop recursivo que drena fundos além do que deveria ser permitido.

O exemplo clássico é uma função de saque que envia ETH a um usuário antes de zerar seu saldo. Um atacante implanta um contrato com uma função fallback que chama saque novamente ao receber ETH. O resultado é que o atacante pode sacar seu saldo múltiplas vezes antes que o contrato registre a dedução.

Ataques modernos de reentrância evoluíram além do padrão de função única. Reentrância cross-function explora estado compartilhado entre diferentes funções no mesmo contrato. Reentrância cross-contract mira estado compartilhado entre múltiplos contratos em um protocolo. Reentrância somente leitura manipula funções view das quais contratos externos dependem para cálculos de preço ou colateral.

  • Siga o padrão checks-effects-interactions: valide condições, atualize o estado, então faça chamadas externas — nunca o inverso
  • Use guards de reentrância (mutex locks) em todas as funções que alteram estado e fazem chamadas externas
  • Audite para reentrância cross-function e cross-contract, não apenas padrões de função única
  • Considere vetores de reentrância somente leitura se seu contrato expõe funções view usadas por outros protocolos
  • Use padrões pull-over-push de pagamento onde usuários sacam fundos em vez do contrato enviá-los

2. Overflow e Underflow de Inteiros

Overflow de inteiros ocorre quando uma operação aritmética produz um valor maior que o máximo que um tipo de variável pode armazenar, fazendo-o voltar para zero ou um número pequeno. Underflow de inteiros é o inverso — subtrair de zero volta ao valor máximo. Em contratos financeiros, isso pode significar que um usuário com zero tokens de repente tem bilhões, ou um saldo massivo se torna insignificante.

Antes do Solidity 0.8.0, operações aritméticas não verificavam overflow ou underflow por padrão, tornando esta uma das classes de vulnerabilidade mais comuns. O exploit do token BEC em 2018 usou um overflow de inteiro para gerar bilhões de tokens do nada, derrubando o valor do token para zero.

Embora o Solidity 0.8+ inclua verificações de overflow integradas, o perigo não desapareceu. O bloco unchecked desabilita explicitamente essas proteções para otimização de gas. Além disso, conversão de tipo entre diferentes tamanhos de inteiro (uint256 para uint128, por exemplo) pode truncar valores silenciosamente. E protocolos escritos em outras linguagens como Vyper ou Rust têm seus próprios comportamentos de overflow.

  • Use Solidity 0.8.0 ou posterior para se beneficiar das verificações de overflow e underflow integradas
  • Audite cada uso da palavra-chave unchecked para confirmar que overflow é realmente impossível naquele contexto
  • Tenha cuidado com conversão de tipo — valide explicitamente que os valores cabem no tipo de destino antes de converter
  • Use SafeMath ou bibliotecas equivalentes para contratos que devem suportar versões mais antigas do Solidity
  • Teste condições de borda: o que acontece em zero, em valores máximos e nos limites de tipo

3. Front-Running e Ataques MEV

Front-running ocorre quando um atacante vê uma transação pendente na mempool e submete sua própria transação com um preço de gas maior para executar primeiro. Em blockchains públicas, todas as transações pendentes são visíveis antes de serem incluídas em um bloco, criando uma assimetria de informação que atores sofisticados exploram para lucro. Isso é parte do fenômeno mais amplo de Maximal Extractable Value (MEV).

O padrão de front-running mais comum em DeFi é o ataque sanduíche. Um atacante vê um grande swap pendente em uma exchange descentralizada, compra o token alvo primeiro (empurrando o preço para cima), deixa a transação da vítima executar no preço inflacionado, e então vende imediatamente depois para lucrar. A vítima recebe menos tokens do que esperava, e o atacante embolsa a diferença.

Front-running também afeta lançamentos de tokens, mints de NFT, liquidações, atualizações de oráculos e votos de governança. Qualquer transação onde o resultado depende da ordem de execução é potencialmente vulnerável.

  • Implemente proteção de slippage com impacto de preço máximo aceitável definido pelo usuário em todas as funções de swap
  • Use esquemas de commit-reveal para operações onde o conteúdo da transação deve ser ocultado até a execução
  • Considere submissão de transações privadas via Flashbots Protect ou serviços similares de proteção MEV
  • Projete mecanismos que sejam independentes de ordem onde possível — leilões em lote em vez de primeiro a chegar, primeiro a ser servido
  • Defina prazos razoáveis nas transações para evitar que sejam retidas e executadas em momentos desfavoráveis
  • Para governança, use propostas com time-lock e votação por snapshot para prevenir manipulação de votos por flash loan

4. Manipulação de Oráculos

Oráculos fornecem dados externos para smart contracts — mais comumente feeds de preço para protocolos DeFi. Se um atacante pode manipular os dados de preço dos quais um contrato depende, ele pode enganar o protocolo a tomar decisões baseadas em informações falsas. Este é um dos vetores de ataque mais devastadores financeiramente, responsável por centenas de milhões em perdas.

A técnica mais comum de manipulação de oráculos usa flash loans para distorcer temporariamente preços on-chain. Um atacante toma emprestada uma quantidade massiva de tokens, os usa para mover o preço em uma DEX, aciona um protocolo vulnerável que lê aquele preço da DEX, e então lucra com a operação a preço incorreto — tudo em uma única transação. Como flash loans não exigem colateral, o atacante não arrisca nada.

Mesmo provedores de oráculos bem conhecidos não são imunes. Feeds Chainlink podem ter dados obsoletos se as condições de atualização não forem atendidas. Oráculos TWAP da Uniswap podem ser manipulados com capital sustentado ao longo de múltiplos blocos. Implementações customizadas de oráculos frequentemente têm riscos de centralização ou atrasos de atualização que criam janelas de exploração.

  • Use preços médios ponderados pelo tempo (TWAP) em vez de preços spot para resistir à manipulação de bloco único
  • Implemente verificações de desvio de preço que rejeitem atualizações além de um limite razoável
  • Use múltiplas fontes de oráculo independentes com mecanismo de mediana ou consenso
  • Adicione verificações de frescor — rejeite dados de preço mais antigos que um limite definido
  • Implemente circuit breakers que pausem operações durante volatilidade extrema do mercado
  • Nunca use um único pool de DEX como sua única fonte de preço para operações financeiras críticas

5. Falhas de Controle de Acesso

Vulnerabilidades de controle de acesso ocorrem quando funções críticas carecem de verificações de permissão adequadas, permitindo que usuários não autorizados executem operações privilegiadas. Isso inclui funções de inicialização desprotegidas, verificações de papel ausentes em operações administrativas e transferências de propriedade implementadas inadequadamente. O hack da carteira multi-sig Parity, que congelou mais de US$150 milhões em ETH, foi causado por uma função de inicialização desprotegida que qualquer pessoa podia chamar.

O perigo é agravado pela natureza pública do blockchain. Toda função em um contrato é visível e pode ser chamada por qualquer pessoa, a menos que explicitamente restrita. Diferente de software tradicional onde o servidor controla o acesso, smart contracts devem impor suas próprias permissões inteiramente através de código. Não há firewall, não há segmentação de rede e não há validação do lado do servidor — apenas o que o próprio contrato verifica.

Padrões de proxy introduzem complexidade adicional de controle de acesso. O admin do proxy, o proprietário da implementação e a autoridade de upgrade podem ser papéis diferentes, e confusão entre eles cria vulnerabilidades. Padrões de proxy transparente ajudam separando chamadas admin de chamadas de usuário, mas configuração incorreta permanece uma fonte comum de bugs.

  • Use bibliotecas estabelecidas como AccessControl ou Ownable da OpenZeppelin para gestão de permissões
  • Implemente o princípio do menor privilégio — cada papel deve ter apenas as permissões de que precisa
  • Use transferências de propriedade em duas etapas (propor e aceitar) para prevenir transferências acidentais para endereços errados
  • Adicione time-locks a mudanças de parâmetros críticos para que a comunidade possa revisar e reagir antes das mudanças entrarem em vigor
  • Exija aprovação multi-assinatura para operações administrativas — nunca use uma EOA única para governança de protocolo
  • Audite padrões de proxy cuidadosamente, especialmente a relação entre admin do proxy e proprietário da implementação

6. Ataques de Flash Loan

Flash loans permitem que qualquer pessoa tome emprestada uma quantidade ilimitada de tokens com zero colateral, desde que o empréstimo seja pago dentro da mesma transação. Embora sejam uma inovação legítima em DeFi para arbitragem e refinanciamento, se tornaram o principal mecanismo de financiamento para exploits sofisticados. Flash loans efetivamente dão a cada atacante o capital de uma baleia, removendo a barreira financeira para executar ataques de manipulação de mercado.

Um ataque típico de flash loan combina múltiplas vulnerabilidades em uma única transação atômica. O atacante toma emprestados milhões de dólares em tokens, os usa para manipular um oráculo de preço, explora um protocolo que depende daquele oráculo, extrai lucro, paga o empréstimo com juros e fica com a diferença. Se qualquer etapa falhar, toda a transação é revertida e o atacante perde apenas a taxa de gas.

Ataques de flash loan são particularmente perigosos porque são livres de risco para o atacante e podem ser executados por qualquer pessoa com conhecimento técnico para construir a transação. O exploit da Euler Finance em 2023 usou um flash loan para manipular precificação de colateral, resultando em uma perda de US$197 milhões — o maior ataque de flash loan até hoje.

  • Projete protocolos para serem resistentes a flash loans assumindo que qualquer usuário pode ter capital ilimitado em uma única transação
  • Use oráculos TWAP e médias de preço multi-bloco que não podem ser manipulados dentro de uma única transação
  • Implemente períodos mínimos de lock para depósitos antes que possam ser usados como colateral ou poder de voto
  • Adicione restrições de operação no mesmo bloco — impeça depósito e empréstimo na mesma transação quando apropriado
  • Teste seu protocolo com ferramentas de simulação de flash loan para identificar potenciais vetores de ataque
  • Considere se os invariantes do seu protocolo se mantêm quando um usuário tem capital temporário ilimitado

7. Negação de Serviço (DoS)

Negação de serviço em smart contracts ocorre quando um atacante pode impedir usuários legítimos de interagir com um contrato. Diferente de ataques DoS web tradicionais que sobrecarregam servidores com tráfego, DoS em smart contracts explora falhas de lógica que bloqueiam permanentemente ou temporariamente funções críticas.

O padrão mais comum é o DoS de loop ilimitado. Se um contrato itera sobre um array que cresce sem limite — como uma lista de detentores de tokens para distribuição de dividendos — um atacante pode adicionar entradas suficientes para fazer o custo de gas da iteração exceder o limite de gas do bloco. A função se torna permanentemente incapaz de ser chamada, e quaisquer fundos presos atrás dela se tornam inacessíveis.

Outro vetor comum é o DoS de revert inesperado. Se um contrato envia ETH para uma lista de endereços e um desses endereços é um contrato que reverte ao receber, toda a operação em lote falha. Um atacante pode explorar isso para bloquear liquidações de leilões, contagem de votos de governança ou qualquer operação que precise processar uma lista de endereços.

  • Evite loops ilimitados — use padrões de paginação ou defina limites rígidos para tamanhos de array
  • Prefira padrões de pagamento pull-over-push: deixe os usuários sacarem em vez de enviar pagamentos para eles
  • Não faça operações críticas dependerem de chamadas externas terem sucesso — trate falhas de forma elegante
  • Use chamadas externas com limite de gas (call com stipend) para impedir que contratos chamados consumam todo o gas
  • Implemente mecanismos de recuperação de emergência que possam contornar funções bloqueadas quando necessário
  • Teste com cenários adversariais: o que acontece se um participante agir maliciosamente?

8. Bugs de Lógica em Regras de Negócio

Bugs de lógica são vulnerabilidades onde o código faz exatamente o que foi escrito para fazer, mas o que foi escrito não é o que os desenvolvedores pretendiam. Estes são os bugs mais difíceis de capturar porque ferramentas automatizadas procuram padrões de vulnerabilidade conhecidos, enquanto bugs de lógica são únicos para as regras de negócio específicas de cada protocolo.

Exemplos comuns incluem cálculos de taxas incorretos que permitem aos usuários evitar o pagamento de taxas sob condições específicas, fórmulas de distribuição de recompensas que podem ser exploradas depositando e sacando em momentos estratégicos, e mecanismos de liquidação que falham em considerar casos extremos em índices de colateral. O incidente de governança da Compound Finance, onde um bug na lógica de distribuição de recompensas causou a distribuição incorreta de US$90 milhões em tokens, foi um bug de lógica pura — o código executou perfeitamente, mas a fórmula estava errada.

Vulnerabilidades de lógica de negócios são amplificadas pela composabilidade. Quando seu protocolo interage com outros protocolos, o comportamento combinado pode produzir resultados que nenhum protocolo antecipou. Um protocolo de empréstimo e um agregador de yield podem ser seguros individualmente, mas sua interação cria um loop de feedback explorável.

  • Escreva especificações abrangentes antes de codificar — documente cada fórmula, cada caso extremo e cada premissa
  • Implemente testes baseados em propriedades que verificam que invariantes se mantêm em milhares de cenários aleatórios
  • Use verificação formal para propriedades matemáticas críticas como conservação de tokens e solvência
  • Teste com cenários econômicos realistas, não apenas testes unitários — simule condições de estresse de mercado
  • Tenha especialistas de domínio (não apenas pesquisadores de segurança) revisarem a lógica de negócios contra a especificação
  • Documente todas as premissas do protocolo explicitamente e teste o que acontece quando essas premissas são violadas

9. Ataques de Replay de Assinatura

Replay de assinatura ocorre quando uma mensagem assinada válida pode ser reutilizada em um contexto onde não deveria ser aceita. Se um contrato aceita uma autorização assinada para transferir tokens mas não rastreia quais assinaturas foram usadas, a mesma assinatura pode ser submetida múltiplas vezes para drenar todo o saldo do usuário. Reproduzir assinaturas entre chains é outra variante — uma assinatura válida no Ethereum pode ser reproduzida no Polygon ou BSC se o contrato não incluir dados específicos da chain na mensagem assinada.

Esta vulnerabilidade aparece frequentemente em sistemas de meta-transação, transações sem gas, order books off-chain e qualquer sistema que use assinatura de dados tipados EIP-712. A função permit (EIP-2612) é uma implementação comum que permite aprovações de tokens via assinaturas em vez de transações on-chain — e é um alvo comum para ataques de replay quando implementada incorretamente.

O risco é aumentado após forks de chain. Quando o Ethereum transitou para proof-of-stake e a chain fork proof-of-work continuou como ETHW, assinaturas criadas em uma chain eram válidas em ambas. Protocolos que não incluíam o chain ID nos dados assinados eram vulneráveis a replay cross-chain.

  • Inclua um nonce em cada mensagem assinada e rastreie nonces usados on-chain para prevenir reutilização
  • Inclua o chain ID (EIP-155) em todos os dados assinados para prevenir replay cross-chain
  • Inclua o endereço do contrato nos dados assinados para prevenir replay entre diferentes instâncias de contrato
  • Siga o EIP-712 para assinatura de dados estruturados tipados — ele inclui separadores de domínio que previnem a maioria dos vetores de replay
  • Implemente expiração de assinatura com prazos para limitar a janela de potencial replay
  • Após forks de chain, audite todas as funções baseadas em assinatura para vulnerabilidade de replay cross-chain

10. Storage Não Inicializado e Armadilhas de Proxy

Vulnerabilidades de storage não inicializado ocorrem quando variáveis de contrato não são devidamente definidas durante a implantação ou inicialização, deixando-as com valores padrão (zero para inteiros, vazio para endereços) que criam condições exploráveis. Isso é especialmente perigoso com padrões de proxy, onde o construtor do contrato de implementação nunca é chamado — o proxy chama uma função inicializadora em vez disso, e se essa função pode ser chamada por qualquer pessoa, um atacante pode assumir a propriedade do contrato.

O ataque de proxy não inicializado de maior perfil ocorreu contra o contrato de implementação do Wormhole em 2022. A equipe havia deixado o contrato de implementação não inicializado, permitindo que um atacante chamasse a função initialize, assumisse a propriedade e atualizasse o contrato para uma versão maliciosa — resultando em uma perda de US$320 milhões.

Colisão de storage é um risco relacionado em padrões de proxy. Se o proxy e os contratos de implementação usam os mesmos slots de storage para variáveis diferentes, escrever em um corrompe o outro. O padrão EIP-1967 define slots de storage específicos para endereços de admin do proxy e implementação para evitar isso, mas implementações customizadas de proxy frequentemente erram.

  • Sempre chame o inicializador na mesma transação da implantação do proxy para prevenir front-running
  • Use o modifier initializer da OpenZeppelin para garantir que funções de inicialização só possam ser chamadas uma vez
  • Desabilite inicializadores no construtor do contrato de implementação para prevenir ataques de inicialização direta
  • Siga as convenções de slot de storage do EIP-1967 para padrões de proxy para evitar colisões de storage
  • Verifique que todas as variáveis de estado tenham valores iniciais sensatos — nunca assuma que o valor padrão zero é seguro
  • Audite caminhos de upgrade cuidadosamente: garanta que novas versões de implementação não introduzam conflitos de layout de storage

Construindo um Processo de Desenvolvimento Focado em Segurança

Prevenir vulnerabilidades não é apenas sobre conhecer os padrões — requer uma cultura e processo de desenvolvimento que torne a segurança uma preocupação de primeira classe em cada estágio.

  • Escreva uma especificação detalhada antes de escrever código, incluindo todos os casos extremos, premissas econômicas e modos de falha
  • Use bibliotecas estabelecidas e auditadas como OpenZeppelin em vez de implementar padrões comuns do zero
  • Implemente suítes de teste abrangentes: testes unitários para funções individuais, testes de integração para interações cross-contract e fuzz tests para condições de borda
  • Execute ferramentas automatizadas de análise de segurança (Slither, Mythril, Echidna) como parte do seu pipeline CI/CD — não apenas antes de auditorias
  • Conduza revisões internas de segurança com um checklist cobrindo todas as dez categorias de vulnerabilidade deste guia
  • Use verificação formal para invariantes matemáticos críticos como conservação de tokens e índices de colateral
  • Implante em testnets e execute períodos estendidos de teste com monitoramento antes da implantação na mainnet
  • Implemente upgradeability ou circuit breakers que permitam responder a vulnerabilidades descobertas
  • Estabeleça um programa de bug bounty com recompensas significativas proporcionais ao valor que seus contratos protegem
  • Monitore seus contratos pós-implantação com alertas automatizados para padrões de transação incomuns

Quando Fazer uma Auditoria Profissional

Uma auditoria de segurança profissional deve ser considerada obrigatória para qualquer contrato que lidará com valor significativo. Mas nem todas as auditorias são iguais, e o timing importa. Auditar muito cedo — antes do código estar estável — desperdiça dinheiro pois as descobertas ficam desatualizadas a cada mudança. Auditar muito tarde — logo antes do lançamento — não deixa tempo para tratar adequadamente as descobertas.

O timing ideal é após o codebase estar com funcionalidades completas, após revisões internas e análise automatizada terem sido conduzidas, e com margem suficiente antes do lançamento para tratar descobertas e obter uma nova revisão. Planeje pelo menos 4-6 semanas para a auditoria inicial e 2-3 semanas para revisão das correções.

Ao avaliar firmas de auditoria, procure equipes com experiência específica no domínio do seu protocolo — empréstimos DeFi, AMMs, bridges, marketplaces de NFT e sistemas de governança cada um tem padrões de vulnerabilidade únicos. As melhores firmas de auditoria combinam ferramental automatizado, revisão manual de código por múltiplos auditores independentes e modelagem de ataque econômico.

Considere contratar múltiplas firmas de auditoria para protocolos de alto valor. Diferentes auditores têm diferentes forças e pontos cegos, e uma vulnerabilidade crítica encontrada pelo segundo auditor que o primeiro não detectou pode economizar milhões.

Segurança de smart contracts não é uma atividade pontual — é uma disciplina contínua que abrange todo o ciclo de vida do desenvolvimento. As dez vulnerabilidades descritas neste guia respondem pela maioria dos fundos perdidos em exploits de blockchain, e cada uma é prevenível com design, testes e revisão adequados.

Smart Contract Vulnerability Layers

Na Xcapit, nossa equipe de cibersegurança combina expertise profunda em smart contracts com certificação ISO 27001 e anos de experiência em blockchain em produção. De auditorias de segurança e testes de penetração a construção de processos de desenvolvimento focados em segurança, ajudamos projetos blockchain a proteger seus usuários e sua reputação. Saiba mais sobre nossos serviços de cibersegurança.

Share
Fernando Boiero

Fernando Boiero

CTO & Co-Fundador

Mais de 20 anos na indústria de tecnologia. Fundador e diretor do Blockchain Lab, professor universitário e PMP certificado. Especialista e líder de pensamento em cibersegurança, blockchain e inteligência artificial.

Vamos construir algo incrível

IA, blockchain e software sob medida — pensado para o seu negócio.

Entre em contato

Construindo em blockchain?

Tokenização, smart contracts, DeFi — já implementamos tudo isso.

Artigos Relacionados

·11 min

Construindo Pipelines DevSecOps para Projetos Blockchain

Como projetar e implementar um pipeline DevSecOps desenvolvido especificamente para projetos blockchain — análise estática de smart contracts, pipelines de auditoria automatizadas, gerenciamento de segredos, automação de deployment e monitoramento pós-deployment.