
CVE-2026-13233 (Drupal OpenAI Provider, SA-CONTRIB-2026-053): SSRF через URL ответа / чтение локальных файлов. Недоверенный источник, не промпт. Безопасный воспроизводитель + обнаружения. Исправлено в версиях 1.1.1/1.2.2.
Ненадёжный upstream: провайдер, который загрузил URL, указанный в его собственном ответе.
Drupal OpenAI Provider (ai_provider_openai) · SSRF (CWE-918) · CVE-2026-13233 · SA-CONTRIB-2026-053
Статус: Скоординированное раскрытие завершено (2026-07-10). Сообщено конфиденциально Команде безопасности Drupal, исправлено и опубликовано как CVE-2026-13233 / уведомление SA-CONTRIB-2026-053 (оценка Умеренно критично). Автор указан как обнаружитель и разработчик исправления.
Исследование классического дефекта авторизации/проверки входных данных в «точке подключения» ИИ: провайдер
генерации изображений ИИ загружал URL, содержащийся в ответе вышестоящего API, используя
функцию общего назначения без разрешённого списка схем. В развёртываниях, где настроенный upstream
не является доверенным по умолчанию (собственная конечная точка / прокси / самостоятельный шлюз / скомпрометированное
реле), ответ мог указывать серверу на file:// или внутренний адрес.
Недоверенный ввод, достигающий стока, — это URL ответа upstream, а не запрос пользователя.
file:// чтение локальных файлов; внутренний анализ автора
также отнёс это к CWE-73 / CWE-441.3.1 / условно 5.3
(Средний); предыдущие 6.5 / 7.4 отозваны, и средняя оценка это подтвердила.ai_provider_openai) < 1.1.1 и 1.2.0–1.2.1 (проверено 1.2.1) на Drupal core 11.2Вся проверка проводилась в собственной, сетевой изолированной песочнице против имитации upstream. Реальный API OpenAI никогда не вызывался. Оракулы утечки были только синтетические.
Подтверждено (динамически продемонстрировано):
settings.php подтверждено sha256 побайтовым совпадением (35,182 Б) — содержимое никогда не выводилось; учётные данные БД
поэтому находятся в области действия.Не проверено (явно не заявлено):
Не затронуто: по умолчанию api.openai.com через TLS. Настройка host контролируется администратором / config-sync / развёртыванием
— атакующий без прав администратора во время выполнения не может её изменить.
URL ответа передавался функции общего назначения, которая учитывает все зарегистрированные обёртки потоков PHP
(file, php, http, data, phar, …). response_format по умолчанию равен url, поэтому уязвимая
ветвь — это путь по умолчанию. file:// является обёрткой файловой системы по умолчанию в PHP и не защищена
allow_url_fopen (ранее заявление «требует allow_url_fopen» было неверным и отозвано).
Исправляйте примитив, а не только место вызова:
http/https перед запросом; отключите перенаправления (30x может перенаправить на file://).file://…, http://169.254.169.254/… и перенаправление 302→file://
должны быть отклонены.Полное направление: docs/fix-direction.md.
.
├── README.md # this file (English, canonical)
├── README_ja.md # Japanese mirror
├── SECURITY.md # reporting policy + responsible-disclosure disclaimer
├── .gitignore # blocks secrets / primary evidence from being committed
├── docs/
│ └── fix-direction.md # root-cause fix + variant hunt + minimal-diff sketch (EN)
├── reproducer/ # SAFE reproducer only (sandbox, mock upstream, benign oracle)
│ ├── README.md # how to stand up the network-isolated sandbox
│ ├── verdict.md # what "success" means: raw-byte match + 200-vs-403 + exit codes
│ ├── mock-openai-server.py # benign mock; default happy-path PNG, ssrf_demo → file:///etc/hostname only
│ └── docker-compose.yml # TEMPLATE: isolated Drupal sandbox + mock (you add the vulnerable target)
├── detections/
│ ├── README.md
│ ├── sigma/web-egress-to-internal-after-imagegen.yml
│ ├── sigma/php-sensitive-file-open.yml
│ ├── sentinel/imagegen-egress-correlation.kql
│ └── splunk/imagegen-content-type-mismatch.spl
└── timeline.md # disclosure timeline (single source of truth)
Документация сейчас на японском (
.ja.md); английские канонические переводы — в планах. Из этого репозитория изъяты: уязвимые нагрузки и любое готовое PoC чтения файлов. Публичныйreproducer/демонстрирует механизм дефекта на имитации с использованием единственного безвредного оракула (/etc/hostname) — без чтения произвольного пути, без захватаsettings.php, без IMDS. Это не оружие против живых сайтов. Обновитесь до 1.1.1 / 1.2.2.
Цель: позволить исследователю подтвердить класс дефекта без предоставления эксплойта для живой цели или раскрытия секретов. Всё работает офлайн.