
Инструментарий для усиления безопасности устаревших систем COBOL — обнаружение невидимых символов Unicode, анализ границ формата, целостность преобразования исходного кода
Инструментарий аудита безопасности для устаревших систем COBOL
Часть методологии исследований VTR | DOI: 10.5281/zenodo.22063208 Статус: воспроизводимо | Лицензия: MIT | Направление: критическая инфраструктура
Обнаруживает расхождения контекста компиляции, атаки с использованием невидимых символов Unicode и небезопасные шаблоны COBOL в исходных кодах GnuCOBOL. Один и тот же исходный файл, скомпилированный с -fixed и -free, даёт разные программы — этот инструмент делает такое расхождение наблюдаемым и воспроизводимым.
git clone https://github.com/LuisCastellanos-dev/cobol-shield
cd cobol-shield
bash tools/poc_compiler_flag.sh
Этот инструмент не заявляет и не демонстрирует удалённое выполнение кода, повышение привилегий или сетевую эксплуатацию. Результаты классифицируются как CONFIRMADO, PROBABLE или OBSERVADO согласно методологии VTR — классификация отражает силу доказательств, а не серьёзность воздействия.
Инструментарий аудита безопасности для устаревших систем COBOL
Обнаруживает атаки с использованием невидимых символов Unicode, небезопасные шаблоны COBOL и проблемы целостности преобразования формата в исходных кодах GnuCOBOL. Проверено на GnuCOBOL 3.1.2. Поведение на IBM Enterprise COBOL или Micro Focus не проверено — семантика флагов может различаться в зависимости от компилятора.
PIC X принимает всё. Ваш пакетный процесс — не должен.
cobol-shield охватывает две различные поверхности угроз:
1. Невидимые символы Unicode — CVE-2021-42574 и векторы класса Glassworm, которые обходят визуальную проверку кода и незаметно повреждают поля PIC X.
2. Статический анализ COBOL — небезопасные шаблоны в устаревших исходных кодах: неинициализированная working-storage, непроверенное переполнение STRING/UNSTRING, несоответствия размеров REDEFINES и позиционные условия фиксированного формата, меняющие смысл при преобразовании.
| Файл | Назначение |
|---|---|
tools/check-invisibles.py | CI-проверка — завершается с кодом 1 при обнаружении невидимых символов Unicode |
tools/clean-invisibles.py | Санитайзер с журналом криминалистического аудита |
src/AUDITOR-INVISIBLE.cob | Валидатор байтов на COBOL с использованием HEX-OF |
tools/cobol_rules.py | Правила статического анализа R-01 — R-04 |
tools/transform_renumber.py | Симулятор сдвига перенумерации фиксированного формата (фаза 2) |
tools/poc_compiler_flag.sh | Окончательный PoC — один файл, -fixed против -free, расхождение флагов компилятора |
tools/poc_differential.sh | Дифференциальный PoC фазы 2 — SOURCE A против SOURCE B (ручная миграция) |
Каждое правило формирует вывод VTR Finding Schema v1, совместимый с
cryptofault и vtr-forensic-img через context_loader.
| Правило | Название | Серьёзность | Классификация |
|---|---|---|---|
| R-01 | UNINITIALIZED_WS | Высокая | HECHO |
| R-02 | UNSTRING_NO_OVERFLOW | Высокая | HECHO |
| R-03 | REDEFINES_SIZE_MISMATCH | Высокая | HECHO |
| R-04 | FORMAT_BOUNDARY_ANALYSIS | Информационная | PROYECCION |
R-01 — UNINITIALIZED_WS Обнаруживает переменные Working-Storage, объявленные без предложения VALUE и без INITIALIZE или MOVE в PROCEDURE DIVISION. Риск неявного неопределённого поведения в пакетных средах и средах CICS.
R-02 — UNSTRING_NO_OVERFLOW Обнаруживает операторы STRING/UNSTRING без обработки ON OVERFLOW. Неявное усечение, когда входные данные превышают длину целевого поля.
R-03 — REDEFINES_SIZE_MISMATCH Обнаруживает REDEFINES, где переопределяемое поле объявляет больше байтов, чем его базовое поле. Риск нарушения границ памяти — поведение зависит от компилятора.
R-04 — FORMAT_BOUNDARY_ANALYSIS (фаза 1 — только наблюдения) Обнаруживает позиционные условия в исходных кодах COBOL фиксированного формата:
COL73_NONEMPTY — непустое содержимое в области идентификации (столбцы 73–80)COL7_VERB — исполняемый глагол COBOL в закомментированной строке (col7 = * / / / D)SOURCE_BOUNDARY — содержимое за пределами столбца 80R-04 формирует severity=info, classification=PROYECCION. Он документирует
условия формата — а не уязвимости. Для оценки воздействия требуется
дифференциальный анализ преобразования (фаза 2).
Центральный тезис: файл COBOL фиксированного формата имеет разную семантику в зависимости от флага компилятора, использованного при сборке — и этот флаг находится вне исходного файла.
Продемонстрировано на GnuCOBOL 3.1.2, единственный артефакт, без модификаций:
bash tools/poc_compiler_flag.sh
cobc -x -fixed poc-same-file.cbl → компилируется → вывод: 0000001000
cobc -x -free poc-same-file.cbl → 10 ошибок компиляции
При -fixed: строка 6, col7=* — это индикатор комментария — MOVE 999999
неактивен, программа выполняется и выводит 1000.
При -free: порядковые номера 000100...001000 разбираются как числовые
литералы — заголовок PROGRAM-ID считается отсутствующим, каждая строка вызывает
ошибку. Один и тот же файл синтаксически некорректен.
Флаг компилятора не находится внутри исходного файла. Он находится в Makefile, конфигурации CI или в вызове оператора. Его изменение — намеренное или случайное — меняет, является ли программа корректной и что она делает.
Доказательства: corpus/fixed-format/poc-evidence.md
SHA-256 и полный журнал ошибок задокументированы.
Более ранний PoC демонстрирует тот же тезис через ручную миграцию:
SOURCE A (фиксированный формат, col7='*' неактивен): вывод → 0000001000
SOURCE B (свободный формат, код активен): вывод → 0000999999
SHA-256 A: b70a948a0df5e8f685e82f5bffc9c4710f2c0a7a23b6294e7ca20092c2d25d37
SHA-256 B: f5fd80f79ed3e5be97628f89790256d6fba80605dce2b7985b729b5fef6f26d5
Ограничение: SOURCE B — это ручное представление некорректной миграции, а не вывод IBM Z Open Editor или IBM SCU при реальной перенумерации. У приведённого выше PoC с флагом компилятора этого ограничения нет.
Обнаруживаемые диапазоны:
| Кодовая точка | Название | Риск |
|---|---|---|
| U+0001–U+001F | Управляющие символы C0 | Аварийные завершения пакетных процессов |
| U+200B–U+200F | Нулевой ширины | Повреждение данных, усечение VSAM |
| U+202A–U+202E | Переопределение Bidi | Trojan Source — CVE-2021-42574 |
| U+2066–U+2069 | Изоляция Bidi | Подмена направления |
| U+FE00–U+FE0F | Селекторы вариаций | Стеганография класса Glassworm |
| U+E000–U+F8FF | Область частного использования | Сокрытие полезной нагрузки |
| U+FEFF | BOM | Неявно добавленный байт |
# Байтовый анализ
hexdump -C source.cob | grep -E "e2 80 (8b|ae)"
# Проверка Unicode в CI — завершается с кодом 1 при обнаружении
python3 tools/check-invisibles.py .
# Санитизация с журналом криминалистического аудита
python3 tools/clean-invisibles.py . --report audit-$(date +%Y%m%d).log
# Запуск правил статического анализа
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 преобразования
bash tools/poc_differential.sh
- name: Check for invisible Unicode
run: python3 tools/check-invisibles.py .
PIC X(n) — это необработанный байтовый буфер. Он принимает любую последовательность байтов без
валидации. Когда слой Zowe API передаёт JSON в копибук COBOL через
MOVE, невидимые символы Unicode незаметно попадают в запись.