Аутентифицированная загрузка произвольных файлов, приводящая к удалённому выполнению кода. Технический анализ и контролируемое воспроизведение CVE-2026-38526 в Webkul Krayin CRM 2.2.x.
Аутентифицированная загрузка произвольных файлов, приводящая к удалённому выполнению кода. Технический анализ и контролируемое воспроизведение CVE-2026-38526 в Webkul Krayin CRM 2.2.x.
CVE-2026-38526 — это уязвимость аутентифицированной загрузки произвольных файлов, затрагивающая Webkul Krayin CRM 2.2.x.
Уязвимая функциональность доступна через конечную точку загрузки TinyMCE приложения:
POST /admin/tinymce/upload
Приложение недостаточно ограничивает тип файла, который можно загрузить. Аутентифицированный пользователь может отправить файл с исполняемым на стороне сервера расширением, например .php. Приложение сохраняет загруженный файл и возвращает его доступный URL.
Когда развёртывание допускает выполнение PHP из места загрузки, загруженный файл впоследствии может быть запрошен через веб-сервер, что приводит к удалённому выполнению кода в контексте процесса веб-приложения.
Опубликованная запись CVE оценивает уязвимость как CVSS 3.1: 9.9 (Critical).
Этот репозиторий содержит мой собственный технический анализ и контролируемое воспроизведение уязвимости.
Уязвимость уже была публично раскрыта под идентификатором CVE-2026-38526. Данная работа не претендует на открытие уязвимости. Целью этого исследования было понять уязвимую реализацию, воспроизвести путь эксплуатации в контролируемой среде и изучить условия, которые превращают проблему загрузки файлов в удалённое выполнение кода.
Уязвимость также использовалась в машине Hack The Box GCSB 2026 Nexus, что предоставило практическую среду для изучения этой проблемы.
Продукт: Webkul Krayin CRM Затронутые версии: 2.2.x Уязвимость: Загрузка произвольных файлов Итоговое воздействие: Удалённое выполнение кода Аутентификация: Требуется Вектор атаки: Сеть CWE: CWE-434 — Неограниченная загрузка файлов опасного типа CVSS: 9.9 Critical CVE: CVE-2026-38526
Уязвимая функциональность обрабатывается:
/admin/tinymce/upload
Конечная точка принимает загруженный файл через параметр file. Соответствующая логика приложения формирует имя сохраняемого файла из исходного имени файла и сохраняет его исходное расширение.

Такое поведение важно, поскольку приложение не просто принимает загруженный объект; оно сохраняет контролируемое злоумышленником исполняемое расширение и делает результирующий объект доступным через механизм хранения приложения.
Основная проблема — недостаточная проверка загружаемых файлов на стороне сервера.
Приложение использует исходное расширение, предоставленное клиентом, при формировании имени сохраняемого файла. Отсутствует достаточно строгий список разрешённых типов, предотвращающий попадание исполняемых типов файлов на уровень хранения.
Соответствующий поток:

Использование сгенерированного имени файла не решает основную проблему.
Например, преобразование shell.php в сгенерированное имя файла, такое как .php, не делает загруженный файл безопасным, если сервер продолжает интерпретировать файлы .php как исполняемый код PHP.
Неограниченная загрузка не означает автоматически удалённое выполнение кода.
Путь выполнения зависит от того, как сервер обрабатывает загруженный файл.
В уязвимом сценарии развёртывания цепочка выглядит так:

Если выполнение PHP отключено для каталога загрузки, прямой путь к RCE можно предотвратить, даже если основная слабость загрузки произвольных файлов остаётся.
wget:
wget https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/upload.py
wget https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/marker.php
curl:
curl -LO https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/upload.py
curl -LO https://raw.githubusercontent.com/Ish3ng0m4/CVE-2026-38526-KrayinCRM/main/poc/marker.php
2. Поместите файлы в
poc/
├── upload.py
└── marker.php
3. Создайте окружение Python и установите зависимость
python3 -m venv .venv
source .venv/bin/activate
pip install requests
4. Сделайте PoC исполняемым
chmod +x poc/upload.py
6. Запустите его
python3 poc/upload.py \
--url http://[Lab_IP:PORT] \
--email [email protected] \
--password 'YOUR_PASSWORD'
Эксплуатация требует аутентифицированной учётной записи, имеющей доступ к уязвимой функциональности.
В общих чертах:
Результирующий контекст выполнения определяется базовым развёртыванием. В типичном развёртывании на Linux это может быть служебная учётная запись веб-сервера, например:
www-data
Это не даёт автоматически привилегий root в операционной системе. Дальнейшее воздействие зависит от разрешений и конфигурации скомпрометированной среды.
Уязвимое поведение можно свести к трём важным операциям.
Получение загруженного файла
$file = request()->file('file');
Приложение получает файл, предоставленный клиентом.
Сохранение расширения, контролируемого клиентом
$filename = md5($file->getClientOriginalName().time())
.'.'.$file->getClientOriginalExtension();
Само имя файла изменяется, но исходное расширение сохраняется. Это важное различие: рандомизация имени файла не является проверкой типа файла.
Сохранение и предоставление файла
$path = $file->storeAs($this->storagePath, $filename);
return [
'file' => $path,
'file_name' => $file->getClientOriginalName(),
'file_url' => Storage::url($path),
];
Приложение сохраняет файл и предоставляет клиенту его URL.
Успешная эксплуатация может предоставить злоумышленнику выполнение кода с привилегиями веб-приложения.
В зависимости от развёртывания это может позволить злоумышленнику:
Читать файлы приложения
Доступ к конфигурации приложения
Получить учётные данные базы данных или другие секреты
Изменять данные приложения
Развернуть дополнительный вредоносный код
Переместиться к другим системам, доступным со скомпрометированного хоста
Попытаться выполнить дальнейшее повышение привилегий
Фактическое воздействие зависит от привилегий скомпрометированного процесса приложения и конфигурации безопасности базовой системы.