Revue de sécurité Nym
Audit de sécurité des composants principaux de Nym
Introduction
En juillet 2021, Nym a fait l'objet d'un audit de sécurité par [Jean-Philippe Aumasson] (https://www.aumasson.jp/), un expert en sécurité renommé. L'audit visait à identifier les vulnérabilités potentielles et les défauts dans la base de code de Nym, en se concentrant sur la cryptographie, la sécurité du code et la sécurité des protocoles. L’examen visait à assurer l’intégrité et la robustesse du système, couvrant les aspects clés de son architecture et de sa mise en œuvre. Vous pouvez voir le rapport d'audit complet ici.
Résumé de l'audit
L'audit a eu lieu à l'été 2021. La portée de l'audit couvrait plusieurs dépôts du projet Nym, y compris :
- Le dépôt principal de Nym : nymtech/nym, qui implémente les services de mixnode, de passerelle et de validateur.
- Format de paquets Sphinx Mixnet : nymtech/sphinx, utilisé par les mixnodes.
- Protocole de signature aveugle à seuil de coco : nymtech/coconut, utilisé pour la délivrance de vos identifiants.
L'audit a consisté à examiner la dernière version du code dans la branche développement, qui a été régulièrement actualisée en raison de l'évolution rapide du projet. L’équipe Nym a fourni à JP Aumasson un accès complet à la base de code, aux spécifications détaillées du projet, aux documents de recherche et à la documentation d’appui.
Zones de focalisation clés de l'audit
L'audit s'est concentré sur trois domaines principaux : la sécurité du code, la cryptographie et la conception du protocole. Les auditeurs ont examiné minutieusement la base de code de Nym pour identifier les vulnérabilités, à la recherche de problèmes communs tels que les modèles de codage dangereux et les erreurs mal gérées. Une attention particulière a été accordée à la sécurité de la mémoire et d'éviter les embûches comme les débordements d'entiers.
La revue cryptographique couvrait une large gamme de [primitives de base employées par Nym] (https://nym.com/trust-center/cryptography), telles que AES-128-CTR, BLAKE2b, ChaCha, Ed25519 et d'autres. Le but était d'assurer la bonne mise en œuvre de ces algorithmes et de vérifier leur résistance aux attaques de canal latéral, à l'utilisation abusive de paramètres, et aux défauts de la génération aléatoire.
En plus de revoir les composants individuels, l'audit a également examiné les protocoles qui définissent la fonctionnalité principale de Nym. Cela a consisté à examiner le [format de paquet Sphinx] (https://nym.com/blog/sphinx-the-anonymous-data-format-behind-lightning-and-nym) et le [protocole de signature aveugle du seuil de cocout] (https://nym.com/blog/nym-credentials-a-decentralized-private-alternative-to-the-faceopticon) pour identifier les faiblesses qui pourraient compromettre la vie privée ou la sécurité. L'examen s'est concentré sur les fuites d'informations potentielles menaçant l'anonymat des utilisateurs, ainsi que sur les vulnérabilités telles que les contournements de la vérification MAC, de petites attaques de sous-groupe, et des défauts dans les opérations cryptographiques telles que l'arithmétique BLS12-381 et les zero-knowledge proofs.
Vue d'ensemble des constatations
Neuf vulnérabilités de sécurité ont été découvertes durant l'audit. Aucune n'a été jugée aussi critique, deux aussi élevée, une comme moyenne et six comme inférieure. En outre, 17 observations ont été faites, proposant des recommandations pour le renforcement du réseau Nym. Ci-dessous, nous fournissons une vue d'ensemble des correctifs mis en œuvre pour répondre à toutes les vulnérabilités de sécurité identifiées.
S-SPHX-01 : Validations de clés manquantes (Faible)
Le problème identifié dans nymtech/sphinx concernant la validation insuffisante des clés privées et publiques a été résolu par migration vers la bibliothèque x25519, qui applique intrinsèquement la validité des clés par sa conception. L'implémentation de x25519 garantit que les clés privées sont correctement contraintes, ce qui signifie qu'elles sont automatiquement limitées à un sous-ensemble valide de scalaires, éliminant ainsi le risque d'utilisation de clés privées invalides. De plus, bien que x25519 ne valide pas explicitement les clés publiques, son implémentation de l'échelle de Montgomery empêche intrinsèquement l'utilisation de certains points de courbe invalides. Cela atténue le risque de rencontrer des points à l'infini ou d'autres clés publiques mal formées. En outre, le processus d'échange de clés garantit qu'un secret partagé zéro peut être détecté et rejeté si nécessaire. En utilisant x25519, nous avons considérablement amélioré la validation des clés, réduisant le risque que des clés non valides ou mal formatées soient utilisées dans le système. Cela résout efficacement les préoccupations soulevées dans le cadre de la vérification concernant la validation clé.
S-COCO-01 : Distribution biaisée du hash-to-scalar (Faible)
Le processus de hachage pour dériver un scalaire dans le champ BLS12-381 impliquait précédemment de mapper la sortie d'une fonction de hachage directement à un élément de champ scalaire. Cependant, cette approche a introduit un biais en raison de l'opération de réduction modulaire (mod p), qui peut donner lieu à une distribution non uniforme lorsque la sortie du hachage ne s'aligne pas parfaitement avec le module principal du champ. Pour résoudre ce problème, nous avons remplacé la fonction hash-to-scalar existante par la hash_to_field de la fonction bls12_381 crate. Cette fonction suit la [spécification standardisée de hachage à champ] (https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#name-hashing-to-a-finite-field), assurant une correspondance uniforme et impartiale des sorties de hachage aux éléments du champ. De plus, le protocole zk-Nym, qui a remplacé le protocole Coconut, repose également sur cette fonction pour ses opérations de hachage, assurant la cohérence et la justesse des calculs cryptographiques.
S-COCO-02: Autorisations des fichiers de clés keygen-cli (Low)
Les auditeurs ont noté que les fichiers clés keygen-cli ont des permissions par défaut, mais ils devraient avoir des permissions plus restreintes pour une meilleure sécurité. Ce problème ne nécessitait aucun changement, puisque keygen-cli n'était utilisé que dans les premières étapes de notre implémentation Coconut. Il ne fait plus partie du dépôt principal de Nym et n'est pas en cours d'utilisation. Depuis que l'outil est devenu obsolète, aucune action supplémentaire n'était nécessaire concernant ses permissions de fichiers.
S-CRYP-01 : Réutilisation potentielle du procédé de chiffrement IV (High)
Le problème implique une fonction qui chiffre les données en utilisant un vecteur d'initialisation (IV). Si aucun IV n'est fourni, la fonction par défaut utilise un zéro IV, ce qui peut entraîner une réutilisation de l'IV. Ce problème a été résolu en introduisant le protocole AES-GCM-SIV pendant la phase d'inscription. Pour prévenir les attaques de rétrogradation, nous avons removed l'option d'utiliser la clé ancienne AES-128-CTR pour la communication entre le client et la passerelle. Tant que le client et la passerelle sont mis à jour, ils génèreront toujours une IV, aléatoire et non nulle.
S-PROT-01 : Double dépense potentielle des titres de compétences (High)
Les auditeurs ont remarqué que la version révisée de Coconut manquait d'un mécanisme de détection des doubles dépenses, qui auraient pu permettre à plusieurs passerelles de valider incorrectement un mot de passe comme non utilisé en même temps. Cependant, le contrat de bande passante de Coconut a été mis à jour par la suite pour suivre l'utilisation des informations d'identification en stockant l'état sur la chaîne et résoudre ce problème. De plus, Coconut a depuis été remplacé par le [protocole zk-nym] (https://nym.com/blog/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet), qui inclut une [fonctionnalité de détection des dépenses doubles] intégrée (https://arxiv.org/abs/2303.08221).
S-NYM-01 : Dépendances avec vulnérabilités connues (Moyen)
Les auditeurs ont identifié que plusieurs composants du projet Nym se basaient sur des versions plus anciennes de dépendances avec des vulnérabilités de sécurité connues. Par exemple, le dépôt Sphinx a utilisé une version non sécurisée de la caisse generic-array, le dépôt central de Nym s'est appuyé sur un tokio obsolète, et le client Nym avait plusieurs caisses avec des problèmes de sécurité connus, dont certaines semblaient être exploitables dans le contexte de Nym. À la suite de la recommandation des auditeurs, nous avons régulièrement mis à jour les dépendances. Nous gérons maintenant activement nos dépendances grâce à Dependabot, qui surveille et détecte en permanence et automatiquement les paquets obsolètes ou vulnérables dans nos dépôts. Voir les [correctifs Dependabot appliqués en continu] (https://github.com/nymtech/nym-vpn-client/pulls?q=is%3Apr+label%3Adependencies+is%3Aclosed) dans notre dépôt.
S-NYM-02 : Échec du déchiffrement non géré (Low)
Le problème identifié dans le code se produit dans la fonction recover_identifier dans nym/common/nymsphinx/acknowledgments/identifier.rs, où les échecs de déchiffrement, tels que les paramètres invalides, ne sont pas gérés correctement. Cela peut conduire à la panique ou à d'autres états précaires. Un problème similaire existe dans la fonction recover_plaintext dans nym/common/nymsphinx/src/receiver.rs. L'échec de la gestion des erreurs de décryptage peut potentiellement entraîner l'entrée du système dans un état instable ou non sécurisé. Après avoir examiné soigneusement les fonctions, nous avons conclu que le premier exemple fourni, dans recover_identifier, est un non-problème. Il est impossible de fournir des paramètres incorrects, car tout est paramétré avec AckEncryptionAlgorithm (link), signifie que toutes les valeurs non valides seraient prises au moment de la compilation.
Le deuxième cas mentionné, recover_plaintext, n'existe plus. Cependant, le code qui l'a remplacé, recover_plaintext_from_regular_packet, avait un cas d'échec théoriquement possible si nous devions modifier certains paramètres à des valeurs inhabituelles. Nous avons résolu ce problème en ajoutant une [gestion des erreurs] appropriée (https://github.com/nymtech/nym/blob/50b044a100ca1fa4b4cd8ddc37b63d9bfbf140ac/common/nymsphinx/src/receiver.rs#L101) pour nous assurer que le système reste stable, même dans les cas les plus reculés.
S-NYM-03 : Génération de Panique en ID de fragment (Low)
Le code utilisé pour générer de nouveaux identifiants de fragment sélectionne aléatoirement une valeur i32 et prend sa valeur absolue. Cependant, cette approche peut conduire à la panique dans les cas où la valeur choisie aléatoirement est i32::MIN, comme sa valeur absolue ne peut pas être représentée dans les limites d'un i32. Il en résulte une erreur 'tentative d'annuler avec un débordement' en raison des limitations de l'encodage à 2 compléments.
Nous sommes d'accord pour que le niveau de gravité soit trop bas pour ce problème, car la probabilité de rencontrer ce cas est d'environ 1 milliard sur 4 milliards. Cependant, nous avons résolu le problème en[ l'implémentation de la correction recommandée par l'auditeur ] (https://github.com/nymtech/nym/blob/50b044a100ca1fa4b4cd8ddc37b63d9bfbf140ac/common/nymsphinx/chunking/src/set.rs#L78) pour éviter les paniques potentielles et les plantages inattendus, surtout lorsque des millions d'utilisateurs génèrent des milliers d'ID de fragment.
S-NYM-04 : Mnémonique non zéroisé (Faible)
Le problème identifié a souligné que le BIP39 mnémonique utilisé pour connecter le service nymd n'a pas été dénaturé après utilisation, résultant en plusieurs copies de la persistance mnémonique dans la mémoire. Cela a augmenté le risque d'exposition, car les mnémoniques sont plus faciles à identifier en mémoire que les clés cryptographiques brutes. Pour y remédier, nous avons mis en œuvre plusieurs mesures d’atténuation. Dans les composants de la rouille, nous avons intégré la caisse zeroize pour nous assurer que toute mémoire contenant le mnémonique soit effacée en toute sécurité dès qu'elle est hors portée. Comme JavaScript est un langage collecté par des garbages, il ne fournit pas de contrôle direct sur l'élimination de la mémoire, nous avons adopté une approche différente pour atténuer l'exposition dans la période d'exécution JavaScript. Plus précisément, nous avons modifié le système de sorte que l'exécutable JavaScript se termine une fois que le mnémonique a été passé à la couche Rust . Cela garantit que toutes les instances du mnémonique dans la mémoire JavaScript sont effacées lors de l'arrêt de l'exécution. Le mnémonique est transféré à Rust dès que possible, réduisant ainsi son exposition en JavaScript. Une fois dans Rust, zeroize s'assure que toutes les instances du mnémonique sont correctement effacées une fois qu'elles ne sont plus nécessaires. Avec ces changements, nous avons considérablement minimisé la présence du mnémonique en mémoire, en réduisant le risque d'exposition et en veillant à ce que les données sensibles soient gérées et effacées en toute sécurité.
Derniers mots.
Nous tenons à remercier JP Aumasson pour son expertise et son engagement tout au long de ce processus d'audit. Nous apprécions également la collaboration et le professionnalisme démontrés pendant les phases de planification et d'exécution de l'audit. Notre engagement continu envers la sécurité demeure une priorité absolue, et nous attendons avec impatience de poursuivre nos partenariats avec des experts en sécurité pour maintenir les normes les plus élevées pour notre écosystème.