Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
fuzzilli — Un fuzzer de motores JavaScript | Kitploit
Herramientas/GitHubGitHub/googleprojectzero/fuzzilli
Análisis de VulnerabilidadesFuzzingAnálisis de BinariosPapers e InvestigaciónAprendizaje y Educación
GitHubgoogleprojectzero/fuzzilli

fuzzilli

Un fuzzer de motores JavaScript

Ver Repositorio
2.3k36655hace 7 díasRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Fuzzilli

Un fuzzer guiado por cobertura para intérpretes de lenguajes dinámicos basado en un lenguaje intermedio personalizado ("FuzzIL") que puede ser mutado y traducido a JavaScript.

Uso

Los pasos básicos para usar este fuzzer son:

  1. Descarga el código fuente de uno de los motores JavaScript compatibles. Consulta el directorio Targets/ para la lista de motores JavaScript compatibles.
  2. Aplica los parches correspondientes del directorio del objetivo. Consulta también el README.md en ese directorio.
  3. Compila el motor con instrumentación de cobertura (requiere clang >= 4.0) como se describe en el README.
  4. Compila el fuzzer: swift build [-c release].
  5. Ejecuta el fuzzer: swift run [-c release] FuzzilliCli --profile=<profile> [other cli options] /path/to/jsshell. Consulta también swift run FuzzilliCli --help.

La compilación y ejecución de Fuzzilli y los motores JavaScript compatibles dentro de Docker y en Google Compute Engine también es compatible.

Hacking

Revisa main.swift para ver un ejemplo de uso de la librería Fuzzilli y juega con las diversas opciones de configuración. Luego, echa un vistazo a Fuzzer.swift para la lógica de fuzzing de alto nivel. A partir de ahí, sumérgete en cualquier parte que parezca interesante.

Descargar herramienta

¡Los parches, adiciones, otras contribuciones, etc. a este proyecto son muy bienvenidos! Sin embargo, revisa rápidamente las notas para contribuyentes. Fuzzilli sigue aproximadamente la guía de estilo de código de Google para swift.

Se agradecería mucho si pudieras enviar una nota breve (posiblemente incluyendo un número CVE) a [email protected] o abrir un pull request por cualquier vulnerabilidad encontrada con la ayuda de este proyecto para que pueda ser incluida en la sección bug showcase. Aparte de eso, por supuesto puedes reclamar cualquier recompensa por errores, créditos CVE, etc. por las vulnerabilidades :)

Concepto

Al fuzzear para encontrar errores en el núcleo del intérprete, por ejemplo en compiladores JIT, la corrección semántica de los programas generados se convierte en una preocupación. Esto contrasta con la mayoría de otros escenarios, por ejemplo, fuzzear APIs de tiempo de ejecución, donde la corrección semántica se puede sortear fácilmente envolviendo el código generado en construcciones try-catch. Hay diferentes posibilidades para lograr una tasa aceptable de muestras semánticamente correctas, una de ellas es un enfoque mutacional en el que todas las muestras en el corpus también son semánticamente válidas. En ese caso, cada mutación solo tiene una pequeña probabilidad de convertir una muestra válida en una inválida.

Para implementar un fuzzer JavaScript basado en mutaciones, es necesario definir mutaciones al código JavaScript. En lugar de mutar el AST u otros elementos sintácticos de un programa, se define un lenguaje intermedio personalizado (IL) sobre el cual se pueden realizar mutaciones al flujo de control y datos de un programa de manera más directa. Este IL luego se traduce a JavaScript para su ejecución. El lenguaje intermedio tiene aproximadamente el siguiente aspecto:

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]

Que puede, por ejemplo, traducirse trivialmente al siguiente código JavaScript:

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);

O al siguiente código JavaScript mediante la inserción de expresiones intermedias:

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

FuzzIL tiene varias propiedades:

  • Un programa FuzzIL es simplemente una lista de instrucciones.
  • Una instrucción FuzzIL es una operación junto con variables de entrada y salida y potencialmente uno o más parámetros (encerrados entre comillas simples en la notación anterior).
  • Las entradas a las instrucciones son siempre variables, no hay valores inmediatos.
  • Cada salida de una instrucción es una nueva variable, y las variables existentes solo pueden reasignarse mediante operaciones dedicadas como la instrucción Reassign.
  • Cada variable se define antes de ser utilizada.

Se pueden realizar varias mutaciones en estos programas:

  • InputMutator: reemplaza las variables de entrada de las instrucciones por otras diferentes para mutar el flujo de datos del programa.
  • CodeGenMutator: genera código y lo inserta en algún lugar del programa mutado. El código se genera ejecutando un generador de código o copiando algunas instrucciones de otro programa en el corpus (splicing).
  • CombineMutator: inserta un programa del corpus en una posición aleatoria en el programa mutado.
  • OperationMutator: muta los parámetros de las operaciones, por ejemplo reemplazando una constante entera por otra diferente.
  • y más...

Se puede encontrar una discusión mucho más detallada sobre cómo funciona Fuzzilli aquí.

Implementación

El fuzzer está implementado en Swift, con algunas partes (por ejemplo, mediciones de cobertura, interacciones de socket, etc.) implementadas en C.

Arquitectura

Una instancia del fuzzer (implementada en Fuzzer.swift) está compuesta por los siguientes componentes centrales:

  • MutationFuzzer: produce nuevos programas a partir de los existentes aplicando mutaciones. Luego ejecuta las muestras producidas y las evalúa.
  • ScriptRunner: ejecuta programas del lenguaje objetivo.
  • Corpus: almacena muestras interesantes y las suministra al núcleo del fuzzer.
  • Environment: tiene conocimiento del entorno de ejecución, por ejemplo, los builtins disponibles, nombres de propiedades y métodos.
  • Minimizer: minimiza programas que causan fallos y programas interesantes.
  • Evaluator: evalúa si una muestra es interesante según alguna métrica, por ejemplo, cobertura de código.
  • Lifter: traduce un programa FuzzIL al lenguaje objetivo (JavaScript).

Además, hay varios módulos disponibles opcionalmente:

  • Statistics: recopila diversas piezas de información estadística.
  • NetworkSync: sincroniza múltiples instancias a través de la red.
  • ThreadSync: sincroniza múltiples instancias dentro del mismo proceso.
  • Storage: almacena programas que causan fallos en disco.

El fuzzer está basado en eventos, con la mayoría de las interacciones entre diferentes clases ocurriendo a través de eventos. Los eventos se despachan, por ejemplo, como resultado de un fallo o de que se encuentre un programa interesante, se ejecute un nuevo programa, se genere un mensaje de registro, etc. Consulta Events.swift para la lista completa de eventos. El mecanismo de eventos desacopla efectivamente los diversos componentes del fuzzer y facilita la implementación de módulos adicionales.

Un programa FuzzIL se puede construir usando una instancia de ProgramBuilder. ProgramBuilder proporciona métodos para crear y agregar nuevas instrucciones, agregar instrucciones de otro programa, recuperar variables existentes, consultar el contexto de ejecución en la posición actual (por ejemplo, si está dentro de un bucle) y más.

Ejecución

Fuzzilli utiliza un modo de ejecución personalizado llamado REPRL (read-eval-print-reset-loop). Para ello, el motor objetivo se modifica para aceptar una entrada de script a través de pipes y/o memoria compartida, ejecutarlo, luego restablecer su estado interno y esperar el siguiente script. Esto elimina la sobrecarga de la creación de procesos y en gran parte de la inicialización del motor.

Escalabilidad

Hay una instancia de Fuzzer por proceso objetivo. Esto permite la ejecución síncrona de programas y, por lo tanto, simplifica la implementación de varios algoritmos, como mutaciones consecutivas y minimización. Además, evita la necesidad de implementar acceso seguro para subprocesos al estado interno, por ejemplo, el corpus. Cada instancia del fuzzer tiene su propia DispatchQueue, que corresponde conceptualmente a un solo subproceso. Como regla general, cada interacción con una instancia de Fuzzer debe ocurrir en la cola de distribución de esa instancia. Esto garantiza la seguridad de subprocesos ya que la cola es serial. Para más detalles, consulta la documentación.

Para escalar, las instancias del fuzzer pueden formar una jerarquía de árbol, en cuyo caso informan las muestras interesantes y los fallos recién encontrados a su nodo padre. A su vez, un nodo padre sincroniza su corpus con sus nodos hijos. La comunicación entre nodos en el árbol puede ocurrir de diferentes maneras, cada una implementada como un módulo:

  • Comunicación entre subprocesos: sincroniza instancias en el mismo proceso encolando tareas en la DispatchQueue del otro fuzzer.
  • Comunicación entre máquinas: sincroniza instancias a través de un protocolo simple basado en TCP.

Este diseño permite que el fuzzer escale a muchos núcleos en una sola máquina, así como a muchas máquinas diferentes. Como un nodo padre puede sobrecargarse rápidamente si demasiadas instancias le envían programas, es posible configurar múltiples niveles de instancias, por ejemplo, una instancia raíz, 16 nodos intermedios conectados a la raíz y 256 "hojas" conectadas a los nodos intermedios. Consulta el directorio Cloud/ para más información sobre fuzzing distribuido.

Recursos

Recursos adicionales sobre este fuzzer:

  • Una presentación sobre Fuzzilli presentada en Offensive Con 2019.
  • La tesis de maestría para la cual se realizó la implementación inicial.
  • Un artículo de blog de Sensepost sobre el uso de Fuzzilli para encontrar un error en v8.
  • Un artículo de blog de Doyensec sobre fuzzing del motor JerryScript con Fuzzilli.
  • Un artículo del Simposio NDSS 2023 sobre Fuzzilli y cómo se compara con otros fuzzers.

Escaparate de Bug

La siguiente es una lista de algunos de los bugs encontrados con la ayuda de Fuzzilli. Solo deben incluirse en esta lista los bugs con impacto en la seguridad que estuvieran presentes en al menos una versión Beta del software afectado. Dado que Fuzzilli se utiliza a menudo para pruebas de fuzzing continuas durante el desarrollo, muchos problemas encontrados por él no se incluyen en esta lista, ya que generalmente se descubren antes de que el código vulnerable alcance una versión Beta. Sin embargo, se puede encontrar una lista de todos los problemas encontrados recientemente por Fuzzilli en V8 aquí.

¡Un agradecimiento especial a todos los usuarios de Fuzzilli que han informado bugs encontrados por él!

WebKit/JavaScriptCore

  • Issue 185328: El compilador DFG utiliza un registro de salida incorrecto para la operación NumberIsInteger
  • CVE-2018-4299: performProxyCall filtra un objeto interno al script
  • CVE-2018-4359: compileMathIC produce código máquina incorrecto
  • CVE-2019-8518: Acceso fuera de límites en FTL JIT debido a que LICM mueve el acceso al array antes de la comprobación de límites
  • CVE-2019-8558: Use-after-free de CodeBlock debido a Watchpoints colgantes
  • CVE-2019-8611: La optimización AIR elimina incorrectamente la asignación a un registro
  • CVE-2019-8623: El movimiento de código invariante de bucle (LICM) en DFG JIT deja una variable de pila sin inicializar
  • CVE-2019-8622: doesGC() de DFG es incorrecto acerca del comportamiento de la operación HasIndexedProperty en StringObjects
  • CVE-2019-8671: DFG: El movimiento de código invariante de bucle (LICM) deja el acceso a propiedades de objeto sin protección
  • CVE-2019-8672: Use-after-free de JSValue en ValueProfiles
  • CVE-2019-8678: JSC no ejecuta haveABadTime() cuando algunos prototipos son modificados, lo que lleva a confusiones de tipo
  • CVE-2019-8685: JSPropertyNameEnumerator usa identificadores de estructura incorrectos
  • CVE-2019-8765: Confusión de tipo GetterSetter durante la compilación DFG
  • CVE-2019-8820: Confusión de tipo durante el bailout al reconstruir objetos de argumentos
  • CVE-2019-8844: ObjectAllocationSinkingPhase no debería insertar pistas para asignaciones que ya no son válidas
  • CVE-2020-3901: Confusión de tipo GetterSetter en código FTL JIT (debido a LICM no siempre seguro)
  • CVE-2021-30851: Falta de bloqueo durante la búsqueda concurrente en HashTable
  • CVE-2021-30818: Confusión de tipo al reconstruir argumentos en la salida OSR de DFG
  • CVE-2022-46696: Fallo de aserción debido a falta de comprobación de excepción en código compilado por JIT
  • CVE-2022-46699: Fallo de aserción debido a almacenamiento en caché incorrecto de propiedades especiales en ICs
  • CVE-2022-46700: Intl.Locale.prototype.hourCycles filtra un JSValue vacío al script
  • CVE-2025-43214: Corrupción de memoria durante JSToWasmEntry al iterar sobre la pila
  • CVE-2025-43213: Tipificación inválida de la operación NewRegExpUntyped

Gecko/Spidermonkey

  • CVE-2018-12386: Error de asignación de registros en IonMonkey conduce a confusiones de tipo
  • CVE-2019-9791: La inferencia de tipos de IonMonkey es incorrecta para constructores ingresados a través de OSR
  • CVE-2019-9792: IonMonkey filtra el valor mágico JS_OPTIMIZED_OUT al script
  • CVE-2019-9816: ObjectGroup inesperado en la operación ObjectGroupDispatch
  • CVE-2019-9813: El código compilado por IonMonkey no actualiza los tipos de propiedad inferidos, lo que lleva a confusiones de tipo
  • CVE-2019-11707: IonMonkey predice incorrectamente el tipo de retorno de Array.prototype.pop, lo que lleva a confusiones de tipo
  • CVE-2020-15656: Confusión de tipo para argumentos especiales en IonMonkey
  • CVE-2021-29982: Asignación de registros incorrecta (encontrado por JIT-Picker)
  • CVE-2021-29984: La reordenación de instrucciones en combinación con un GC inesperado puede provocar corrupción de memoria
  • CVE-2022-28285: AliasSet para MLoadTypedArrayElementHole demasiado permisivo
  • CVE-2022-31745: Error en el GC incremental
  • CVE-2022-42928: La falta de anotaciones KeepAlive para algunas operaciones BigInt puede provocar corrupción de memoria
  • CVE-2022-45406: Use-after-free de un Realm de JavaScript
  • CVE-2023-4577: Corrupción de memoria debido a la interacción de GC y RegEx
  • CVE-2023-5171: GC provocó una condición de use-after-free durante la compilación
  • CVE-2023-25735: Posible use-after-free por falta de coincidencia de compartimentos
  • CVE-2023-25751: Corrupción de código jitted
  • CVE-2023-29535: Corrupción de memoria durante el GC de mapas débiles
  • CVE-2023-29543: Corrupción de memoria dentro del depurador
  • CVE-2023-29544: Corrupción de memoria durante el marcado paralelo
  • CVE-2023-29549: Objetos asignados en un realm incorrecto
  • CVE-2024-0744: El código compilado por JIT podría haber desreferenciado un valor de puntero salvaje
  • CVE-2024-3854: JIT optimizó incorrectamente las sentencias switch y generó código con lecturas fuera de límites
  • CVE-2024-3855: JIT optimizó incorrectamente las operaciones MSubstr, lo que provocó lecturas fuera de límites
  • CVE-2024-3857: JIT generó código incorrecto resultando en use-after-free durante la recolección de basura
  • CVE-2024-3858: Mutar un objeto JavaScript mientras el trazado del GC bloquea el código jitted
  • CVE-2024-6613: Listado incorrecto de marcos de pila WASM
  • CVE-2024-6614: Listado incorrecto de marcos de pila WASM
  • CVE-2024-7521: Manejo de excepciones de WebAssembly incompleto
  • CVE-2024-7652: Error en la especificación de AsyncGeneratorPrototype
  • CVE-2024-8381: Confusión de tipo al buscar un nombre de propiedad en un bloque "with"
  • CVE-2024-9396: Puede ocurrir una posible corrupción de memoria al clonar ciertos objetos
  • CVE-2025-0240: Falta de coincidencia de compartimentos al analizar el módulo JSON de JavaScript
  • CVE-2025-0241: Corrupción de memoria al usar la segmentación de texto de JavaScript
  • CVE-2025-1012: Use-after-free durante la deslazificación concurrente
  • CVE-2025-1934: GC inesperado durante el procesamiento de bailout de RegExp

Chromium/v8* Issue 939316: Turbofan puede leer un puntero Map fuera de límites al optimizar Reflect.construct

  • Issue 944062: JSCallReducer::ReduceArrayIndexOfIncludes no inserta comprobaciones de Map
  • CVE-2019-5831: Procesamiento incorrecto de Map en V8
  • Issue 944865: Representación de valor inválida en V8
  • CVE-2019-5841: Error en la heurística de inline
  • CVE-2019-5847: Elementos sellados/congelados de V8 causan un fallo
  • CVE-2019-5853: Corrupción de memoria en la comprobación de longitud de regexp
  • Issue 992914: La migración de Map no respeta los tipos de elementos, lo que provoca confusión de tipos
  • CVE-2020-6512: Confusión de tipos en V8
  • CVE-2020-16006: Corrupción de memoria debido a una colisión hash manejada incorrectamente en DescriptorArray
  • CVE-2021-37991: Condición de carrera durante la compilación JIT concurrente
  • Issue 1359937: La deserialización de BigInts podría resultar en un valor -0n inválido
  • Issue 1377775: Comprobación de tipo incorrecta al inlinear Array.prototype.at en Turbofan

Duktape

  • Issue 2323: Puntero valstack inestable en putprop
  • Issue 2320: Desbordamiento de puntero memcmp en string builtin

JerryScript

  • CVE-2020-13991: Liberación incorrecta de argumentos spread
  • Issue 3784: Corrupción de memoria debido a una enumeración de propiedades incorrecta
  • CVE-2020-13623: Desbordamiento de pila mediante claves de propiedad para objetos Proxy
  • CVE-2020-13649 (1): Corrupción de memoria debido al manejo de errores en caso de OOM
  • CVE-2020-13649 (2): Corrupción de memoria debido al manejo de errores en caso de OOM
  • CVE-2020-13622: Corrupción de memoria debido al manejo incorrecto de claves de propiedad para objetos Proxy
  • CVE-2020-14163: Corrupción de memoria debido a una condición de carrera desencadenada por la recolección de basura al agregar pares clave/valor
  • Issue 3813: Manejo de errores incorrecto en la función SerializeJSONProperty
  • Issue 3814: Objeto Proxy inesperado en la aserción ecma_op_function_has_instance
  • Issue 3836: Corrupción de memoria debido a una inicialización incorrecta de TypedArray
  • Issue 3837: Corrupción de memoria debido al manejo incorrecto de memoria en getOwnPropertyDescriptor

Hermes

  • CVE-2020-1912: Corrupción de memoria al ejecutar funciones generadoras internas compiladas de forma diferida
  • CVE-2020-1914: Corrupción de bytecode al manejar la instrucción SaveGeneratorLong

Disclaimer

Este no es un producto oficialmente compatible de Google.