
PoC et analyse d'un débordement local de tampon de pile dans dataSIMS Avionics ARINC 664-1 v4.5.3, avec ventilation du payload, script de reproduction et corrections de la fiche CVE.
Débordement de tampon local basé sur la pile dans dataSIMS Avionics ARINC 4.5.3 (Data Device Corporation)
Salut, je suis Kağan Çapar. En février 2020, j'ai trouvé un débordement de tampon local basé sur la pile dans le logiciel de bus de données avionique dataSIMS de DDC et j'ai publié une preuve de concept sur Exploit-DB en février 2021. Près de cinq ans plus tard, en janvier 2026, VulnCheck lui a attribué la CVE-2021-47881 en tant que CVE rétroactive — j'ai appris cette attribution après coup, et non de sa part.
Ce dépôt constitue l'archive de cette découverte : le PoC original préservé tel que publié, un port Python 3 octet pour octet identique, une analyse annotée de la charge utile, et des corrections pour deux problèmes dans l'enregistrement CVE publié.
Périmètre, d'emblée. Ceci est un enregistrement, pas une analyse de cause racine. dataSIMS est un logiciel commercial closed-source, il n'existe aucun correctif fournisseur, et je n'ai pas re-testé ceci contre une version actuelle. Ce qui est vérifiable ici est vérifié et montré ; tout le reste est signalé dans Limitations. Si vous êtes venu ici en attendant la profondeur de CVE-2026-5201, lisez d'abord cette note.
| CVE | CVE-2021-47881 |
| CWE | CWE-121 — Débordement de tampon basé sur la pile |
| CVSS v4.0 | 6.7 MOYEN — AV:L/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N (VulnCheck) |
| CVSS v3.1 | 8.4 ÉLEVÉ — AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (VulnCheck) |
| Composant affecté | dataSIMS Avionics ARINC 664-1, version 4.5.3 |
| Fournisseur | Data Device Corporation |
| CNA | VulnCheck |
| Découverte | 2020-02-17 |
| PoC publié | 2021-02-19 — EDB-49577 |
| CVE publiée | 2026-01-23 (NVD) |
| Correctif fournisseur | aucun publié |
| Testé sur | Windows 10 Entreprise x64 |
Le composant affecté est le module ARINC 664-1 de dataSIMS 4.5.3. Il relit un fichier de résultats qui — malgré le module auquel il appartient — est nommé milstd1553result.txt ; ce nom est un artefact du fournisseur hérité de la lignée MIL-STD-1553 de la suite, et non une indication du module affecté. Fournir une version surdimensionnée de ce fichier, façonnée par un attaquant, fait déborder un tampon de pile de taille fixe pendant le chemin de relecture et écrase l'adresse de retour sauvegardée. Le crash se termine avec un contrôle total de EIP :
EIP 42424242 <- 'BBBB' de la charge utile
ECX 42424242
C0000005 <- STATUS_ACCESS_VIOLATION
Le PoC publié fait 1040 octets et s'arrête à l'écrasement de EIP. Il n'atteint pas l'exécution de code, et cela n'a jamais été son intention — voir Exploitabilité.
La disposition des champs du PoC, vérifiée en exécutant le port (py poc/poc_py3.py --layout) :
Le décalage de EIP est 1007. Ce n'est pas un nombre que vous obtenez avec !mona findmsp ou pattern_offset.rb — c'est la somme de cinq champs réglés à la main. Le PoC original a été construit en élargissant un crash jusqu'à ce que l'adresse de retour bouge, et non en localisant le décalage de manière analytique. Je le signale plutôt que de l'embellir : une réécriture propre trouverait la vraie distance jusqu'à l'adresse de retour sauvegardée et supprimerait entièrement align, imp et imp2, puisque aucun d'eux ne porte de sens. imp/imp2 sont des chaînes de remplissage, pas des imports.
buf est un stub msfvenom shikata_ga_nai de 29 octets. Désassemblé avec ndisasm -b32 :
00000000 DAC1 fcmovb st1 ; opération FPU factice (signature sgn)
00000002 D97424F4 fnstenv [esp-0xc] ; GetPC
00000006 58 pop eax ; eax = &stub
00000007 BB0B7E9762 mov ebx,0x62977e0b ; clé XOR
0000000C 33C9 xor ecx,ecx
0000000E B101 mov cl,0x1 ; <-- UN SEUL bloc de 4 octets
00000010 315819 xor [eax+0x19],ebx ; décoder le bloc à +0x19
00000013 83E8FC sub eax,-4 ; eax += 4
00000016 035815 add ebx,[eax+0x15] ; plan de clés
00000019 E9 db 0xe9 ; <-- bloc encodé, pas du code
0000001A 8B db 0x8b
0000001B 7C9C jl 0xffffffb9
Deux choses en ressortent, et toutes deux signifient que la charge utile ne peut jamais s'exécuter :
mov cl,0x1 — la boucle de décodage est configurée pour un seul bloc de 4 octets. Il n'y a pas de véritable charge utile derrière, seulement ces 4 octets.\xe2\xf4 (loop) est absent. Un stub sgn complet termine la boucle de décodage avec loop avant le corps encodé. Ici, l'exécution retombe directement de add ebx,[eax+0x15] dans E9 8B 7C 9C — qui, à ce moment-là, est encore encodé, et n'est de toute façon pas une séquence d'instructions valide.Le stub est donc un espace réservé qui occupe la queue de la charge utile. Cela correspond à la façon dont le PoC a été décrit sur Exploit-DB, et c'est la lecture honnête : c'est une démonstration de contrôle de EIP, pas un exploit fonctionnel.
En pesant cela comme le ferait un courtier ou un fournisseur, plutôt que comme le fait le vecteur CVSS v3.1 :
milstd1553result.txt est un fichier que l'application produit elle-même, dans un emplacement que le même utilisateur contrôle déjà. Un attaquant capable de le réécrire peut généralement déjà exécuter du code en tant que cet utilisateur. Cela en fait un bug de robustesse bien plus qu'un bug de sécurité.EIP sur une build x86 de 2020 ne dit pas grand-chose en soi. Le transformer en exécution nécessite un scénario DEP/ASLR — un module sans /DYNAMICBASE, une chaîne ROP, ou un écrasement partiel. Rien de tout cela n'a été fait, et je n'ai pas vérifié quelles mitigations la build actuelle embarque.UI:A de CVSS v4.0 reflète la réalité ; le UI:N de v3.1 non.Si quelqu'un veut rendre cela réellement intéressant, les surfaces productives ne sont pas du tout ce fichier : le pilote noyau que DDC livre pour ses cartes PCIe 1553/664 (gestion des IOCTL → LPE), tout analyse de trames ARINC 664/AFDX exposée au réseau, et les formats de fichiers d'entrée que la suite consomme depuis des sources non fiables. Ceux-là franchissent de vraies frontières. Celui-ci non.
L'enregistrement CVE comporte deux défauts qu'il vaut la peine d'énoncer clairement, puisqu'il est publié sous mon nom.
La désignation du produit dans l'enregistrement — « dataSIMS Avionics ARINC 664-1 version 4.5.3 » — est correcte. Le composant affecté est le module ARINC 664, comme indiqué dans mon titre original sur Exploit-DB.
Le défaut est la référence fournisseur que le CNA a attachée. La NVD cite BU-69414, qui est la page produit du logiciel MIL-STD-1553 de DDC — une pile de bus de données différente de celle que cette découverte affecte. L'ARINC 664 est l'AFDX (Ethernet commuté profilé, ARINC 664 Partie 7) ; le MIL-STD-1553 est un bus à double redondance commande/réponse de 1 Mbps. Ce sont des normes sans rapport.
La cause probable de la mauvaise citation est le nom du fichier de résultats. dataSIMS nomme le fichier de résultats du module ARINC 664 milstd1553result.txt — un vestige de la lignée MIL-STD-1553 de la suite. Quiconque lit la description de la CVE et cherche une page produit fournisseur correspondante suivra cette chaîne directement vers la gamme 1553, ce qui semble être ce qui s'est produit. Le nom du fichier n'est pas une preuve du module affecté, et un enregistrement qui pointe vers la page produit 1553 envoie les défenseurs auditer le mauvais composant.
Les deux vecteurs proviennent de VulnCheck, et ils se contredisent sur les deux points qui comptent :
| v3.1 (8.4 ÉLEVÉ) | v4.0 (6.7 MOYEN) | |
|---|---|---|
| Interaction utilisateur | UI:N — aucune | UI:A — requise |
| Impact | C:H/I:H/A:H — CIA complète | VC:N/VI:N/VA:H — disponibilité uniquement |
Ils ne peuvent pas être tous les deux corrects. Le vecteur v4.0 est celui qui se défend : le PoC démontre un crash, pas une divulgation ni une perte d'intégrité. Le score v3.1 de 8.4 surévalue la découverte, et je préfère le dire ici plutôt que d'en bénéficier.
Rien ici n'a besoin du logiciel cible — le PoC écrit uniquement le fichier malformé. Déclencher le débordement nécessite dataSIMS 4.5.3, qui est un logiciel commercial sous licence que ce dépôt ne distribue pas.
# afficher la carte des champs, n'écrit rien
py poc/poc_py3.py --layout
# écrire la charge utile de 1040 octets
py poc/poc_py3.py -o milstd1553result.txt
Chargez ensuite le fichier avec la build affectée sous un débogueur et observez l'écrasement de EIP. poc/49577.py est le source Python 2 original, archivé verbatim ; il ne s'exécutera pas sous Python 3.
Le port produit un fichier de 1040 octets identique octet pour octet (sha256 530efb5e…). Trois choses ont dû changer, et une chose qui ressemble à un bug n'en est pas un :
print len(win32) est une instruction en Python 2, une SyntaxError en Python 3.str avec un shellcode bytes. Python 2 le permettait parce que str était des octets ; Python 3 lève une TypeError.open(..., "w") doit devenir "wb". En mode texte, Python 3 encoderait en UTF-8 chaque octet ≥ 0x80 du stub — 0xda → 0xc3 0x9a — corrompant silencieusement la charge utile et modifiant sa longueur.imp2 = "\x61\x72\x61\x63\x61\x67\x131\x7a" n'est pas un caprice lié à la version. \x prend exactement deux chiffres hexadécimaux en Python 2 comme en Python 3, donc est suivi du caractère . Le champ fait 9 octets dans les deux cas. C'est juste une lecture malaisée.Énoncées explicitement pour que personne n'ait à deviner ce qui a été fait et ce qui ne l'a pas été :
EIP est tout le résultat.Kağan Çapar — GitHub · Exploit-DB · LinkedIn · X
| Champ | Décalage | Longueur | Contenu |
|---|
junk | 0 / 0x000 | 600 | remplissage 0x41 |
align | 600 / 0x258 | 8 | "22221111" |
prop | 608 / 0x260 | 380 | remplissage 0x43 |
imp | 988 / 0x3dc | 10 | "bzhrturlu2" |
imp2 | 998 / 0x3e6 | 9 | "aracag" 0x13 "1z" |
overwrite | 1007 / 0x3ef | 4 | 0x42 × 4 → adresse de retour sauvegardée |
buf | 1011 / 0x3f3 | 29 | stub de décodage shikata_ga_nai |
| total | 1040 | sha256 530efb5efef917082e40dcf379f5e0a526375724af18aba6f0270f794f96d066 |
\x1310x131| Date | Événement |
|---|
| 2020-02-17 | Vulnérabilité trouvée |
| 2021-02-19 | PoC publié — EDB-49577 |
| 2026-01-22 | Avis VulnCheck publié |
| 2026-01-23 | CVE-2021-47881 publiée sur NVD |
| 2026-06-17 | Enregistrement NVD modifié pour la dernière fois |