Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
fuzzilli — Un fuzzer de moteur JavaScript | Kitploit
Outils/GitHubGitHub/googleprojectzero/fuzzilli
Analyse des VulnérabilitésFuzzingAnalyse de BinairesArticles et RechercheApprentissage et Éducation
GitHubgoogleprojectzero/fuzzilli

fuzzilli

Un fuzzer de moteur JavaScript

Voir le dépôt
2.3k3661il y a 7 joursVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Fuzzilli

Un fuzzer guidé par la couverture de code pour les interpréteurs de langages dynamiques basé sur un langage intermédiaire personnalisé ("FuzzIL") qui peut être muté et traduit en JavaScript.

Utilisation

Les étapes de base pour utiliser ce fuzzer sont :

  1. Télécharger le code source de l'un des moteurs JavaScript pris en charge. Voir le répertoire Targets/ pour la liste des moteurs JavaScript supportés.
  2. Appliquer les correctifs correspondants depuis le répertoire de la cible. Consultez également le README.md dans ce répertoire.
  3. Compiler le moteur avec l'instrumentation de couverture (nécessite clang >= 4.0) comme décrit dans le README.
  4. Compiler le fuzzer : swift build [-c release].
  5. Exécuter le fuzzer : swift run [-c release] FuzzilliCli --profile=<profile> [autres options cli] /chemin/vers/jsshell. Voir aussi swift run FuzzilliCli --help.

La construction et l'exécution de Fuzzilli et des moteurs JavaScript pris en charge dans Docker et sur Google Compute Engine sont également supportées.

Développement

Consultez main.swift pour voir un exemple d'utilisation de la bibliothèque Fuzzilli et jouer avec les différentes options de configuration. Ensuite, jetez un œil à Fuzzer.swift pour la logique de fuzzing de haut niveau. De là, plongez dans toute partie qui vous semble intéressante.

Les correctifs, ajouts, autres contributions, etc. à ce projet sont très bienvenus ! Cependant, veuillez rapidement consulter les notes pour les contributeurs. Fuzzilli suit approximativement le guide de style de code de Google pour Swift.

Il serait grandement apprécié que vous envoyiez une courte note (incluant éventuellement un numéro CVE) à [email protected] ou ouvriez une pull request pour toute vulnérabilité découverte avec l'aide de ce projet afin qu'elle puisse être incluse dans la section démonstration de bogues. Autrement, vous pouvez bien sûr réclamer toute prime de bogue, crédits CVE, etc. pour les vulnérabilités :)

Concept

Lors du fuzzing pour des bogues de cœur d'interpréteur, par exemple dans les compilateurs JIT, la correction sémantique des programmes générés devient une préoccupation. Cela contraste avec la plupart des autres scénarios, par exemple le fuzzing des API d'exécution, où la correction sémantique peut facilement être contournée en enveloppant le code généré dans des constructions try-catch. Il existe différentes possibilités pour atteindre un taux acceptable d'échantillons sémantiquement corrects, dont l'une est une approche mutationnelle où tous les échantillons du corpus sont également sémantiquement valides. Dans ce cas, chaque mutation a seulement une faible chance de transformer un échantillon valide en un échantillon invalide.

Pour implémenter un fuzzer JavaScript basé sur les mutations, il faut définir des mutations du code JavaScript. Au lieu de muter l'AST ou d'autres éléments syntaxiques d'un programme, un langage intermédiaire personnalisé (IL) est défini sur lequel les mutations du flux de contrôle et de données d'un programme peuvent être effectuées plus directement. Cet IL est ensuite traduit en JavaScript pour exécution. Le langage intermédiaire ressemble approximativement à ceci :

root@kitploit:~
v0 <− LoadInteger '0'
v1 <− LoadInteger '10'
v2 <− LoadInteger '1'
v3 <− LoadInteger '0'
BeginFor v0, '<', v1, '+', v2 −> v4
   v6 <− BinaryOperation v3, '+', v4
   Reassign v3, v6
EndFor
v7 <− LoadString 'Result: '
v8 <− BinaryOperation v7, '+', v3
v9 <− LoadGlobal 'console'
v10 <− CallMethod v9, 'log', [v8]

Qui peut par exemple être trivialement traduit en code JavaScript suivant :

root@kitploit:~
const v0 = 0;
const v1 = 10;
const v2 = 1;
let v3 = 0;
for (let v4 = v0; v4 < v1; v4 = v4 + v2) {
    const v6 = v3 + v4;
    v3 = v6;
}
const v7 = "Result: ";
const v8 = v7 + v3;
const v9 = console;
const v10 = v9.log(v8);

Ou au code JavaScript suivant en inlineant les expressions intermédiaires :

root@kitploit:~
let v3 = 0;
for (let v4 = 0; v4 < 10; v4++) {
    v3 = v3 + v4;
}
console.log("Result: " + v3);

FuzzIL a un certain nombre de propriétés :

  • Un programme FuzzIL est simplement une liste d'instructions.
  • Une instruction FuzzIL est une opération avec des variables d'entrée et de sortie et potentiellement un ou plusieurs paramètres (entre guillemets simples dans la notation ci-dessus).
  • Les entrées des instructions sont toujours des variables, il n'y a pas de valeurs immédiates.
  • Chaque sortie d'une instruction est une nouvelle variable, et les variables existantes ne peuvent être réaffectées que par des opérations dédiées telles que l'instruction Reassign.
  • Chaque variable est définie avant d'être utilisée.

Un certain nombre de mutations peuvent ensuite être effectuées sur ces programmes :

  • InputMutator : remplace les variables d'entrée des instructions par des différentes pour muter le flux de données du programme.
  • CodeGenMutator : génère du code et l'insère quelque part dans le programme muté. Le code est généré soit en exécutant un générateur de code, soit en copiant certaines instructions d'un autre programme du corpus (épissage).
  • CombineMutator : insère un programme du corpus dans une position aléatoire dans le programme muté.
  • OperationMutator : mute les paramètres des opérations, par exemple en remplaçant une constante entière par une autre.
  • et plus encore...

Une discussion beaucoup plus approfondie sur le fonctionnement de Fuzzilli peut être trouvée ici.

Implémentation

Le fuzzer est implémenté en Swift, avec certaines parties (par exemple les mesures de couverture, les interactions socket, etc.) implémentées en C.

Architecture

Une instance de fuzzer (implémentée dans Fuzzer.swift) est composée des composants centraux suivants :

  • MutationFuzzer : produit de nouveaux programmes à partir de programmes existants en appliquant des mutations. Ensuite, exécute les échantillons produits et les évalue.
  • ScriptRunner : exécute les programmes du langage cible.
  • Corpus : stocke les échantillons intéressants et les fournit au fuzzer principal.
  • Environment : a connaissance de l'environnement d'exécution, par exemple les builtins disponibles, les noms de propriétés et les méthodes.
  • Minimizer : minimise les programmes crashants et intéressants.
  • Evaluator : évalue si un échantillon est intéressant selon une certaine métrique, par exemple la couverture de code.
  • Lifter : traduit un programme FuzzIL vers le langage cible (JavaScript).

De plus, un certain nombre de modules sont optionnellement disponibles :

  • Statistics : rassemble diverses informations statistiques.
  • NetworkSync : synchronise plusieurs instances sur le réseau.
  • ThreadSync : synchronise plusieurs instances au sein du même processus.
  • Storage : stocke les programmes crashants sur le disque.

Le fuzzer est piloté par événements, la plupart des interactions entre différentes classes se produisant via des événements. Les événements sont déclenchés par exemple suite à un crash ou à la découverte d'un programme intéressant, à l'exécution d'un nouveau programme, à la génération d'un message de log, etc. Voir Events.swift pour la liste complète des événements. Le mécanisme d'événements découple efficacement les différents composants du fuzzer et facilite l'implémentation de modules supplémentaires.

Un programme FuzzIL peut être construit à l'aide d'une instance ProgramBuilder. Un ProgramBuilder fournit des méthodes pour créer et ajouter de nouvelles instructions, ajouter des instructions d'un autre programme, récupérer des variables existantes, interroger le contexte d'exécution à la position actuelle (par exemple si elle se trouve à l'intérieur d'une boucle), et plus encore.

Exécution

Fuzzilli utilise un mode d'exécution personnalisé appelé REPRL (read-eval-print-reset-loop). Pour cela, le moteur cible est modifié pour accepter une entrée de script via des pipes et/ou une mémoire partagée, l'exécuter, puis réinitialiser son état interne et attendre le prochain script. Cela supprime le surcoût lié à la création de processus et en grande partie à l'initialisation du moteur.

Scalabilité

Il y a une instance Fuzzer par processus cible. Cela permet une exécution synchrone des programmes et simplifie ainsi l'implémentation de divers algorithmes tels que les mutations consécutives et la minimisation. De plus, cela évite de devoir implémenter un accès thread-safe à l'état interne, par exemple le corpus. Chaque instance de fuzzer a sa propre DispatchQueue, correspondant conceptuellement à un seul thread. En règle générale, toute interaction avec une instance Fuzzer doit se produire sur la file d'attente de répartition de cette instance. Cela garantit la sécurité des threads car la file d'attente est série. Pour plus de détails, voir la documentation.

Pour passer à l'échelle, les instances de fuzzer peuvent former une hiérarchie arborescente, dans laquelle elles signalent les nouveaux échantillons intéressants et les crashs à leur nœud parent. En retour, un nœud parent synchronise son corpus avec ses nœuds enfants. La communication entre les nœuds de l'arbre peut se faire de différentes manières, chacune implémentée comme un module :

  • Communication inter-thread : synchronise les instances dans le même processus en mettant des tâches en file d'attente dans la DispatchQueue de l'autre fuzzer.
  • Communication inter-machine : synchronise les instances via un protocole simple basé sur TCP.

Cette conception permet au fuzzer de passer à l'échelle vers plusieurs cœurs sur une seule machine ainsi que vers de nombreuses machines différentes. Comme un nœud parent peut rapidement devenir surchargé si trop d'instances lui envoient des programmes, il est possible de configurer plusieurs niveaux d'instances, par exemple une instance racine, 16 nœuds intermédiaires connectés à la racine, et 256 "feuilles" connectées aux nœuds intermédiaires. Voir le répertoire Cloud/ pour plus d'informations sur le fuzzing distribué.

Ressources

Ressources supplémentaires sur ce fuzzer :

  • Une présentation sur Fuzzilli donnée à l'Offensive Con 2019.
  • Le mémoire de master pour lequel l'implémentation initiale a été réalisée.
  • Un article de blog par Sensepost sur l'utilisation de Fuzzilli pour trouver un bogue dans V8.
  • Un article de blog par Doyensec sur le fuzzing du moteur JerryScript avec Fuzzilli.
  • Un article du NDSS Symposium 2023 sur Fuzzilli et sa comparaison avec d'autres fuzzers.

Démonstration de bogues

La liste suivante contient certains des bogues découverts avec l'aide de Fuzzilli. Seuls les bogues ayant un impact sur la sécurité et présents dans au moins une version bêta du logiciel concerné doivent être inclus dans cette liste. Étant donné que Fuzzilli est souvent utilisé pour des tests de fuzzing continus pendant le développement, de nombreux problèmes découverts par lui ne sont pas inclus dans cette liste car ils sont généralement trouvés avant que le code vulnérable n'atteigne une version bêta. Une liste de tous les problèmes récemment trouvés par Fuzzilli dans V8 peut cependant être trouvée ici.

Remerciements particuliers à tous les utilisateurs de Fuzzilli qui ont signalé des bogues découverts par celui-ci !

WebKit/JavaScriptCore

  • Issue 185328 : Le compilateur DFG utilise un registre de sortie incorrect pour l'opération NumberIsInteger
  • CVE-2018-4299 : performProxyCall fuit un objet interne vers le script
  • CVE-2018-4359 : compileMathIC produit un code machine incorrect
  • CVE-2019-8518 : Accès hors limites dans le JIT FTL dû à LICM déplaçant un accès à un tableau avant la vérification des limites
  • CVE-2019-8558 : Use-after-free de CodeBlock dû à des Watchpoints pendant
  • CVE-2019-8611 : L'optimisation AIR supprime incorrectement l'affectation à un registre
  • CVE-2019-8623 : Le mouvement de code invariant de boucle (LICM) dans le JIT DFG laisse une variable de pile non initialisée
  • CVE-2019-8622 : doesGC() du DFG est incorrect concernant le comportement de l'opération HasIndexedProperty sur les StringObjects
  • CVE-2019-8671 : DFG : Le mouvement de code invariant de boucle (LICM) laisse un accès à une propriété d'objet non gardé
  • CVE-2019-8672 : Use-after-free de JSValue dans les ValueProfiles
  • CVE-2019-8678 : JSC échoue à exécuter haveABadTime() lorsque certains prototypes sont modifiés, conduisant à des confusions de type
  • CVE-2019-8685 : JSPropertyNameEnumerator utilise des ID de structure incorrects
  • CVE-2019-8765 : Confusion de type GetterSetter lors de la compilation DFG
  • CVE-2019-8820 : Confusion de type lors du bailout lors de la reconstruction des objets arguments

Gecko/Spidermonkey

  • CVE-2018-12386 : Bogue d'allocation de registres dans IonMonkey conduit à des confusions de type
  • CVE-2019-9791 : L'inférence de type d'IonMonkey est incorrecte pour les constructeurs entrés via OSR
  • CVE-2019-9792 : IonMonkey fuit la valeur magique JS_OPTIMIZED_OUT vers le script
  • CVE-2019-9816 : ObjectGroup inattendu dans l'opération ObjectGroupDispatch
  • CVE-2019-9813 : Le code compilé par IonMonkey ne met pas à jour les types de propriétés inférés, conduisant à des confusions de type
  • CVE-2019-11707 : IonMonkey prédit incorrectement le type de retour de Array.prototype.pop, conduisant à des confusions de type
  • CVE-2020-15656 : Confusion de type pour les arguments spéciaux dans IonMonkey
  • CVE-2021-29982 : Allocation de registre incorrecte (trouvé par JIT-Picker)
  • CVE-2021-29984 : Le réordonnancement d'instructions combiné à un GC inattendu peut conduire à une corruption mémoire
  • CVE-2022-28285 : AliasSet pour MLoadTypedArrayElementHole trop permissif
  • CVE-2022-31745 : Erreur dans le GC incrémental
  • CVE-2022-42928 : Annotations KeepAlive manquantes pour certaines opérations BigInt peuvent conduire à une corruption mémoire
  • CVE-2022-45406 : Use-after-free d'un Realm JavaScript
  • CVE-2023-4577 : Corruption mémoire due à l'interaction du GC et des expressions régulières

Chromium/v8* Issue 939316: Turbofan peut lire un pointeur Map hors limites lors de l'optimisation de Reflect.construct

  • Issue 944062: JSCallReducer::ReduceArrayIndexOfIncludes ne parvient pas à insérer les vérifications Map
  • CVE-2019-5831: Traitement incorrect des Maps dans V8
  • Issue 944865: Représentation de valeur invalide dans V8
  • CVE-2019-5841: Bogue dans l'heuristique d'inlining
  • CVE-2019-5847: Les éléments scellés/gelés de V8 provoquent un crash
  • CVE-2019-5853: Corruption de mémoire dans la vérification de longueur de regexp
  • Issue 992914: La migration de Map ne respecte pas les types d'éléments, ce qui conduit à une confusion de type
  • CVE-2020-6512: Confusion de type dans V8
  • CVE-2020-16006: Corruption de mémoire due à une collision de hachage mal gérée dans DescriptorArray
  • CVE-2021-37991: Condition de course lors de la compilation JIT concurrente
  • Issue 1359937: La désérialisation de BigInts pourrait produire une valeur -0n invalide
  • Issue 1377775: Vérification de type incorrecte lors de l'inlining de Array.prototype.at dans Turbofan

Duktape

  • Issue 2323: Pointeur valstack instable dans putprop
  • Issue 2320: Dépassement du pointeur Memcmp dans la fonction intégrée de chaîne

JerryScript

  • CVE-2020-13991: Libération incorrecte des arguments spread
  • Issue 3784: Corruption de mémoire due à une énumération incorrecte des propriétés
  • CVE-2020-13623: Dépassement de pile via les clés de propriété pour les objets Proxy
  • CVE-2020-13649 (1): Corruption de mémoire due à la gestion des erreurs en cas de OOM
  • CVE-2020-13649 (2): Corruption de mémoire due à la gestion des erreurs en cas de OOM
  • CVE-2020-13622: Corruption de mémoire due à un traitement incorrect des clés de propriété pour les objets Proxy
  • CVE-2020-14163: Corruption de mémoire due à une condition de course déclenchée par le ramasse-miettes lors de l'ajout de paires clé/valeur
  • Issue 3813: Gestion incorrecte des erreurs dans la fonction SerializeJSONProperty
  • Issue 3814: Objet Proxy inattendu dans l'assertion ecma_op_function_has_instance
  • Issue 3836: Corruption de mémoire due à une initialisation incorrecte de TypedArray
  • Issue 3837: Corruption de mémoire due à une gestion incorrecte de la mémoire dans getOwnPropertyDescriptor

Hermes

  • CVE-2020-1912: Corruption de mémoire lors de l'exécution de fonctions génératrices internes compilées paresseusement
  • CVE-2020-1914: Corruption de bytecode lors du traitement de l'instruction SaveGeneratorLong

Avertissement

Ce n'est pas un produit officiellement supporté par Google.

Télécharger l’outil
  • CVE-2019-8844 : ObjectAllocationSinkingPhase ne devrait pas insérer de hints pour les allocations qui ne sont plus valides
  • CVE-2020-3901 : Confusion de type GetterSetter dans le code JIT FTL (dû à un LICM pas toujours sûr)
  • CVE-2021-30851 : Verrou manquant lors d'une recherche simultanée dans une HashTable
  • CVE-2021-30818 : Confusion de type lors de la reconstruction des arguments sur la sortie OSR du DFG
  • CVE-2022-46696 : Échec d'assertion dû à une vérification d'exception manquante dans le code compilé JIT
  • CVE-2022-46699 : Échec d'assertion dû à une mise en cache incorrecte de propriétés spéciales dans les ICs
  • CVE-2022-46700 : Intl.Locale.prototype.hourCycles fuit un JSValue vide vers le script
  • CVE-2025-43214 : Corruption mémoire lors de JSToWasmEntry lors de l'itération sur la pile
  • CVE-2025-43213 : Typage invalide de l'opération NewRegExpUntyped
  • CVE-2023-5171 : Le GC a entraîné une condition use-after-free pendant la compilation
  • CVE-2023-25735 : Use-after-free potentiel dû à une incohérence de compartiment
  • CVE-2023-25751 : Corruption du code JIT
  • CVE-2023-29535 : Corruption mémoire lors du GC des weak maps
  • CVE-2023-29543 : Corruption mémoire dans Debugger
  • CVE-2023-29544 : Corruption mémoire lors du marquage parallèle
  • CVE-2023-29549 : Objets alloués dans un mauvais realm
  • CVE-2024-0744 : Le code compilé JIT aurait pu déréférencer une valeur de pointeur sauvage
  • CVE-2024-3854 : Le JIT a optimisé incorrectement les instructions switch et a généré du code avec des lectures hors limites
  • CVE-2024-3855 : Le JIT a optimisé incorrectement les opérations MSubstr, ce qui a conduit à des lectures hors limites
  • CVE-2024-3857 : Le JIT a généré un code incorrect entraînant un use-after-free lors du garbage collection
  • CVE-2024-3858 : La mutation d'un objet JavaScript pendant le traçage GC fait crasher le code JIT
  • CVE-2024-6613 : Liste incorrecte des frames de pile WASM
  • CVE-2024-6614 : Liste incorrecte des frames de pile WASM
  • CVE-2024-7521 : Gestion incomplète des exceptions WebAssembly
  • CVE-2024-7652 : Bogue dans la spécification AsyncGeneratorPrototype
  • CVE-2024-8381 : Confusion de type lors de la recherche d'un nom de propriété dans un bloc "with"
  • CVE-2024-9396 : Corruption mémoire potentielle lors du clonage de certains objets
  • CVE-2025-0240 : Incohérence de compartiment lors de l'analyse d'un module JSON JavaScript
  • CVE-2025-0241 : Corruption mémoire lors de l'utilisation de la segmentation de texte JavaScript
  • CVE-2025-1012 : Use-after-free lors de la délazification concurrente
  • CVE-2025-1934 : GC inattendu lors du traitement du bailout d'expressions régulières