Revisão de Segurança Nym
Auditoria de segurança dos componentes principais da Nym
Introdução
Em julho de 2021, a Nym passou por uma auditoria de segurança realizada por Jean-Philippe Aumasson, um renomado especialista em segurança. O objetivo era identificar possíveis vulnerabilidades e defeitos no código da Nym, com foco em criptografia, segurança do código e segurança de protocolo. A revisão visava garantir a integridade e robustez do sistema, cobrindo aspectos-chave de sua arquitetura e implementação. Você pode ver o relatório completo da auditoria aqui.
Resumo da Auditoria
A auditoria ocorreu no verão de 2021. O escopo da auditoria cobriu múltiplos repositórios do projeto Nym, incluindo:
- Repositório Principal da Nym: nymtech/nym, que implementa os serviços de mixnode, gateway e validador.
- Formato de Pacote Sphinx Mixnet: nymtech/sphinx, utilizado pelos mixnodes.
- Protocolo de Assinatura Cega Threshold Coconut: nymtech/coconut, usado para emissão de credenciais.
A auditoria envolveu a revisão da versão mais recente do código na branch develop, que era atualizada regularmente devido à rápida evolução do projeto. A equipe da Nym forneceu ao JP Aumasson acesso completo ao código-fonte, especificações detalhadas do projeto, artigos de pesquisa e documentação de suporte.
Principais Áreas de Foco da Auditoria
A auditoria focou em três áreas principais: segurança do código, criptografia e design de protocolo. Os auditores examinaram minuciosamente o código da Nym para identificar vulnerabilidades, buscando problemas comuns como padrões de codificação inseguros e erros mal tratados. Atenção especial foi dada à segurança de memória e à prevenção de armadilhas como estouro de inteiros.
A revisão criptográfica cobriu uma ampla gama de primitivos centrais utilizados pela Nym, como AES-128-CTR, BLAKE2b, ChaCha, Ed25519 e outros. O objetivo era garantir a implementação correta desses algoritmos e verificar sua resistência a ataques de canal lateral, uso incorreto de parâmetros e falhas na geração de aleatoriedade.
Além de revisar os componentes individuais, a auditoria também analisou os protocolos que definem a funcionalidade central da Nym. Isso envolveu examinar o formato de pacote Sphinx e o protocolo de assinatura cega threshold Coconut para identificar quaisquer fraquezas que pudessem comprometer a privacidade ou a segurança. A revisão focou em possíveis vazamentos de informações que ameaçam o anonimato do usuário, bem como vulnerabilidades como desvios de verificação MAC, ataques de subgrupo pequeno e falhas em operações criptográficas como aritmética BLS12-381 e provas de conhecimento zero.
Visão Geral das Descobertas
Nove vulnerabilidades de segurança foram descobertas durante a auditoria. Nenhuma foi classificada como crítica, duas como alta, uma como média e seis como baixa. Adicionalmente, 17 observações foram feitas, oferecendo recomendações para fortalecer ainda mais a rede Nym. A seguir, apresentamos uma visão geral das correções implementadas para tratar todas as vulnerabilidades de segurança identificadas.
S-SPHX-01: Validações de chaves ausentes (Baixo)
O problema identificado em nymtech/sphinx referente à validação insuficiente de chaves privadas e públicas foi tratado pela migração para a biblioteca x25519, que aplica inerentemente a validade das chaves por meio de seu design. A implementação do x25519 garante que as chaves privadas sejam corretamente restringidas (clamped), ou seja, automaticamente limitadas a um subconjunto válido de escalares, eliminando o risco de uso de chaves privadas inválidas. Além disso, embora o x25519 não valide explicitamente as chaves públicas, sua implementação de escada de Montgomery previne inerentemente que certos pontos de curva inválidos sejam utilizados. Isso mitiga o risco de encontrar pontos no infinito ou outras chaves públicas malformadas. Além disso, o processo de troca de chaves garante que um segredo compartilhado totalmente zero possa ser detectado e rejeitado quando necessário. Ao utilizar o x25519, melhoramos significativamente a validação de chaves, reduzindo o risco de chaves inválidas ou mal formatadas serem usadas no sistema. Isso resolve efetivamente as preocupações levantadas na auditoria sobre validação de chaves.
S-COCO-01: Distribuição enviesada no hash-to-scalar (Baixo)
O processo de hash para derivar um escalar no campo BLS12-381 envolvia anteriormente o mapeamento direto da saída de uma função hash para um elemento do campo escalar. No entanto, essa abordagem introduzia viés devido à operação de redução modular (mod p), que pode resultar em uma distribuição não uniforme quando a saída do hash não se alinha perfeitamente com o módulo primo do campo. Para tratar esse problema, substituímos a função hash-to-scalar existente pela função hash_to_field do crate bls12_381. Essa função segue a especificação padronizada de hash-to-field, garantindo um mapeamento uniforme e sem viés das saídas de hash para elementos do campo. Adicionalmente, o protocolo zk-Nym, que substituiu o protocolo Coconut, também utiliza essa função para suas operações de hash, garantindo consistência e correção nos cálculos criptográficos.
S-COCO-02: Permissões de arquivos de chave do keygen-cli (Baixo)
Os auditores observaram que os arquivos de chave do keygen-cli possuem permissões padrão, mas deveriam ter permissões mais restritivas para maior segurança. Esse problema não exigiu nenhuma alteração, pois o keygen-cli foi usado apenas nas fases iniciais de nossa implementação do Coconut. Ele não faz mais parte do repositório principal da Nym e não está em uso ativo. Como a ferramenta se tornou obsoleta, nenhuma ação adicional foi necessária quanto às suas permissões de arquivo.
S-CRYP-01: Possível reutilização de IV em cifra de fluxo (Alto)
O problema envolve uma função que criptografa dados usando um vetor de inicialização (IV). Se nenhum IV for fornecido, a função usa por padrão um IV zero, o que poderia resultar em reutilização de IV. Esse problema foi resolvido com a introdução do protocolo AES-GCM-SIV durante a fase de registro. Para evitar ataques de downgrade, removemos a opção de usar a chave AES-128-CTR legada para comunicação entre o cliente e o gateway. Desde que tanto o cliente quanto o gateway estejam atualizados, eles sempre gerarão um IV aleatório e não nulo.
S-PROT-01: Possível gasto duplo de credenciais (Alto)
Os auditores observaram que a versão revisada do Coconut não possuía um mecanismo de detecção de gasto duplo, o que poderia ter permitido que múltiplos gateways validassem incorretamente uma credencial como não utilizada ao mesmo tempo. No entanto, o contrato de largura de banda do Coconut foi posteriormente atualizado para rastrear o uso de credenciais armazenando o estado na blockchain, resolvendo esse problema. Adicionalmente, o Coconut foi substituído pelo protocolo zk-nyms, que inclui funcionalidade de detecção de gasto duplo integrada.
S-NYM-01: Dependências com vulnerabilidades conhecidas (Médio)
Os auditores identificaram que vários componentes do projeto Nym dependiam de versões mais antigas de dependências com vulnerabilidades de segurança conhecidas. Por exemplo, o repositório Sphinx usava uma versão insegura do crate generic-array, o repositório principal da Nym dependia de um tokio desatualizado, e o cliente Nym tinha vários crates com problemas de segurança conhecidos, alguns dos quais pareciam ser exploráveis no contexto da Nym. Seguindo a recomendação dos auditores, atualizamos regularmente as dependências. Agora gerenciamos ativamente nossas dependências através do Dependabot, que monitora continuamente e detecta automaticamente pacotes desatualizados ou vulneráveis em nossos repositórios. Veja as correções do Dependabot aplicadas continuamente em nosso repositório.
S-NYM-02: Falha de descriptografia não tratada (Baixo)
O problema identificado no código ocorre na função recover_identifier em nym/common/nymsphinx/acknowledgments/identifier.rs, onde falhas de descriptografia, como parâmetros inválidos, não são tratadas corretamente. Isso pode levar a panic ou outros estados inseguros. Um problema semelhante existe na função recover_plaintext em nym/common/nymsphinx/src/receiver.rs. A falha em gerenciar erros de descriptografia pode potencialmente resultar no sistema entrando em um estado instável ou inseguro. Após revisar cuidadosamente as funções, concluímos que o primeiro exemplo fornecido, em recover_identifier, não é um problema real. É impossível fornecer parâmetros incorretos, pois tudo é parametrizado com AckEncryptionAlgorithm (link), o que significa que quaisquer valores inválidos seriam detectados em tempo de compilação.
O segundo caso mencionado, recover_plaintext, não existe mais. No entanto, o código que o substituiu, recover_plaintext_from_regular_packet, tinha um caso de falha teoricamente possível se modificássemos alguns parâmetros para valores incomuns. Tratamos isso adicionando um tratamento de erros adequado para garantir que o sistema permaneça estável, mesmo em casos extremos.
S-NYM-03: Panic na geração de IDs de fragmento (Baixo)
O código usado para gerar novos IDs de fragmento seleciona aleatoriamente um valor i32 e calcula seu valor absoluto. No entanto, essa abordagem pode levar a panic nos casos em que o valor escolhido aleatoriamente é i32::MIN, pois seu valor absoluto não pode ser representado dentro dos limites de um i32. Isso resulta em um erro de "tentativa de negar com estouro" devido às limitações da codificação em complemento de 2.
Concordamos que a classificação de severidade foi definida muito baixa para esse problema, pois a probabilidade de encontrar esse caso é de aproximadamente 1 em 4 bilhões. No entanto, tratamos o problema implementando a correção recomendada pelo auditor para prevenir possíveis panics e travamentos inesperados, especialmente quando milhões de usuários geram milhares de IDs de fragmento.
S-NYM-04: Mnemônico não zerado (Baixo)
O problema identificado destacou que o mnemônico BIP39 usado para conectar o serviço nymd não estava sendo zerado após o uso, resultando em múltiplas cópias do mnemônico persistindo na memória. Isso aumentava o risco de exposição, pois mnemônicos são mais facilmente identificáveis na memória em comparação com chaves criptográficas brutas. Para tratar isso, implementamos várias mitigações. Nos componentes Rust, integramos o crate zeroize para garantir que qualquer memória contendo o mnemônico seja apagada com segurança assim que sair do escopo. Como JavaScript é uma linguagem com coleta de lixo e não fornece controle direto sobre o descarte de memória, adotamos uma abordagem diferente para mitigar a exposição no runtime JavaScript. Especificamente, modificamos o sistema para que o runtime JavaScript seja encerrado assim que o mnemônico for transferido para a camada Rust. Isso garante que todas as instâncias do mnemônico na memória JavaScript sejam limpas ao encerrar o runtime. O mnemônico é transferido para Rust o mais cedo possível, reduzindo sua exposição em JavaScript. Uma vez no Rust, o zeroize garante que todas as instâncias do mnemônico sejam apagadas com segurança quando não forem mais necessárias. Com essas mudanças, minimizamos significativamente a presença do mnemônico na memória, reduzindo o risco de exposição e garantindo que os dados sensíveis sejam gerenciados e apagados com segurança.
Palavras finais
Gostaríamos de agradecer ao JP Aumasson pela sua expertise e dedicação durante todo o processo de auditoria. Também apreciamos a colaboração e o profissionalismo demonstrados durante as etapas de planejamento e execução da auditoria. Nosso compromisso contínuo com a segurança permanece uma prioridade máxima, e aguardamos a continuidade das parcerias com especialistas em segurança para manter os mais altos padrões para o nosso ecossistema.