WEB3DEV

Cover image for Recomendações de Auditor: Checklist do Solidity & Ataque de Reentrância | Parte 2/3
Fatima Lima
Fatima Lima

Posted on

Recomendações de Auditor: Checklist do Solidity & Ataque de Reentrância | Parte 2/3

Continuamos nossa série de artigos educativos e hoje veremos algumas dicas específicas para auditoria durante o desenvolvimento de contratos inteligentes no Solidity!

Image description

Hoje também damos continuidade a uma série exclusiva de três partes, na qual discutiremos várias facetas do trabalho de um auditor (ou desenvolvedor, se estivermos falando de auditoria interna), desde a otimização de gas até a proteção contra ataques e limitações da EVM. Garantimos que será divertido!

A propósito, há algumas vagas agora, portanto, se o seu projeto precisar de uma auditoria, sinta-se à vontade para escrever para nós, visite nossa página de relatórios públicos aqui. Entre em contato: [email protected]!

Por que você precisa ler este artigo?

Contratos inteligentes são contratos que são autoexecutáveis porque as condições do acordo são colocadas diretamente no código. Eles são imutáveis e executados em uma rede blockchain descentralizada. Devido à sua natureza, protegê-los e auditá-los é fundamental por vários motivos.

Para começar, a segurança é fundamental em qualquer aplicativo descentralizado (DApp) porque ele lida com transações monetárias e dados de usuários. Até mesmo pequenas vulnerabilidades ou erros de programação em contratos inteligentes podem ter implicações desastrosas, como perda de fundos ou acesso ilegal a dados. Podemos garantir que os contratos inteligentes sejam resistentes a ataques e que as possíveis brechas sejam fechadas, protegendo-os.

Para isso, vários procedimentos de segurança devem ser seguidos. Para começar, devem ser implementados padrões de codificação seguros, como o Solidity. Usar bibliotecas matemáticas seguras e evitar recursos obsoletos ou experimentais são exemplos de práticas recomendadas. Para evitar o acesso não autorizado, as funções e variáveis do contrato devem ser marcadas corretamente como públicas, privadas ou internas.

Auditor’s Notes: Semantic Grep & Solidity

Além disso, as auditorias são essenciais para detectar vulnerabilidades e problemas de lógica em contratos inteligentes. A auditoria implica um exame minucioso da base de código do contrato e da funcionalidade planejada para garantir que ela se alinhe às metas do projeto e não apresente riscos. Os auditores procuram falhas de segurança, possíveis dificuldades de reentrada, processamento inadequado de dados e outras falhas de programação no contrato.

Nos últimos meses, temos desenvolvido ativamente nossos próprios detectores Slither (consulte nossa ferramenta Slitherin) para auxiliar na revisão do código e no processo de auditoria. Informe-nos caso tenha descoberto um problema/bug/vulnerabilidade por meio de nossos detectores Slither personalizados. Você pode entrar em contato conosco abrindo um PR/Issue ou diretamente, o que for mais conveniente para você!

As auditorias são essenciais para detectar possíveis riscos à segurança e evitar possíveis explorações que possam ser aproveitadas por agentes mal-intencionados. Elas fornecem uma camada extra de garantia ao identificar falhas que podem ter sido negligenciadas durante o desenvolvimento. Além disso, as auditorias ajudam a atender aos requisitos regulamentares e, ao mesmo tempo, aumentam a credibilidade e a confiança entre usuários e investidores, na medida em que demonstram um compromisso com a segurança.

Além disso, as auditorias podem ajudar a avaliar os aspectos econômicos e de teoria dos jogos dos contratos inteligentes. Garantir que a lógica e os incentivos do contrato estejam alinhados com os resultados desejados é fundamental em sistemas descentralizados. Ao auditar o contrato, podemos verificar se ele se comporta como esperado e se as variáveis econômicas, como mecanismos de emissão de tokens ou mecanismos de staking, estão alinhadas com as metas do projeto.

Reentrancy Attacks on Smart Contracts Distilled

Além dos aspectos técnicos, as auditorias também oferecem uma oportunidade de revisão da linguagem natural. A base de código é frequentemente revisada por especialistas que podem identificar e corrigir quaisquer ambiguidades ou inconsistências no código, tornando-o mais legível e compreensível.

O lançamento de um projeto sem a proteção e auditoria dos contratos inteligentes é um risco significativo. Isso pode expor o projeto a possíveis vulnerabilidades, levando a perdas financeiras, danos à reputação e consequências legais. Os investidores e usuários estão cada vez mais cautelosos e conscientes dos riscos envolvidos em sistemas descentralizados e tendem a preferir projetos que tenham sido auditados por empresas de boa reputação.

Solidity vs. Vyper | EVM Smart Contract Language Comparisons

Em resumo, a proteção e a auditoria de contratos inteligentes antes do lançamento de um projeto são fundamentais para garantir a segurança, a confiabilidade e a credibilidade do aplicativo descentralizado. Isso atenua as possíveis vulnerabilidades, aumenta a confiança entre usuários e investidores, alinha os incentivos econômicos e ajuda a atender aos requisitos regulatórios.

Podemos dizer com segurança que essas dicas podem ser lidas publicamente em poucos lugares e nosso blog é um desses lugares. A seguir, apresentamos nossas observações - apenas fatos secos para auditores, truques e os melhores hacks do dia a dia compartilhados por nossos melhores auditores.

Tudo o que você vê abaixo é baseado em nossa experiência pessoal. E hoje, queridos leitores, isso será disponibilizado para vocês!

Concluímos nossa própria pesquisa há alguns meses; leia-a se ainda não o fez:

Short Types in Solidity: Rare Tricks Uncovered

Você também encontrará uma lista de ferramentas e pesquisas para seu próprio estudo e recomendamos enfaticamente que você as leia separadamente para melhor compreensão! Vamos começar!

I — Checagens de Reentrância

Em termos simples, o ataque de Reentrância ocorre entre dois contratos inteligentes, em que um contrato inteligente atacante explora o código em um contrato vulnerável para drenar seus fundos.

A exploração funciona de forma que o contrato inteligente atacante chame repetidamente a função withdraw (retirada) antes que o contrato inteligente vulnerável tenha tido tempo de atualizar o saldo.

Como nosso time vem trabalhando desde 2016, acumulamos um grande número de observações, que ofereceremos aqui, juntamente com várias recomendações de segurança. As técnicas listadas abaixo podem ajudá-lo a aumentar consideravelmente a segurança da integridade do seu projeto:

  • Descrição dos padrões para o Slither: reentrancy-eth (ataque no momento do envio de ether), reentrancy-no-eth (ataque a qualquer função externa sem o envio de ether), reentrancy-benign (ataque possível, mas nenhum dano causado), reentrancy-events (exibe eventos na ordem errada, o que pode causar problemas para terceiros). Para evitar esses ataques, o padrão check-effects-interactions deve ser utilizado em todos os casos;
  • Consulte: Reentrancy Attacks on Smart Contracts Distilled; Read-only Reentrancy: In-Depth; Slither Detectors by Pessimistic.io;
  • É muito importante identificar todos os locais em que a execução passa, para endereços não seguros: msg.sender, token especificado pelo usuário etc. Rastrear de quais lugares "chegamos lá". As violações de CEI podem ser bastante invisíveis se forem usados métodos internos ou herança;
  • Se for usado um modificador non-reentrant, ele normalmente deverá estar em todos os métodos que não sejam de visualização. Lembre-se de que non-reentrant não protege o sistema de contratos, mas, apenas cada contrato individualmente;
  • Algumas vezes podem-se encontrar ataques de reentrância de somente leitura, possíveis durante a leitura de dados de ativos. Os ataques são realizados durante as chamadas callback (de retorno), quando os valores de todos os novos saldos de tokens ainda não foram registrados;
  • Devemos lembrar que os métodos de visualização podem não funcionar corretamente se já estivermos dentro desse contrato (contratos de integração podem ter problemas).

#100DaysOfSolidity #067 Decoding Re-Entrancy Attacks in Solidity Smart Contracts: A Comprehensive…

Referências Úteis

Gostaríamos de expressar nossa sincera gratidão aos autores de todos os materiais de referência! Dê uma olhada neles:

Também concluímos nossa própria pesquisa há alguns meses; leia-a se ainda não o fez:

Read-only Reentrancy: In-Depth

II — Outras Verificações

Ninguém pode negar que a base de qualquer integração segura é uma abordagem única para a criação de códigos. Como resultado, este artigo se concentrará apenas nas áreas que podem ser muito valiosas para manter seu código seguro e protegido. Concluímos nossa própria pesquisa há alguns meses; leia-a se ainda não o fez:

Auditor’s Notes: Semantic Grep & Solidity 2.0

A integração de seu projeto será substancialmente mais segura se você implementar as recomendações abaixo:

Valor de Retorno não Utilizado

  • call/delegatecall/staticcall/callcode/send — sempre verifica o valor de retorno;
  • SafeMath e análogos — sempre x+=y; se torna x.add(y) ao invés de x=x.add(y);
  • Muitos padrões e projetos retornam um bool (ERC20) ou um código de erro (Compound), que devem ser verificados;

Controle de Acesso

  • Controle de Acesso— verificar se as funções têm verificação adequada do chamador: Por exemplo, você não pode usar tx.origin para verificar o chamador (med); e, é uma prática muito ruim separar os contratos da EoA;
  • Quase sempre os setters devem ser protegidos por algum tipo de função;
  • initialize() e seus análogos também devem ser protegidos por algo;
  • Às vezes, as funções do contrato só devem ser chamadas a partir de outro contrato do mesmo projeto. Nesse caso, deve haver uma verificação "onlyThatContract";
  • Ao usar TimelockController da OpenZeppelin, o desenvolvedor obtém funções de administrador para as funções de proponente e executor. Na documentação é recomendável removê-lo das funções de administrador imediatamente após a implantação, caso contrário, ele ficará sobrecarregado - o desenvolvedor poderá controlar todo o processo de governança, ignorando o bloqueio de tempo;

Chamadas para Endereços "Personalizados"

  • Por meio de uma chamada arbitrária em um contrato C1, o C2 pode ser chamado, o que significa que é o C1 que o chama. Isso ignora as verificações de msg.sender em C2. Por exemplo, se houver um sistema de dois contratos C1 e C2:

a) C1.foo() faz uma chamada arbitrária (além de, possivelmente, mais alguma coisa);

b) C1.bar() faz todos os tipos de verificações e chama C2.xyz();

c) C2.xyz() faz algo muito importante e é protegido por onlyC1, então as verificações de C1.bar podem ser contornadas por C1.foo()->C2.xyz() (onlyC1 não perceberá o truque);

  • Se o contrato A tiver ativos (ether ou tokens) no contrato A e o contrato A fizer uma delegatecall para o "usuário" do contrato B, o contrato B poderá retirar ativos do balanço patrimonial do contrato A;
  • Não podemos descartar o caso em que não haja tokens, mas haja uma moeda nativa. Se o projeto estiver localizado em uma cadeia específica em que a moeda nativa é um contrato pré-compilado (por exemplo, Moonbeam e tokens MOVR e GLMR), uma delegatecall também poderá ser executada para ele. Exemplo de vulnerabilidade;
  • O uso da função fallback() no código do contrato deve ser feito com muito cuidado. A presença da função fallback() sem reversão e sem condições permite a execução, para esse contrato, de uma função com qualquer assinatura que não seja apresentada no código-fonte do contrato (pode ser maliciosa);
  • Potential DoS: o endereço pode simplesmente fazer um drop ou "devorar" todo o gas e o contrato de chamada não deve, de forma alguma, atrasar ou congelar por causa disso (relevante para o padrão State Machine). Também relevante para **.send()**, **.transfer()**.;
  • Delegatecall para um endereço falso pode remover o contrato de chamada ou interromper completamente o armazenamento;
  • A partir da versão 0.5, o compilador insere uma verificação do endereço chamado (que é um contrato e não uma EoA). Mas para chamadas de baixo nível (.call, .delegatecall e outras) e assembly não há essa verificação. A chamada de um endereço sem contrato não criará nenhum erro, mas a lógica nem sequer será iniciada.

Referências Úteis

Gostaríamos de expressar nossa sincera gratidão aos autores de todos os materiais de referências! Dê uma olhada neles:

Para concluir, gostaríamos de dizer que esperamos que este artigo tenha sido esclarecedor e útil para você! Obrigado por ler! 🙂

O mais importante que gostaríamos de dizer e mostrar é que um instrumento novo não é sinônimo de bom e um instrumento antigo não é sinônimo de ruim. Tudo se resume a saber como usá-lo e estar disposto a procurar algo novo. Esperamos que você tenha se interessado por isso!

Nos últimos meses, temos desenvolvido ativamente nossos próprios detectores Slither (consulte nossa ferramenta Slitherin) para auxiliar na revisão do código e no processo de auditoria. Informe-nos caso tenha descoberto um problema/bug/vulnerabilidade por meio de nossos detectores Slither personalizados. Você pode entrar em contato conosco abrindo um PR/Issue ou diretamente, o que for mais conveniente para você!

Quais instrumentos devemos analisar? Sobre o que você teria interesse em ler? Deixe seus comentários, teremos prazer em respondê-los e as melhores respostas e perguntas poderão ser incluídas no próximo artigo!

A propósito, há algumas vagas agora, portanto, se o seu projeto precisar de uma auditoria, sinta-se à vontade para escrever para nós, visite nossa página de relatórios públicos aqui.

Mantenha-se em segurança!

Esse artigo foi escrito Officer's Notes e traduzido por Fátima Lima. O original pode ser lido aqui.

Top comments (0)