Análise de vulnerabilidades do compilador Solidity e práticas de prevenção de segurança

Análise de vulnerabilidades do compilador Solidity e estratégias de resposta

O compilador é uma das partes fundamentais dos sistemas de computação modernos. É um tipo especial de programa de computador que é responsável por converter o código fonte da linguagem de programação de alto nível, que é fácil para os humanos entenderem e escreverem, em código de instrução que pode ser executado pela CPU de baixo nível ou por uma máquina virtual de bytecode.

Embora a maioria dos desenvolvedores e especialistas em segurança geralmente se concentrem na segurança do código do aplicativo, a segurança do próprio compilador não deve ser ignorada. Como um tipo de programa de computador, os compiladores também podem ter vulnerabilidades de segurança, que em certas circunstâncias podem representar riscos de segurança graves. Por exemplo, ao compilar e analisar o código Javascript no front-end, os navegadores podem, devido a vulnerabilidades no mecanismo de análise do Javascript, permitir que atacantes explorem essas vulnerabilidades para executar código remotamente quando os usuários acessam páginas da web maliciosas, eventualmente controlando o navegador da vítima ou até mesmo todo o sistema operacional.

O compilador Solidity não é exceção, existem vulnerabilidades de segurança em várias versões diferentes.

Vulnerabilidade do compilador Solidity

A principal função do compilador Solidity é converter o código do contrato inteligente escrito pelos desenvolvedores em código de instruções executável pela Máquina Virtual Ethereum (EVM). Este código de instruções EVM é empacotado e enviado para a rede Ethereum através de transações, sendo finalmente processado e executado pela EVM.

É importante notar que as vulnerabilidades do compilador Solidity são diferentes das vulnerabilidades da própria EVM. As vulnerabilidades da EVM referem-se a problemas de segurança que ocorrem quando a máquina virtual executa instruções. Como os atacantes podem carregar qualquer código na rede Ethereum, esse código acabará sendo executado em cada programa cliente P2P Ethereum. Se houver vulnerabilidades de segurança na EVM, isso pode afetar toda a rede Ethereum, causando negação de serviço (DoS) ou até permitindo que um atacante controle toda a blockchain. No entanto, devido ao design relativamente simples da EVM e à infrequente atualização do código central, a probabilidade de tais problemas ocorrerem é baixa.

Vulnerabilidades do compilador Solidity referem-se a problemas que ocorrem quando o compilador converte código Solidity em código EVM. Ao contrário do caso em que um navegador compila e executa Javascript no computador do cliente do usuário, o processo de compilação do Solidity ocorre apenas no computador do desenvolvedor de contratos inteligentes e não é executado na rede Ethereum. Portanto, as vulnerabilidades do compilador Solidity não afetam diretamente a rede Ethereum em si.

Uma das principais ameaças das vulnerabilidades do compilador Solidity é que elas podem levar a um código EVM gerado que não corresponde às expectativas dos desenvolvedores de contratos inteligentes. Como os contratos inteligentes na Ethereum geralmente envolvem os ativos de criptomoeda dos usuários, qualquer bug no contrato inteligente causado pelo compilador pode resultar em perdas de ativos dos usuários, resultando em consequências graves.

Os desenvolvedores e auditores de contratos podem se concentrar em problemas de implementação lógica do código do contrato, bem como em questões de segurança a nível de Solidity, como reentrância e estouro de inteiros. No entanto, apenas auditar a lógica do código-fonte do contrato torna difícil identificar vulnerabilidades no compilador Solidity. É necessário analisar conjuntamente a versão específica do compilador e padrões de código específicos para determinar se o contrato inteligente é afetado por vulnerabilidades do compilador.

Análise de vulnerabilidades do compilador Solidity e medidas de resposta

Exemplo de vulnerabilidade do compilador Solidity

Aqui estão alguns exemplos reais de vulnerabilidades do compilador Solidity, que mostram suas formas específicas, causas e danos.

SOL-2016-9 HighOrderByteCleanStorage

Esta vulnerabilidade existe em versões anteriores do compilador Solidity (>=0.1.6 <0.4.4).

Considere o seguinte código:

solidity contrato C { uint32 a = 0x1234; uint32 b = 0; função f() pública { a += 1; } função run() público ver retorna (uint) { return b; } }

A variável storage b não foi modificada, portanto a função run() deveria retornar o valor padrão 0. No entanto, no código gerado pela versão vulnerável do compilador, run() realmente retorna 1.

É difícil para os desenvolvedores comuns identificar problemas no código acima apenas por meio de uma simples revisão de código. Embora este exemplo seja relativamente simples e possa não resultar em consequências particularmente graves, se a variável b for utilizada para validação de permissões, contabilidade de ativos e outras funções críticas, essa situação inconsistente com o esperado pode levar a sérios riscos de segurança.

A raiz deste problema reside no fato de que a EVM utiliza uma máquina virtual baseada em pilha, onde cada elemento da pilha tem 32 bytes de tamanho (ou seja, o tamanho da variável uint256). Cada slot no armazenamento subjacente também tem 32 bytes de tamanho. A linguagem Solidity suporta tipos de dados menores que 32 bytes, como uint32, e o compilador, ao lidar com variáveis desses tipos, precisa realizar operações apropriadas de limpeza nos bits mais significativos (clean up) para garantir a correção dos dados. Na situação mencionada, quando a adição resulta em um estouro de inteiro, o compilador não limpou corretamente os bits mais significativos do resultado, resultando na escrita de um bit de 1 nos bits mais significativos do armazenamento após o estouro, o que acabou por sobrescrever a variável a, alterando o valor da variável b para 1.

SOL-2022-4 Efeitos Laterais de Memória em Inline Assembly

A vulnerabilidade existe nas versões do compilador >=0.8.13 <0.8.15. Considere o seguinte código:

solidity contrato C { function f() public pure returns (uint) { assembly { mstore(0, 0x42) } uint x; assembly { x := mload(0) } return x; } }

O compilador Solidity, ao converter a linguagem Solidity em código EVM, não se limita a uma simples tradução. Ele também realiza uma análise aprofundada do fluxo de controle e dos dados, implementando vários processos de otimização de compilação para reduzir o tamanho do código gerado e otimizar o consumo de gas durante a execução. Esse tipo de operação de otimização é comum em compiladores de várias linguagens de alto nível, mas devido à complexidade das situações a serem consideradas, é suscetível a bugs ou vulnerabilidades de segurança.

A vulnerabilidade do código acima resulta desse tipo de operação de otimização. O compilador considera que, se houver um código em uma função que modifica os dados no deslocamento de memória 0, mas não houver nenhum outro lugar que utilize esses dados posteriormente, então o código que modifica a memória 0 pode ser removido diretamente, economizando gas e sem afetar a lógica do programa subsequente.

Esta estratégia de otimização em si não tem problema, mas na implementação específica do código do compilador Solidity, tal otimização é aplicada apenas a um único bloco de assembly. No código PoC acima, as operações de escrita e acesso à memória 0 estão em dois blocos de assembly diferentes, enquanto o compilador apenas analisou e otimizou o bloco de assembly isolado. Como não há nenhuma operação de leitura após a escrita na memória 0 no primeiro bloco de assembly, a instrução de escrita é considerada redundante e será removida, resultando em um bug. Na versão vulnerável, a função f( retornará o valor 0, enquanto na verdade o valor correto que o código acima deveria retornar é 0x42.

) SOL-2022-6 AbiReencodingHeadOverflowWithStaticArrayCleanup

A vulnerabilidade afeta compiladores nas versões >= 0.5.8 < 0.8.16. Considere o seguinte código:

solidity contrato C { function f###string( calldata a[1] external pure returns )string memory( { return abi.decode)abi.encode(a(, )string([1])); } }

Normalmente, a variável a retornada pelo código acima deve ser "aaaa". Mas na versão com vulnerabilidades, será retornada uma string vazia "".

A causa da vulnerabilidade é que o Solidity, ao realizar a operação abi.encode em um array do tipo calldata, limpou erroneamente alguns dados, resultando na modificação de outros dados adjacentes, causando inconsistências nos dados após a codificação e decodificação.

É importante notar que o Solidity, ao realizar chamadas externas e emitir eventos, codifica implicitamente os parâmetros usando abi.encode. Portanto, a probabilidade de ocorrer o código de vulnerabilidade mencionado é maior do que a intuição sugere.

![Análise de vulnerabilidades do compilador Solidity e medidas de resposta][0]https://img-cdn.gateio.im/webp-social/moments-c97428f89ed62d5ad8551cdb2ba30867.webp(

Sugestões de Segurança

Após a análise do modelo de ameaças de vulnerabilidades do compilador Solidity e a revisão de vulnerabilidades históricas, apresentamos as seguintes recomendações para desenvolvedores e profissionais de segurança.

) Para os desenvolvedores:

  1. Utilize uma versão mais recente do compilador Solidity. Embora versões novas possam também introduzir novos problemas de segurança, os problemas de segurança conhecidos são geralmente menores do que nas versões mais antigas.

  2. Melhorar os casos de teste unitário. A maioria dos bugs a nível de compilador resulta em discrepâncias entre os resultados de execução do código e as expectativas. Este tipo de problema é difícil de detectar através de revisões de código, mas pode facilmente ser exposto na fase de testes. Portanto, ao aumentar a cobertura de código, é possível evitar ao máximo este tipo de problemas.

  3. Evite ao máximo o uso de assembly inline, codificação e decodificação ABI para arrays multidimensionais e estruturas complexas, e evite buscar habilidades técnicas desnecessárias ao usar novos recursos de linguagem e funcionalidades experimentais, a menos que haja uma necessidade clara. De acordo com a análise de vulnerabilidades históricas, a maior parte das falhas está relacionada a operações como assembly inline e codificadores ABI. O compilador é mais propenso a erros ao lidar com características complexas da linguagem. Por outro lado, os desenvolvedores também podem cometer erros ao utilizar novos recursos, resultando em problemas de segurança.

Para os seguranças:

  1. Ao realizar auditoria de segurança em código Solidity, não ignore os riscos de segurança que podem ser introduzidos pelo compilador Solidity. O item de verificação correspondente na Classificação de Fraquezas de Smart Contract ###SWC( é SWC-102: Versão do Compilador Desatualizada.

  2. No processo de desenvolvimento interno do SDL, urge à equipa de desenvolvimento que atualize a versão do compilador Solidity e pode considerar a introdução de uma verificação automática da versão do compilador no processo de CI/CD.

  3. Mas não há necessidade de entrar em pânico excessivo sobre as vulnerabilidades dos compiladores; a maioria das vulnerabilidades dos compiladores é acionada apenas em padrões de código específicos, e não é garantido que contratos compilados com versões vulneráveis do compilador apresentem riscos de segurança. O impacto real na segurança deve ser avaliado com base nas circunstâncias do projeto.

Recursos Úteis

  • Artigos de alerta de segurança publicados regularmente pela equipe Solidity
  • Lista de bugs atualizada regularmente no repositório oficial do Solidity
  • Lista de bugs do compilador de várias versões. Pode-se utilizar isto para introduzir uma verificação automática da versão do compilador no processo CI/CD, alertando sobre vulnerabilidades de segurança existentes na versão atual. Code pode indicar vulnerabilidades de segurança na versão atual do compilador.

![Análise de vulnerabilidades do compilador Solidity e medidas de resposta])https://img-cdn.gateio.im/webp-social/moments-84f5083d8748f2aab71fd92671d999a7.webp(

Resumo

Este artigo parte dos conceitos básicos do compilador para apresentar as vulnerabilidades do compilador Solidity e analisar os riscos de segurança que podem surgir em ambientes de desenvolvimento Ethereum reais. Por fim, oferece várias recomendações práticas de segurança para desenvolvedores e profissionais de segurança. Ao entender essas vulnerabilidades e adotar medidas preventivas adequadas, podemos proteger melhor a segurança dos contratos inteligentes e reduzir o risco potencial de perda de ativos.

ETH1.95%
Ver original
Esta página pode conter conteúdos de terceiros, que são fornecidos apenas para fins informativos (sem representações/garantias) e não devem ser considerados como uma aprovação dos seus pontos de vista pela Gate, nem como aconselhamento financeiro ou profissional. Consulte a Declaração de exoneração de responsabilidade para obter mais informações.
  • Recompensa
  • 6
  • Partilhar
Comentar
0/400
0xLuckboxvip
· 9h atrás
Buracos lógicos e tal realmente machucam a cabeça. Fui, fui.
Ver originalResponder0
LidoStakeAddictvip
· 23h atrás
Transbordou, o código ainda precisa ser ajustado.
Ver originalResponder0
StablecoinArbitrageurvip
· 07-30 09:26
*ajusta os óculos* hmm... estatisticamente falando, os riscos de compilador estão severamente subavaliados nos cálculos de tvl em defi
Ver originalResponder0
BoredStakervip
· 07-30 09:24
Quando é que se pode falar de forma compreensível!
Ver originalResponder0
ArbitrageBotvip
· 07-30 09:24
Mais uma vez a ter que lidar com as armadilhas do compilador?
Ver originalResponder0
APY追逐者vip
· 07-30 09:15
Só me lembrei da vulnerabilidade do compilador quando estava a pagar o gás da caça ao louco.
Ver originalResponder0
Negocie cripto em qualquer lugar e a qualquer hora
qrCode
Digitalizar para transferir a aplicação Gate
Novidades
Português (Portugal)
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)