
Toolkit di hardening della sicurezza per sistemi legacy COBOL — rilevamento di Unicode invisibile, analisi dei confini di formato, integrità della trasformazione del codice sorgente
Toolkit di auditing di sicurezza per sistemi legacy COBOL
Parte della VTR Research Methodology | DOI: 10.5281/zenodo.22063208 Stato: Riproducibile | Licenza: MIT | Track: Infrastrutture Critiche
Rileva divergenze nel contesto di compilazione, attacchi Unicode invisibili e pattern COBOL non sicuri nei sorgenti GnuCOBOL. Lo stesso file sorgente compilato con -fixed rispetto a -free produce programmi diversi — questo strumento rende tale divergenza osservabile e riproducibile.
git clone https://github.com/LuisCastellanos-dev/cobol-shield
cd cobol-shield
bash tools/poc_compiler_flag.sh
Questo strumento non rivendica né dimostra esecuzione di codice remoto, escalation di privilegi o sfruttamento di rete. I risultati sono classificati come CONFIRMADO, PROBABLE o OBSERVADO secondo la metodologia VTR — la classificazione riflette la solidità delle prove, non la gravità dell'impatto.
Toolkit di auditing di sicurezza per sistemi legacy COBOL
Rileva attacchi Unicode invisibili, pattern COBOL non sicuri e problemi di integrità nella trasformazione di formato nei sorgenti GnuCOBOL. Validato con GnuCOBOL 3.1.2. Comportamento su IBM Enterprise COBOL o Micro Focus non verificato — la semantica dei flag specifici del compilatore può differire.
PIC X accetta tutto. Il tuo batch non dovrebbe.
cobol-shield copre due superfici di minaccia distinte:
1. Caratteri Unicode Invisibili — CVE-2021-42574 e vettori di classe Glassworm che aggirano la revisione visiva del codice e corrompono silenziosamente i campi PIC X.
2. Analisi Statica COBOL — pattern non sicuri nei sorgenti legacy: working-storage non inizializzato, overflow non controllato di STRING/UNSTRING, discrepanze di dimensione nei REDEFINES e condizioni posizionali in formato fisso che cambiano significato sotto trasformazione.
| File | Scopo |
|---|---|
tools/check-invisibles.py | Checker CI — esce con 1 al rilevamento di Unicode invisibile |
tools/clean-invisibles.py | Sanitizzatore con log di audit forense |
src/AUDITOR-INVISIBLE.cob | Validatore di byte in COBOL che usa HEX-OF |
tools/cobol_rules.py | Regole di analisi statica da R-01 a R-04 |
tools/transform_renumber.py | Simulatore di slittamento di rinumerazione in formato fisso (Fase 2) |
tools/poc_compiler_flag.sh | PoC definitivo — stesso file, -fixed vs -free, divergenza del flag del compilatore |
tools/poc_differential.sh | PoC differenziale di Fase 2 — SOURCE A vs SOURCE B (migrazione manuale) |
Ogni regola produce un output VTR Finding Schema v1 compatibile con
cryptofault e vtr-forensic-img tramite context_loader.
| Regola | Nome | Gravità | Classificazione |
|---|---|---|---|
| R-01 | UNINITIALIZED_WS | Alta | HECHO |
| R-02 | UNSTRING_NO_OVERFLOW | Alta | HECHO |
| R-03 | REDEFINES_SIZE_MISMATCH | Alta | HECHO |
| R-04 | FORMAT_BOUNDARY_ANALYSIS | Info | PROYECCION |
R-01 — UNINITIALIZED_WS Rileva variabili Working-Storage dichiarate senza clausola VALUE e senza INITIALIZE o MOVE nella PROCEDURE DIVISION. Rischio silenzioso di comportamento indefinito in ambienti batch e CICS.
R-02 — UNSTRING_NO_OVERFLOW Rileva istruzioni STRING/UNSTRING senza gestione di ON OVERFLOW. Troncamento silenzioso quando l'input supera la lunghezza del campo di destinazione.
R-03 — REDEFINES_SIZE_MISMATCH Rileva REDEFINES in cui il campo ridefinito dichiara più byte della sua base. Rischio di violazione dei confini di memoria — comportamento dipendente dal compilatore.
R-04 — FORMAT_BOUNDARY_ANALYSIS (Fase 1 — solo osservazioni) Rileva condizioni posizionali nei sorgenti COBOL in formato fisso:
COL73_NONEMPTY — contenuto non spazio nell'area di identificazione (colonne 73–80)COL7_VERB — verbo eseguibile COBOL in una riga commentata (col7 = * / / / D)SOURCE_BOUNDARY — contenuto oltre la colonna 80R-04 produce severity=info, classification=PROYECCION. Documenta
condizioni di formato — non vulnerabilità. L'impatto richiede un'analisi
differenziale di trasformazione (Fase 2).
La tesi centrale: un file COBOL in formato fisso ha semantiche diverse a seconda del flag del compilatore usato per compilarlo — e quel flag risiede al di fuori del file sorgente.
Dimostrato con GnuCOBOL 3.1.2, singolo artefatto, nessuna modifica:
bash tools/poc_compiler_flag.sh
cobc -x -fixed poc-same-file.cbl → compila → output: 0000001000
cobc -x -free poc-same-file.cbl → 10 errori di compilazione
Con -fixed: la riga 6 col7=* è l'indicatore di commento — MOVE 999999
è dormiente, il programma viene eseguito e visualizza 1000.
Con -free: i numeri di sequenza 000100...001000 vengono interpretati come
letterali numerici — l'header PROGRAM-ID risulta mancante, ogni riga produce
un errore. Lo stesso file è sintatticamente non valido.
Il flag del compilatore non è dentro il file sorgente. Risiede nel Makefile, nella configurazione CI o nell'invocazione dell'operatore. Cambiarlo — intenzionalmente o accidentalmente — cambia se il programma è valido e cosa fa.
Prove: corpus/fixed-format/poc-evidence.md
SHA-256 e log completo degli errori documentati.
Un PoC precedente dimostra la stessa tesi tramite migrazione manuale:
SOURCE A (formato fisso, col7='*' dormiente): output → 0000001000
SOURCE B (formato libero, codice attivo): output → 0000999999
SHA-256 A: b70a948a0df5e8f685e82f5bffc9c4710f2c0a7a23b6294e7ca20092c2d25d37
SHA-256 B: f5fd80f79ed3e5be97628f89790256d6fba80605dce2b7985b729b5fef6f26d5
Limitazione: SOURCE B è una rappresentazione manuale di una migrazione errata, non l'output di IBM Z Open Editor o IBM SCU sotto una reale rinumerazione. Il PoC del flag del compilatore sopra non ha questa limitazione.
Intervalli rilevati:
| Codepoint | Nome | Rischio |
|---|---|---|
| U+0001–U+001F | Controlli C0 | Abend batch |
| U+200B–U+200F | Zero-Width | Corruzione dati, troncamento VSAM |
| U+202A–U+202E | Bidi Override | Trojan Source — CVE-2021-42574 |
| U+2066–U+2069 | Bidi Isolate | Spoofing di direzione |
| U+FE00–U+FE0F | Variation Selectors | Steganografia di classe Glassworm |
| U+E000–U+F8FF | Private Use Area | Occultamento di payload |
| U+FEFF | BOM | Byte anteposto silenziosamente |
# Ispezione a livello di byte
hexdump -C source.cob | grep -E "e2 80 (8b|ae)"
# Controllo CI Unicode — esce con 1 al rilevamento
python3 tools/check-invisibles.py .
# Sanitizza con log di audit forense
python3 tools/clean-invisibles.py . --report audit-$(date +%Y%m%d).log
# Esegui le regole di analisi statica
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 differenziale di trasformazione
bash tools/poc_differential.sh
- name: Check for invisible Unicode
run: python3 tools/check-invisibles.py .
PIC X(n) è un buffer di byte grezzo. Accetta qualsiasi sequenza di byte senza
validazione. Quando un livello API Zowe passa JSON a un copybook COBOL tramite
MOVE, l'Unicode invisibile entra silenziosamente nel record.
Il COBOL in formato fisso aggiunge una seconda superficie: le semantiche posizionali delle colonne (col 7 come area indicatore, colonne 73–80 come area di identificazione) dipendono dal formato. Uno strumento di migrazione che non preserva queste semantiche può attivare codice dormiente o corrompere silenziosamente la struttura del programma.