Back to Blog

Como um Bug Crítico na Rede Solana Foi Detectado e Corrigido a Tempo

Code Auditing
7 de junho de 2022
6 min read

Em abril, nosso sistema de detecção de vulnerabilidades descobriu um problema no rBPF da Solana (ou seja, a máquina virtual onde todos os dApps da Solana são executados: https://github.com/solana-labs/rbpf). Após uma investigação cuidadosa, descobrimos que se trata de uma vulnerabilidade de segurança que pode levar a um caminho de execução incorreto de um contrato. Relatamos o bug à equipe de segurança da Solana, e a equipe imediatamente confirmou e corrigiu a vulnerabilidade. Além disso, eles concederam à nossa equipe uma recompensa no valor de $800.000 USD em tokens SOL.

A vulnerabilidade existe em versões mais recentes do rBPF (0.2.26 a 0.2.27). Quando relatamos o problema, os validadores usados na mainnet ainda não haviam sido atualizados para a(s) versão(ões) afetada(s). Nosso sistema detectou o problema antes que a versão afetada fosse incorporada, tornando o validador da mainnet imune a essa vulnerabilidade.

Detalhamos o problema desta vulnerabilidade a seguir.

1. eBPF e rBPF

eBPF (Extended Berkeley Packet Filter) foi inicialmente desenvolvido para filtrar pacotes no kernel. Devido à segurança, eficiência e escalabilidade do eBPF, ele é agora utilizado em diversas áreas como redes, rastreamento, perfilamento, etc. Considerando a rica capacidade do eBPF, a Solana o utiliza como mecanismo de execução para contratos inteligentes. Para construir dApps na Solana, os desenvolvedores desenvolvem seus contratos inteligentes em Rust e compilam o contrato em bytecode eBPF.

A Solana usa o rBPF, uma máquina virtual escrita em Rust, para executar o bytecode BPF compilado. No entanto, se a máquina virtual proposta (ou seja, rBPF) é robusta, segura e precisa, ainda é uma questão em aberto. Se existirem problemas de segurança dentro do rBPF, todos os validadores que contêm o rBPF podem ser afetados, resultando em grandes perdas (por exemplo, Perda de Fundos) para toda a rede Solana.

2. Causa Raiz

Desenvolvemos uma ferramenta que pode localizar automaticamente bugs de implementação do rBPF e escanear o código do rBPF periodicamente. Um problema grave foi identificado no rBPF (versão 0.2.26) durante o processo de escaneamento, que pode levar ao caminho de execução incorreto de um contrato.

Especificamente, a instrução sdiv é usada como instrução de divisão com sinal, introduzida como uma funcionalidade habilitada por padrão no rbpf 0.2.26. sdiv suporta divisão para operandos em 32 bits (ou seja, sdiv32) e 64 bits (sdiv64). Para a instrução sdiv32, o resultado do cálculo é armazenado no registrador bpf, que é de 64 bits. No entanto, se as instruções após a instrução sdiv32 lerem o resultado do cálculo como 64 bits, o resultado pode ser diferente. Isso ocorre porque o rBPF não estende o resultado do cálculo do sdiv32 para o valor correto em 64 bits durante a compilação JIT.

Por exemplo, se um número positivo (ou seja, 12) é dividido por um número negativo (ou seja, -4) com sdiv32, o resultado correto deveria ser -3 tanto em 32 bits quanto em 64 bits. O código abaixo é um exemplo.

Após executar e rastrear nos modos JIT e Interpretado, pudemos observar as diferenças entre eles:

2.1 Modo Interpretado

0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    29: lddw r5, 0x10000000c
 1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    31: sdiv32 r5, -4
 2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    32: jslt r5, 0, lbb_7
 3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    36: exit

2.2 Modo JIT

0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    29: lddw r5, 0x10000000c
 1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    31: sdiv32 r5, -4
 2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    32: jslt r5, 0, lbb_7
 3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    33: lddw r0, 0x1
 4 [0000000000000001, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    35: exit

No modo Interpretado, o registrador r5 é definido como 0xFFFFFFFFFFFFFFFD (-3 tanto no modo de 32 bits quanto no de 64 bits), enquanto no modo JIT, r5 é definido como 0x00000000FFFFFFFD. Neste caso, r5 será reconhecido como um número positivo (ou seja, 0x00000000FFFFFFFD) para a instrução jslt, que recebe um valor de 64 bits. Após isso, o caminho de execução estará completamente errado.

3. Impacto

Essa implementação incorreta pode levar ao caminho de execução incorreto de um contrato e pode causar problemas sérios.

Por exemplo, se uma operação essencial em um contrato inteligente depende do resultado da instrução sdiv32, isso pode levar a resultados de execução incorretos e ser explorado por atacantes.

Este problema foi introduzido em https://github.com/solana-labs/rbpf/pull/283, o que significa que o rBPF é vulnerável a partir da versão 0.2.26. Identificamos o problema e o relatamos à equipe de segurança da Solana em 28 de abril de 2022. A equipe respondeu rapidamente ao nosso relatório e corrigiu o problema em poucas horas adicionando a operação de extensão de sinal para a instrução sdiv32. A correção está em https://github.com/solana-labs/rbpf/pull/310. Devido à detecção e ao relatório oportuno da nossa equipe, os validadores da mainnet não foram afetados por esta vulnerabilidade.

Este problema é classificado como um bug de vivacidade de protocolo, resultando em uma recompensa de $800.000 concedida pela Solana.

Linha do Tempo

  • 2022/04/28: Relatamos o problema à equipe de segurança da Solana
  • 2022/04/29: A vulnerabilidade foi corrigida
  • 2022/05/09: CVE-2022-23066 foi atribuído
  • 2022/06/01: A recompensa por bug foi concedida

Sobre a BlockSec

A Equipe BlockSec se concentra na segurança do ecossistema blockchain e colabora com os principais projetos DeFi para proteger seus produtos. A equipe é fundada por pesquisadores de segurança de alto nível e especialistas experientes tanto da academia quanto da indústria. Eles publicaram vários artigos sobre segurança em blockchain em conferências de prestígio, relataram vários ataques zero-day em aplicações DeFi e lançaram relatórios detalhados de análise de incidentes de segurança de alto impacto.

Twitter: [BlockSecTeam]

Medium: https://blocksecteam.medium.com

Website: https://www.blocksec.com

Sign up for the latest updates
Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec
Security Insights

Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec

Este relatório semanal aborda dois incidentes de segurança na Ethereum e na BNB Chain no período de 19/10/2026–25/10/2026. Ele examina uma tomada de controle da governança do X100 Freezer financiada por um empréstimo-relâmpago e uma falha na liquidação de impostos que afetou um pool de liquidez de um token NEM na BNB Chain. As perdas estimadas no escopo do relatório totalizam aproximadamente 5,57 milhões USD: cerca de 4,75 milhões USD da transação representativa do X100 e cerca de 820 mil USD do incidente no pool do NEM. O total exclui as extrações subsequentes do X100 relatadas separadamente.

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec
Security Insights

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec

Este relatório semanal aborda 3 incidentes de segurança no período de 12/10/2026–18/10/2026, com perdas totais estimadas em aproximadamente 3,87 milhões USD. A Autheo Network sofreu um comprometimento de chave privada com perdas de cerca de 1,76 milhões USD, a Qubic Wallet perdeu cerca de 1,30 milhões USD devido à geração de seeds fracas, e os contratos Smart Token Vesting V2 da UNCX Network sofreram um erro contábil de cerca de 807 mil USD nas redes Ethereum, BNB Chain, Base e Robinhood Chain. A análise em destaque da UNCX explica como um cálculo incorreto do total de cotas misturou parcelas de vesting criadas com diferentes proporções entre tokens e cotas, permitindo saques acima do devido de pools compartilhados.

~US$ 542 mil perdidos: ataque ao MakerDaoBot | Boletim semanal da BlockSec
Security Insights

~US$ 542 mil perdidos: ataque ao MakerDaoBot | Boletim semanal da BlockSec

O relatório cobre 1 incidente no Ethereum (05–11/10/2026), com perda estimada de US$ 542 mil. Um adaptador malicioso obteve acesso aos saldos MakerDAO via função desprotegida do MakerDaoBot, liquidou 4 leilões ETH-A e converteu 200 ETH-A em WETH, depois enviados como ETH ao atacante.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit