Package privé de reproduction de désinfectant de bout en bout pour six constats GDCM
Six défauts de parseur/codec dans GDCM, reproduits sur la v3.2.6 sous forme d'échecs de sanitizer ou de vérifications de propagation bornées. Chaque déclencheur automatisé dispose d'un contrôle quasi-valide qui ne produit pas le signal vulnérable. Le constat 1 inclut également une primitive de flux de contrôle instrumentée.
Destiné à la revue par les mainteneurs et les coordinateurs de vulnérabilités. Lire SAFETY.md avant d'exécuter quoi que ce soit.
manifest/targets.env :
| Nom | Révision | Description |
|---|
vulnerable | 9c71b163 | tag v3.2.6 |
master | 2cd05d13 | instantané amont master examiné statiquement ; matrice d'exécution en attente |
fixed | non défini | à renseigner uniquement lorsqu'un commit de remédiation revu existe |
master est un instantané daté, pas une branche mobile. Les deux révisions sont accessibles depuis le dépôt public, donc bootstrap.sh peut préparer l'une ou l'autre sans aucune source privée.
Les preuves d'exécution dans ce dépôt concernent la v3.2.6. Les plages plus larges ci-dessous proviennent de l'inspection de l'historique des sources ; les motifs impliqués subsistent également dans l'instantané master épinglé.
| # | CWE | Plage inspectée dans les sources | Chemin requis |
|---|---|---|---|
| 1 | CWE-787 | v3.0.4 à v3.2.7 | lecture multi-trames RLE YBR_FULL_422 |
| 2 | CWE-787 | v2.0.16 à v3.2.7 | encodage/transcodage JPEG2000 |
| 3 | CWE-125 | v2.0.5 à v3.2.7 | analyse de palette segmentée ; l'application de la LUT expose les valeurs propagées |
| 4 | CWE-787 | v2.0.8 à v3.2.7 | ImageRegionReader::ReadIntoBuffer ; lié à la validation de précision incomplète après CVE-2024-22373 |
| 5 | CWE-674 | v2.0.4 ou antérieur à v3.2.7 | analyse ordinaire de séquences imbriquées |
| 6 | CWE-369 | v2.0.4 ou antérieur à v3.2.7 | analyse RLE ordinaire avec NumSegments=0 |
fixtures/ - les entrées DICOM inertes, épinglées par SHA-256 dans manifest/expectations.json et vérifiées avant chaque exécution de déclencheurgenerators/ - générateurs de sources déterministes et sans dépendances pour chaque fixtureharnesses/ - harnais minimaux de lecture/encodage/décodage ; le constat 2 est présenté à la fois via la CLI gdcmconv et via l'API de transcodage de la bibliothèque qu'un serveur appelleraitmanifest/expectations.json - commandes lisibles par machine, signaux décisifs et critères d'acceptation pour la cible fixedscripts/ - préparation des sources épinglées, builds avec sanitizer, exécution bornée, nettoyageevidence/ - résultats concis déjà observés, avec les cibles non testées indiquées explicitementLICENSE - licence MITUn environnement de build Linux ou macOS jetable avec Git, Python 3, CMake 3.20+, Ninja et une chaîne d'outils C++11 (Clang ou GCC). Sur Ubuntu : git python3 cmake ninja-build clang zlib1g-dev. Définir CC/CXX pour utiliser GCC à la place.
La préparation des sources clone via HTTPS sauf si GDCM_SOURCE_REPO pointe vers un clone local existant. Aucun hôte SSH n'est utilisé.
Ces commandes préparent uniquement les sources et les artefacts de build ; elles n'ouvrent aucune fixture.
./scripts/build-target.sh vulnerable asan debug
./scripts/build-target.sh vulnerable ubsan debug
./scripts/build-target.sh master asan debug
./scripts/build-target.sh master ubsan debug
Le troisième argument est le profil. debug correspond à -O0 -g ; release correspond à -O2 -g -DNDEBUG, ce qui élide les gdcm_debug_assert() de GDCM et correspond à la façon dont les distributions compilent la bibliothèque. Exécuter la matrice sous les deux profils répond à la première question que pose un mainteneur, à savoir si les rapports sont un artefact d'un build avec assertions activées.
GDCM_SUPPORT_BROKEN_IMPLEMENTATION=ON est la valeur par défaut de GDCM lui-même et est laissée telle quelle. Remplacer le parallélisme conservateur avec JOBS=8.
Chaque build écrit build-info.json (révision, compilateur, flags, plateforme) dans son arbre de build GDCM, et chaque résumé d'exécution l'incorpore, de sorte que les preuves archivées sont auto-descriptives.
export GDCM_REPRO_ACK=I_UNDERSTAND_THIS_CRASHES_A_LOCAL_PROCESS
./scripts/run-matrix.sh vulnerable master --profile debug # all automated cases
./scripts/run-one.sh vulnerable f1 # one trigger
./scripts/run-one.sh vulnerable f1 --control # its control
run-matrix.sh exécute chaque cas automatisé pour chaque cible, ne s'arrête pas au premier échec, et écrit _runs/matrix-<stamp>.json ainsi qu'un fichier rendu _runs/matrix-<stamp>.md. Le cas f1-exploit en deux étapes reste manuel et est signalé comme tel plutôt que d'être mal classé comme un cas automatisé en échec.
Chaque processus enfant a les core dumps désactivés et un délai d'expiration de 15 secondes ; le constat 5 reçoit en plus une limite de pile bornée. Les sorties restent sous _runs/. Le classificateur fait correspondre la classe de sanitizer et la fonction impliquée, jamais les adresses, les PID ou les numéros de ligne source.
Pour vulnerable, un cas passe lorsque le signal décisif apparaît et que son contrôle reste propre. Pour master, le runner enregistre une observation plutôt qu'un verdict prédéclaré. Pour fixed, un cas passe uniquement lorsque le signal est absent, qu'aucun autre sanitizer ou signal fatal n'apparaît, et que le harnais renvoie un résultat propre autorisé. Ces règles sont provisoires tant que FIXED_REV ne désigne pas un correctif réel ; elles doivent être revues au regard du comportement de rejet-ou-traitement prévu par ce correctif.
| Cas | Constat | Ce qu'il montre |
|---|---|---|
f1 | 1 | écriture tas ASan dans RLECodec::DecodeFragment |
f1-exploit | 1 | écrasement instrumenté d'objet adjacent et contrôle de branche indirecte (Linux x86-64) |
f2 | 2 | écriture tas ASan dans opj_write_from_memory via gdcmconv --j2k |
f2-lib | 2 | la même écriture via ImageChangeTransferSyntax::Change |
f3 | 3 | lecture tas ASan dans l'expansion de palette segmentée |
f3-propagation | 3 | des octets hors limites atteignent les pixels décodés, rapportés sous forme de comptage |
f3-sentinel | 3 | un mot de garde connu et borné franchit la limite logique de la LUT |
f4 | 4 | écriture tas ASan dans le décodage de région JPEG2000 |
f5 | 5 | épuisement de pile ASan sur des éléments de séquence imbriqués |
f6 | 6 | division par zéro UBSan dans le décodage RLE ; SIGFPE sur x86 |
Deux harnais supplémentaires relèvent de la recherche d'exploitabilité plutôt que de cas de reproduction, et ne se compilent que dans le profil sans sanitizer sur Linux x86-64 :
| Harnais | Constat | Ce qu'il établit |
|---|---|---|
finding01_groom | 1 | l'adjacence glibc testée, observée via des hooks d'enregistrement d'allocations |
finding03_leak | 3 | une surlecture de 131070 octets peut exposer un pointeur de bibliothèque spécifique au build |
evidence/v3.2.6-macos-arm64-debug.md consigne la matrice debug v3.2.6 complète, y compris chaque contrôle et les deux vérifications bornées de propagation du constat 3.
evidence/v3.2.6-linux-x86_64-finding01-groom.md et evidence/v3.2.6-linux-x86_64-finding03-leak.md consignent les deux résultats d'exploitabilité ci-dessous. Les résultats pour le master actuel, la matrice complète en profil release et f1-exploit ne sont pas revendiqués tant que leurs transcriptions ne sont pas conservées.
./scripts/clean.sh
Le nettoyage refuse de s'exécuter sans le marqueur du package et ne supprime que _work, _build, _generated, _runs et les caches de bytecode Python sous ce dépôt. Les preuves conservées sous evidence/ ne sont pas supprimées.
f1-exploit est réservé à Linux-x86_64 et s'exécute manuellement ; manifest/expectations.json contient la séquence de commandes exacte. Sous la disposition d'allocation déterministe du harnais, il teste trois faits distincts, chacun avec un cas négatif apparié :
f1 simple, signale une corruption mais explicitement pas un contrôle du contenu, de sorte que la vérification est falsifiable ;Environ la moitié des fenêtres de 8 octets dans le débordement de 12288 octets acceptent une valeur arbitraire. Les autres sont couplées, car DoYBRFull422 duplique un octet source vers deux positions de sortie ; l'offset 6144 est l'une des fenêtres libres. Le décodage de la trame 1 s'exécute en dernier, donc c'est le contenu de la trame 1 qui persiste au-delà de l'allocation.
Le harnais enregistre si ImageReader::Read() renvoie true alors que l'objet adjacent est modifié. Une transcription Linux x86-64 réussie doit être conservée avant de décrire ce résultat comme une preuve observée.
f1-exploit fournit sa propre disposition de victime, il ne peut donc pas répondre à la question de savoir si un processus non modifié présente cette disposition. finding01_groom utilise la glibc standard, le PIE par défaut et l'ASLR, avec des hooks d'allocation globaux qui enregistrent mais ne déplacent pas les allocations. Dans les tests conservés :
finding01 simple meurt de la même manière sans aucune instrumentation.Sur le build glibc testé, le constat 1 a causé de manière fiable un déni de service ; aucun chemin d'exécution de code n'a été trouvé. La géométrie testée était fixe, et d'autres allocateurs ou plateformes peuvent disposer le tas différemment.
finding03_leak est le résultat le plus fort. Dans le build testé, la lecture hors limites atteint 131070 octets, un pointeur de vtable gdcm::ByteValue entre dans les pixels décodés, et le harnais dérive la base de chargement de la bibliothèque en utilisant l'offset de vtable connu de ce build. Il s'agit d'un résultat de divulgation locale au niveau de l'API : il nécessite l'application de la LUT et l'accès au tampon de pixels décodés. Il ne démontre pas qu'un service réseau renvoie ces pixels.
Les deux ne peuvent pas être chaînés en exécution de code ici, et pas seulement parce qu'aucune victime n'a été trouvée : ils nécessitent des valeurs de PhotometricInterpretation différentes, donc deux fichiers, et une base divulguée n'est utile que tant que le processus qui la divulgue est encore vivant.
Un rapport de sanitizer prouve l'événement de sécurité mémoire ou de comportement indéfini énoncé dans le processus et la révision testés. f1-exploit teste le contrôle d'octets et un écrasement de pointeur de fonction adjacent sous un allocateur instrumenté qui fournit délibérément la disposition cible. Il n'établit pas cette disposition dans un consommateur non modifié. Les essais conservés de finding01_groom n'ont pas observé cette disposition pour la géométrie et le build glibc testés.
Rien de tout cela ne prouve l'accessibilité à distance dans un produit particulier, la persistance ou l'applicabilité en aval. L'argument d'accessibilité pour un déploiement donné est une affirmation distincte, formulée dans le texte de divulgation et non par ce package.