Pourquoi tout ce flou sur le fuzzing des compilateurs ?
Les compilateurs traduisent le code lisible par l'homme en code machine, et toute erreur dans ce processus peut entraîner des bugs logiciels ou des vulnérabilités de sécurité. Une façon efficace de tester les compilateurs est d'utiliser le fuzzing, une méthode qui consiste à fournir des données aléatoires apparemment valides en entrée pour détecter des problèmes inattendus.
Le fuzzing pour les compilateurs de blockchain : un territoire inexploré
L’exploration des fuzzers dans le domaine des compilateurs de blockchain est encore une nouvelle frontière. À mesure que les machines virtuelles (VM) deviennent plus complexes et que des technologies telles que les VM WASM émergent, l’application de techniques de test avancées aux compilateurs devient de plus en plus importante. Ces mesures proactives sont indispensables dans les écosystèmes où la correction de codes défectueux ou nuisibles est à la fois coûteuse et difficile.
Étude de cas : Le compilateur Clarity
Le compilateur Clarity traite le langage de contrat intelligent Clarity, en traduisant son arbre de syntaxe abstraite (AST) directement en WebAssembly (WebASM), en contournant les passes d'optimisation pour une traduction simple. Pour plus de détails sur les spécificités du langage Clarity, reportez-vous à la documentation Clarity.
Augmenter l'efficacité du Fuzzer
Zest se distingue par l'adoption d'un fuzzing sensible à la structure, essentiel pour générer des entrées hautement structurées – les programmes dans ce contexte. En se concentrant au-delà des erreurs d'analyse, Zest garantit que les entrées sont syntaxiquement valides, avec une forte probabilité de validité sémantique. En exploitant le fuzzing guidé par la couverture, il conserve les entrées qui dévoilent de nouveaux modèles de couverture, formant un corpus pour les mutations ultérieures. Le retour d'informations sur la validité sémantique est intégré, améliorant le discernement de Zest dans l'évaluation des résultats. En utilisant libfuzzer pour la génération de flux d'octets, Zest utilise un générateur Clarity pour convertir de manière déterministe ces flux en programmes Clarity syntaxiquement et sémantiquement valides, en filtrant les erreurs prévisibles comme les incompatibilités de type.
Notre solution : informations architecturales et rapports de couverture
Vue schématique de notre stratégie de fuzzing basée sur la mutation.
Nous avons conçu un générateur de code Clarity qui accepte une chaîne d'octets aléatoire et génère des programmes Clarity valides. Bien que son itération initiale comporte un ensemble limité d'opcodes et de fonctionnalités de langage, il s'est avéré efficace pour découvrir des découvertes notables. En utilisant l'implémentation de LibFuzzer par Rust, nous avons géré la génération de chaînes d'octets, la gestion du corpus et la récupération des informations de couverture. Après l'exécution, nous avons méticuleusement analysé la sortie du compilateur, en filtrant les résultats triviaux et en utilisant une vérification de l'analyseur WASM pour garantir la validité du WASM généré dans les cas de compilation réussie.
Constats et perspectives
- Le compilateur vous permet de nommer les variables/fonctions avec des noms de type. Cela signifie qu'à partir de là dans le contrat, le nom du type est remplacé par le nom de la variable/fonction. Il peut y avoir des vecteurs d'attaque qui pourraient exploiter cela
- Le compilateur ne semble pas limiter le nombre de variables locales générées par le WASM résultant. Il semble que les lignes inutiles des littéraux (par exemple, la déclaration d'un entier nu qui n'est pas du tout utilisé et qui est fonctionnellement équivalent à un nop) génèrent des variables locales dans le WASM. Cela est particulièrement insidieux avec les listes. Ainsi, un programme « gonflé » peut se compiler sans problème, mais lors de sa validation avec un analyseur WASM, il avertit que l'utilisation des variables locales est dépassée
Perspectives d'avenir : améliorations et futurs fuzzers
Notre voyage ne s'arrête pas là. Nous envisageons d'étendre les capacités du compilateur Clarity, d'explorer des stratégies de fuzzing supplémentaires et d'approfondir les nuances de Stacks. Alors que nous continuons à démêler les complexités des compilateurs de blockchain, nous invitons la communauté à nous rejoindre dans cette entreprise pionnière. Ensemble, nous pouvons améliorer la robustesse et la fiabilité des technologies de blockchain, ouvrant la voie à un avenir plus sûr.
