Добавить в корзинуПозвонить
Найти в Дзене
The Codeby

Один POST-параметр — и flat-file CMS у вас в руках

Представьте: CMS, где нет базы данных. Конфигурация, учётные записи, контент, настройки плагинов — всё хранится в YAML-файлах на диске. Теперь представьте, что неаутентифицированный атакующий может записать произвольный файл в любой каталог этой системы. Не «потенциально», а буквально одним HTTP-запросом. Именно это делает CVE-2026-42608 в Grav CMS — flat-file движке на PHP с 14 500+ звёзд на GitHub и порядка 36 000 публично доступных инстансов по данным ZoomEye. 🔍 Корень проблемы — компонент FormFlash, который сохраняет данные форм между HTTP-редиректами. Он принимает идентификатор сессии из POST-параметра __form-flash-id и использует его напрямую при построении пути к директории записи. Значение конкатенируется со строкой tmp://forms/ без проверки на символы вроде ../. Подставил traversal-последовательность — вышел за границы временной папки и пишешь куда хочешь. Разработчики обращались с этим параметром как с доверенным: «ну строка из POST, она же не в SQL попадает». В классичес

Один POST-параметр — и flat-file CMS у вас в руках

Представьте: CMS, где нет базы данных. Конфигурация, учётные записи, контент, настройки плагинов — всё хранится в YAML-файлах на диске. Теперь представьте, что неаутентифицированный атакующий может записать произвольный файл в любой каталог этой системы. Не «потенциально», а буквально одним HTTP-запросом.

Именно это делает CVE-2026-42608 в Grav CMS — flat-file движке на PHP с 14 500+ звёзд на GitHub и порядка 36 000 публично доступных инстансов по данным ZoomEye.

🔍 Корень проблемы — компонент FormFlash, который сохраняет данные форм между HTTP-редиректами. Он принимает идентификатор сессии из POST-параметра __form-flash-id и использует его напрямую при построении пути к директории записи. Значение конкатенируется со строкой tmp://forms/ без проверки на символы вроде ../. Подставил traversal-последовательность — вышел за границы временной папки и пишешь куда хочешь.

Разработчики обращались с этим параметром как с доверенным: «ну строка из POST, она же не в SQL попадает». В классической архитектуре с СУБД это могло бы сойти. Но в flat-file системе запись файла = модификация конфигурации = контроль над приложением.

⚡ Что получает атакующий на практике:

• Запись в user/config/ — изменение поведения сайта и плагинов через инъекцию YAML-конфигурации

• Запись в user/accounts/ — порча или подмена учётных данных, хешей паролей, 2FA-секретов

• Запись в user/pages/ — инъекция контента, потенциальный SSTI через Twig-шаблоны

CVSS 8.8 (HIGH), ноль привилегий, CISA оценивает Technical Impact как total. Эксплуатация автоматизируема — достаточно одного POST-запроса к любой странице с формой. А формы есть почти везде: контактная страница, /admin/login, регистрация.

🧩 Ключевой фрагмент уязвимого кода выглядит обманчиво просто. Метод __construct() класса FormFlash берёт session_id из POST и склеивает с путём без вызова basename() или regex-валидации. Одна пропущенная проверка — и вся файловая система webroot открыта для записи.

По классификации MITRE это CWE-22 (Improper Limitation of a Pathname). По OWASP Top 10 — одновременно A01 (Broken Access Control) и A03 (Injection). Редкий случай, когда одна строка кода попадает сразу в две категории критичных уязвимостей.

📌 Если вы работаете с Grav или проводите аудит flat-file CMS — в полной статье разобран весь путь: от уязвимой строки PHP до рабочего HTTP-запроса, с маппингом на ATT&CK и контекстом предыдущих CVE движка.

https://codeby.net/threads/grav-cms-uyazvimost-path-traversal-0-day-v-formflash-bez-autentifikatsii.93718/