
Boîte à outils de durcissement de la sécurité pour les systèmes COBOL hérités — détection d'Unicode invisible, analyse des limites de format, intégrité de la transformation du code source
Boîte à outils d'audit de sécurité pour les systèmes hérités COBOL
Fait partie de la méthodologie de recherche VTR | DOI : 10.5281/zenodo.22063208 Statut : Reproductible | Licence : MIT | Piste : Infrastructure critique
Détecte les divergences de contexte de compilation, les attaques Unicode invisibles et les motifs COBOL dangereux dans les sources GnuCOBOL. Le même fichier source compilé avec -fixed vs -free produit des programmes différents — cet outil rend cette divergence observable et reproductible.
git clone https://github.com/LuisCastellanos-dev/cobol-shield
cd cobol-shield
bash tools/poc_compiler_flag.sh
Cet outil ne prétend pas démontrer ni ne démontre l'exécution de code à distance, l'élévation de privilèges ou l'exploitation réseau. Les résultats sont classés comme CONFIRMADO, PROBABLE ou OBSERVADO selon la méthodologie VTR — la classification reflète la force des preuves, non la gravité de l'impact.
Boîte à outils d'audit de sécurité pour les systèmes hérités COBOL
Détecte les attaques Unicode invisibles, les motifs COBOL dangereux et les problèmes d'intégrité de transformation de format dans les sources GnuCOBOL. Validé avec GnuCOBOL 3.1.2. Comportement sur IBM Enterprise COBOL ou Micro Focus non vérifié — la sémantique des indicateurs spécifiques au compilateur peut différer.
PIC X accepte tout. Votre batch ne devrait pas.
cobol-shield couvre deux surfaces de menace distinctes :
1. Caractères Unicode invisibles — CVE-2021-42574 et vecteurs de classe Glassworm qui contournent la revue visuelle du code et corrompent silencieusement les champs PIC X.
2. Analyse statique COBOL — motifs dangereux dans les sources héritées : working-storage non initialisé, débordement STRING/UNSTRING non vérifié, incompatibilités de taille REDEFINES, et conditions positionnelles en format fixe qui changent de sens lors d'une transformation.
| Fichier | Objectif |
|---|---|
tools/check-invisibles.py | Vérificateur CI — sortie 1 en cas de détection d'Unicode invisible |
tools/clean-invisibles.py | Assainisseur avec journal d'audit forensique |
src/AUDITOR-INVISIBLE.cob | Validateur d'octets en COBOL utilisant HEX-OF |
tools/cobol_rules.py | Règles d'analyse statique R-01 à R-04 |
tools/transform_renumber.py | Simulateur de décalage de renumérotation en format fixe (Phase 2) |
tools/poc_compiler_flag.sh | PoC définitif — même fichier, -fixed vs -free, divergence d'indicateur de compilateur |
tools/poc_differential.sh | PoC différentiel Phase 2 — SOURCE A vs SOURCE B (migration manuelle) |
Chaque règle produit une sortie VTR Finding Schema v1 compatible avec cryptofault et vtr-forensic-img via context_loader.
| Règle | Nom | Sévérité | Classification |
|---|---|---|---|
| R-01 | UNINITIALIZED_WS | Élevée | HECHO |
| R-02 | UNSTRING_NO_OVERFLOW | Élevée | HECHO |
| R-03 | REDEFINES_SIZE_MISMATCH | Élevée | HECHO |
| R-04 | FORMAT_BOUNDARY_ANALYSIS | Info | PROYECCION |
R-01 — UNINITIALIZED_WS Détecte les variables Working-Storage déclarées sans clause VALUE et sans INITIALIZE ou MOVE dans la PROCEDURE DIVISION. Risque de comportement indéfini silencieux dans les environnements batch et CICS.
R-02 — UNSTRING_NO_OVERFLOW Détecte les instructions STRING/UNSTRING sans gestion ON OVERFLOW. Troncature silencieuse lorsque l'entrée dépasse la longueur du champ cible.
R-03 — REDEFINES_SIZE_MISMATCH Détecte les REDEFINES où le champ redéfini déclare plus d'octets que sa base. Risque de violation de limite mémoire — comportement dépendant du compilateur.
R-04 — FORMAT_BOUNDARY_ANALYSIS (Phase 1 — observations uniquement) Détecte les conditions positionnelles dans les sources COBOL en format fixe :
COL73_NONEMPTY — contenu non-espace dans la zone d'identification (colonnes 73–80)COL7_VERB — verbe exécutable COBOL dans une ligne commentée (col7 = * / / / D)SOURCE_BOUNDARY — contenu au-delà de la colonne 80R-04 produit severity=info, classification=PROYECCION. Il documente des conditions de format — pas des vulnérabilités. L'impact nécessite une analyse différentielle de transformation (Phase 2).
La thèse centrale : un fichier COBOL en format fixe a une sémantique différente selon l'indicateur de compilateur utilisé pour le construire — et cet indicateur vit en dehors du fichier source.
Démontré avec GnuCOBOL 3.1.2, artefact unique, sans modification :
bash tools/poc_compiler_flag.sh
cobc -x -fixed poc-same-file.cbl → compile → sortie : 0000001000
cobc -x -free poc-same-file.cbl → 10 erreurs de compilation
Sous -fixed : ligne 6 col7=* est l'indicateur de commentaire — MOVE 999999 est dormant, le programme s'exécute et affiche 1000.
Sous -free : les numéros de séquence 000100...001000 sont analysés comme des littéraux numériques — l'en-tête PROGRAM-ID est signalé comme manquant, chaque ligne produit une erreur. Le même fichier est syntaxiquement invalide.
L'indicateur de compilateur n'est pas dans le fichier source. Il vit dans le Makefile, la configuration CI ou l'invocation de l'opérateur. Le changer — intentionnellement ou accidentellement — change si le programme est valide et ce qu'il fait.
Preuve : corpus/fixed-format/poc-evidence.md
SHA-256 et journal d'erreurs complet documentés.
Un PoC antérieur démontre la même thèse via une migration manuelle :
SOURCE A (format fixe, col7='*' dormant) : sortie → 0000001000
SOURCE B (format libre, code actif) : sortie → 0000999999
SHA-256 A : b70a948a0df5e8f685e82f5bffc9c4710f2c0a7a23b6294e7ca20092c2d25d37
SHA-256 B : f5fd80f79ed3e5be97628f89790256d6fba80605dce2b7985b729b5fef6f26d5
Limitation : SOURCE B est une représentation manuelle d'une migration incorrecte, pas la sortie d'IBM Z Open Editor ou IBM SCU sous renumérotation réelle. Le PoC d'indicateur de compilateur ci-dessus n'a pas cette limitation.
Plages détectées :
| Point de code | Nom | Risque |
|---|---|---|
| U+0001–U+001F | Contrôles C0 | Abends batch |
| U+200B–U+200F | Largeur nulle | Corruption de données, troncature VSAM |
| U+202A–U+202E | Bidi Override | Trojan Source — CVE-2021-42574 |
| U+2066–U+2069 | Bidi Isolate | Usurpation de direction |
| U+FE00–U+FE0F | Sélecteurs de variation | Stéganographie de classe Glassworm |
| U+E000–U+F8FF | Zone d'usage privé | Dissimulation de charge utile |
| U+FEFF | BOM | Octet préfixé silencieusement |
# Inspection au niveau des octets
hexdump -C source.cob | grep -E "e2 80 (8b|ae)"
# Vérification CI Unicode — sortie 1 en cas de détection
python3 tools/check-invisibles.py .
# Assainir avec journal d'audit forensique
python3 tools/clean-invisibles.py . --report audit-$(date +%Y%m%d).log
# Exécuter les règles d'analyse statique
python3 -c "
from tools.cobol_rules import scan_path_r01, scan_path_r02, scan_path_r03, scan_path_r04
import json
for f in scan_path_r02('your-source.cbl'):
print(f.to_json())
"
# PoC différentiel de transformation
bash tools/poc_differential.sh
- name: Check for invisible Unicode
run: python3 tools/check-invisibles.py .
PIC X(n) est un tampon d'octets brut. Il accepte toute séquence d'octets sans validation. Lorsqu'une couche API Zowe transmet du JSON à un copybook COBOL via MOVE, de l'Unicode invisible entre silencieusement dans l'enregistrement.