
Kit de ferramentas de fortalecimento de segurança para sistemas legados COBOL — deteção de Unicode invisível, análise de limites de formato, integridade da transformação de código-fonte
Kit de ferramentas de auditoria de segurança para sistemas legados COBOL
Parte da Metodologia de Pesquisa VTR | DOI: 10.5281/zenodo.22063208 Status: Reproduzível | Licença: MIT | Trilha: Infraestrutura Crítica
Detecta divergências de contexto de compilação, ataques com Unicode invisível e padrões COBOL inseguros em fontes GnuCOBOL. O mesmo arquivo-fonte compilado com -fixed vs -free produz programas diferentes — esta ferramenta torna essa divergência observável e reproduzível.
git clone https://github.com/LuisCastellanos-dev/cobol-shield
cd cobol-shield
bash tools/poc_compiler_flag.sh
Esta ferramenta não reivindica nem demonstra execução remota de código, escalonamento de privilégios ou exploração de rede. Os achados são classificados como CONFIRMADO, PROVÁVEL ou OBSERVADO conforme a metodologia VTR — a classificação reflete a força da evidência, não a severidade do impacto.
Kit de ferramentas de auditoria de segurança para sistemas legados COBOL
Detecta ataques com Unicode invisível, padrões COBOL inseguros e problemas de integridade na transformação de formato em fontes GnuCOBOL. Validado com GnuCOBOL 3.1.2. Comportamento em IBM Enterprise COBOL ou Micro Focus não verificado — a semântica das flags pode variar entre compiladores.
PIC X aceita tudo. Seu batch não deveria.
cobol-shield cobre duas superfícies de ameaça distintas:
1. Caracteres Unicode Invisíveis — CVE-2021-42574 e vetores da classe Glassworm que contornam a revisão visual de código e corrompem campos PIC X silenciosamente.
2. Análise Estática COBOL — padrões inseguros em fontes legadas: working-storage não inicializado, overflow não verificado em STRING/UNSTRING, incompatibilidades de tamanho em REDEFINES e condições posicionais de formato fixo que mudam de significado sob transformação.
| Arquivo | Propósito |
|---|---|
tools/check-invisibles.py | Verificador de CI — sai com código 1 ao detectar Unicode invisível |
tools/clean-invisibles.py | Sanitizador com log de auditoria forense |
src/AUDITOR-INVISIBLE.cob | Validador de bytes em COBOL usando HEX-OF |
tools/cobol_rules.py | Regras de análise estática R-01 a R-04 |
tools/transform_renumber.py | Simulador de deslocamento de renumeração em formato fixo (Fase 2) |
tools/poc_compiler_flag.sh | PoC definitivo — mesmo arquivo, -fixed vs -free, divergência de flag do compilador |
tools/poc_differential.sh | PoC diferencial da Fase 2 — FONTE A vs FONTE B (migração manual) |
Cada regra produz uma saída no VTR Finding Schema v1 compatível com
cryptofault e vtr-forensic-img via context_loader.
| Regra | Nome | Severidade | Classificação |
|---|---|---|---|
| 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 Detecta variáveis de Working-Storage declaradas sem cláusula VALUE e sem INITIALIZE ou MOVE na PROCEDURE DIVISION. Risco silencioso de comportamento indefinido em ambientes batch e CICS.
R-02 — UNSTRING_NO_OVERFLOW Detecta comandos STRING/UNSTRING sem tratamento de ON OVERFLOW. Truncamento silencioso quando a entrada excede o comprimento do campo de destino.
R-03 — REDEFINES_SIZE_MISMATCH Detecta REDEFINES em que o campo redefinido declara mais bytes que sua base. Risco de violação de limite de memória — comportamento dependente do compilador.
R-04 — FORMAT_BOUNDARY_ANALYSIS (Fase 1 — apenas observações) Detecta condições posicionais em fontes COBOL de formato fixo:
COL73_NONEMPTY — conteúdo não vazio na área de identificação (colunas 73–80)COL7_VERB — verbo executável COBOL em uma linha comentada (col7 = * / / / D)SOURCE_BOUNDARY — conteúdo além da coluna 80R-04 produz severity=info, classification=PROYECCION. Documenta
condições de formato — não vulnerabilidades. O impacto requer análise
diferencial de transformação (Fase 2).
A tese central: um arquivo COBOL em formato fixo tem semânticas diferentes dependendo da flag do compilador usada para compilá-lo — e essa flag vive fora do arquivo-fonte.
Demonstrado com GnuCOBOL 3.1.2, artefato único, sem modificação:
bash tools/poc_compiler_flag.sh
cobc -x -fixed poc-same-file.cbl → compila → saída: 0000001000
cobc -x -free poc-same-file.cbl → 10 erros de compilação
Sob -fixed: a linha 6, col7=*, é o indicador de comentário — MOVE 999999
está dormente, o programa executa e exibe 1000.
Sob -free: os números de sequência 000100...001000 são interpretados como
literais numéricos — o cabeçalho PROGRAM-ID é reportado como ausente, cada linha
produz um erro. O mesmo arquivo é sintaticamente inválido.
A flag do compilador não está dentro do arquivo-fonte. Ela vive no Makefile, na configuração de CI ou na invocação do operador. Alterá-la — intencionalmente ou acidentalmente — muda se o programa é válido e o que ele faz.
Evidência: corpus/fixed-format/poc-evidence.md
SHA-256 e log de erros completo documentados.
Um PoC anterior demonstra a mesma tese via migração manual:
FONTE A (formato fixo, col7='*' dormente): saída → 0000001000
FONTE B (formato livre, código ativo): saída → 0000999999
SHA-256 A: b70a948a0df5e8f685e82f5bffc9c4710f2c0a7a23b6294e7ca20092c2d25d37
SHA-256 B: f5fd80f79ed3e5be97628f89790256d6fba80605dce2b7985b729b5fef6f26d5
Limitação: A FONTE B é uma representação manual de migração incorreta, não a saída do IBM Z Open Editor ou IBM SCU sob renumeração real. O PoC de flag do compilador acima não tem essa limitação.
Intervalos detectados:
| Codepoint | Nome | Risco |
|---|---|---|
| U+0001–U+001F | Controles C0 | Abends em batch |
| U+200B–U+200F | Zero-Width | Corrupção de dados, truncamento VSAM |
| U+202A–U+202E | Bidi Override | Trojan Source — CVE-2021-42574 |
| U+2066–U+2069 | Bidi Isolate | Falsificação de direção |
| U+FE00–U+FE0F | Seletores de Variação | Esteganografia da classe Glassworm |
| U+E000–U+F8FF | Área de Uso Privado | Ocultação de payload |
| U+FEFF | BOM | Byte silenciosamente prefixado |
# Inspeção em nível de byte
hexdump -C source.cob | grep -E "e2 80 (8b|ae)"
# Verificação Unicode de CI — sai com código 1 ao detectar
python3 tools/check-invisibles.py .
# Sanitizar com log de auditoria forense
python3 tools/clean-invisibles.py . --report audit-$(date +%Y%m%d).log
# Executar regras de análise estática
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 diferencial de transformação
bash tools/poc_differential.sh
- name: Check for invisible Unicode
run: python3 tools/check-invisibles.py .
PIC X(n) é um buffer de bytes bruto. Ele aceita qualquer sequência de bytes sem
validação. Quando uma camada de API Zowe passa JSON para um copybook COBOL via
MOVE, Unicode invisível entra no registro silenciosamente.
O COBOL de formato fixo adiciona uma segunda superfície: as semânticas posicionais de coluna (col 7 como área de indicador, colunas 73–80 como área de identificação) dependem do formato. Uma ferramenta de migração que não preserva essas semânticas pode ativar código dormente ou corromper silenciosamente a estrutura do programa.