Threat reportMalwareTL-2026-0385
Joomla SEO Spam Injector — Obfuscated PHP Backdoor Hijacking Site Visitors (php.spam-seo.joomla-injector.002)
Joomla SEO Spam Injector (TL-2026-0385), also tracked as Joomla SEO Spam Injector, is a high-severity malware campaign scored CVSS 8.1, first published 2026-04-17. It has no confirmed attribution, affects Joomla! Joomla Core, maps to 18 MITRE ATT&CK techniques (T1008, T1027, T1036), and is covered by 9 detection rules and 28 indicators of compromise.
- CVSS
- 8.1/10High
- CVEs
- 0None referenced
- Techniques
- 18MITRE ATT&CK
- Actors
- 0Not attributed
- Detection rules
- 9SPL · KQL · Sigma
- IOCs
- 28Indicators of compromise
Key facts for TL-2026-0385
- Threat ID
- TL-2026-0385
- Also known as
- Joomla SEO Spam Injector, Joomla Obfuscated PHP Backdoor, php.spam-seo.joomla-injector.002, erpsaz Joomla Injector, saholerp Joomla Loader
- Severity
- HIGH
- CVSS
- 8.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L)
- Status
- ACTIVE
- Category
- MALWARE
- First published
- Last reviewed
- Attribution confidence
- NONE
- Motivation
- FINANCIAL
- Target sectors
- small-business, ecommerce, media, education, nonprofit, hospitality, professional-services
- Target regions
- Global, North America, Europe, Latin America, Asia-Pacific
- Detection rules
- 9
- Indicators of compromise
- 28
Malware and tooling in Joomla SEO Spam Injector
Malware and tooling: joomla-seo-spam-injector, php.spam-seo.joomla-injector.002, curl_exec (PHP libcurl binding)
How Joomla SEO Spam Injector works
Active mass-compromise campaign against outdated Joomla (<5.X) installations deploys a heavily obfuscated PHP loader at the top of index.php. On every page load the backdoor exfiltrates $_SERVER data to C2 cdn.erpsaz.com (primary) or cdn.saholerp.com (fallback) and selects one of three cloaking modes — silent visitor redirect, raw HTML injection, or fake XML-sitemap / HTML served to search crawlers — enabling large-scale SEO poisoning, visitor hijacking, and reputation damage.
TL-2026-0385 tracks an active Joomla compromise campaign documented by Sucuri on 2026-04-16 (Puja Srivastava). The attacker injects a small, heavily obfuscated PHP loader at the very top of the target site's index.php. The loader is structured across four functions — wffn() (bootstrap decoder), mpjy() (27-entry string lookup table), fotr() (traffic cop / cloaking engine), and joog() (HTTP requester and exfiltrator). All sensitive strings (function names explode, base64_decode, curl_exec, domain fragments, URL components, header names) are fragmented into two-character concatenations (for example 'BASE6' . '4_dec' . 'ODE') and/or stored as a tilde-delimited base64 blob decoded into a 27-index lookup table — defeating naive signature scanners that search for literal sinks or complete base64 strings.
On every page load the backdoor serializes data from the PHP $_SERVER superglobal (HTTP_HOST, REQUEST_URI, HTTP_USER_AGENT, REMOTE_ADDR, etc.), base64-encodes it, and issues a curl_exec() GET to http://cdn.erpsaz.com/admin.php?ua=<encoded_fingerprint>. If the primary returns an empty/non-200 response, the loader retries exactly once against http://cdn.saholerp.com/admin.php (a second flag prevents infinite recursion). A third domain, lashowroom.com, is fully decoded at index 25 of the string table but is never referenced by any URL-constructing index call — present as a decoy to waste analyst time.
The fotr() function then branches on the C2 response: (Mode 1) if the body starts with 'http' the loader issues header('Location: ' . $body) and exit()s, silently redirecting the visitor to an attacker-chosen URL; (Mode 2) if the body starts with '##', the prefix is stripped via substr($body, 2) and the remainder is echoed directly into the page, injecting arbitrary spam HTML (e.g. the spam product links reported by the original victim); (Mode 3) if the response length exceeds 90 characters and contains '</urlset>' the loader sets Content-type:text/xml and returns the body as a fake XML sitemap, otherwise if the body contains '<html' it serves the raw HTML — both modes designed to cloak responses to search-engine crawlers and inject keyword-stuffed pages for SEO poisoning.
Because all directives are delivered remotely and the local file footprint is a single obfuscated block, defenders often miss the infection during casual inspection. The same site can be redirecting end users one hour and feeding Google a fake sitemap the next — fully controlled by the C2 operator. This dynamic control makes the infection long-lived and hard to correlate with any one visible symptom. Root cause in every Sucuri case studied has been exploitation of known, patched vulnerabilities in Joomla core or third-party extensions on installations running branches older than 5.X (which is end-of-life).
C2 infrastructure resolves to 91.239.78.37 (AS6698 VIRTUALSYSTEMS, RIPE, Poland/Ukraine) for cdn.erpsaz.com and 195.26.86.16 (AS43641 SOLLUTIUM-NL, RIPE, Ukraine/Poland) for cdn.saholerp.com. Both parent zones (erpsaz.com, saholerp.com) use Cloudflare nameservers, masking origin at the DNS layer but revealing authoritative zones directly on the sub-CDN hostnames. Sucuri tracks the family under signature php.spam-seo.joomla-injector.002 (original signature lineage dates to 2019; this 2026 variant is the first with the fragmented-string + tilde-delimited-table obfuscation pattern).
Impact is financial and reputational: compromised domains push traffic and link equity to attacker-promoted products, search engines demote or de-index cloaked pages, browsers may flag the site via Safe Browsing, and ad fraud downstream is common. The backdoor does not itself include the spam content — it is a pure remote loader, so removal requires deleting the injected block from index.php, resetting all admin credentials, and completing a full integrity scan of every PHP file on the host to locate any secondary implants.
MITRE ATT&CK techniques used in TL-2026-0385
Command and Control
T1008 Fallback Channels; T1071 Application Layer Protocol; T1102 Web Service; T1132 Data Encoding; T1568 Dynamic Resolution
Defense Evasion
T1027 Obfuscated Files or Information; T1036 Masquerading; T1140 Deobfuscate/Decode Files or Information
Execution
T1059 Command and Scripting Interpreter
Discovery
T1082 System Information Discovery
Initial Access
T1189 Drive-by Compromise; T1190 Exploit Public-Facing Application
Impact
T1491 Defacement; T1496 Resource Hijacking
Persistence
T1505 Server Software Component
Resource Development
T1583 Acquire Infrastructure; T1608 Stage Capabilities
Reconnaissance
Affected products and versions in Joomla SEO Spam Injector
- Joomla! — Joomla Core
Vulnerable versions: 3.X (EOL); 4.X (EOL); any pre-5.X installation
Fixed in: 5.X current branch (only via upgrade, not patch) - Joomla! Extensions Directory (JED) — Third-party Joomla extensions
Vulnerable versions: any unpatched extension with known CVE used as initial access vector
Fixed in: latest vendor-released version of each installed extension
Remediation for Joomla SEO Spam Injector
Patches
- Upgrade Joomla core to the latest 5.X release
- Apply the latest security updates for every installed Joomla extension
- Upgrade PHP to a supported branch (8.2+)
Immediate actions
- Remove the obfuscated PHP block injected at the top of Joomla index.php and any cloned copies across the document root
- Block outbound DNS/HTTP to cdn.erpsaz.com, cdn.saholerp.com, and lashowroom.com at the perimeter and web-server egress
- Block outbound connections to 91.239.78.37 and 195.26.86.16 at the firewall
- Force rotate all Joomla administrator credentials, database passwords, FTP/SFTP keys, and hosting control-panel logins
- Invalidate all active Joomla sessions and regenerate session-secret configuration values
- Run a full file-integrity scan of every .php file on the host to locate secondary backdoors, uploaders, or dropped shells
- Submit the domain for re-review in Google Search Console once cleaned to begin reversing de-indexing
Workarounds
- If immediate upgrade is not possible, place the /administrator directory behind HTTP basic auth or IP allow-list
- Enable Joomla's built-in reCAPTCHA on the admin login form
- Disable PHP functions not required by Joomla (exec, shell_exec, system, passthru) via disable_functions in php.ini
- Block outbound egress from the web server except for explicit allow-listed update endpoints
Longer-term hardening
- Upgrade Joomla to the currently supported 5.X branch — all 3.X and 4.X branches are end-of-life and silently missing security patches
- Deploy a web application firewall (Sucuri, Cloudflare, ModSecurity + CRS) with virtual patching for known Joomla CVEs and outbound C2 egress filtering
- Enable Joomla two-factor authentication for every administrator account and restrict /administrator by IP allow-list
- Set file permissions baseline: directories 755, PHP files 644, never world-writable
- Audit all installed Joomla extensions monthly; remove unused, abandoned, or untrusted extensions
- Deploy host-based file-integrity monitoring (OSSEC, Wazuh, Tripwire) on the document root with alert on any change to index.php, configuration.php, or template files
- Route all outbound traffic from the web tier through an egress proxy and alert on any GET to URIs ending in /admin.php to unknown CDN-named subdomains
Weaknesses (CWE) in Joomla SEO Spam Injector
Timeline of Joomla SEO Spam Injector
- Sucuri Labs publishes signature php.spam-seo.joomla-injector.002, first generation of the Joomla SEO spam injector family.
- New 2026 variant observed in Sucuri incident response queue, introducing two-character fragmented function names and the 27-entry tilde-delimited base64 lookup table as primary obfuscation technique.
- Joomla site owner reports suspicious product links appearing on their ecommerce pages that were never added to the catalog; pages serve different content to search crawlers than to browsers.
- Sucuri Security Analyst Puja Srivastava begins deobfuscation of the injected PHP loader; identifies four-function architecture (wffn, mpjy, fotr, joog) and multi-mode cloaking logic.
- C2 infrastructure confirmed: cdn.erpsaz.com (primary, 91.239.78.37 / AS6698), cdn.saholerp.com (fallback, 195.26.86.16 / AS43641); lashowroom.com identified as decoy string never used in URL construction.
- Sucuri publishes full technical writeup of the Joomla SEO Spam Injector campaign on blog.sucuri.net, including IOCs, cloaking modes, and remediation steps.
- Threadlinqs Intelligence publishes TL-2026-0385 with full MITRE mapping, expanded IOC set, and detection rules (SPL, KQL, Sigma) derived from the Sucuri signature lineage.
- As of 2026-05-29, this Sucuri-documented Joomla SEO-spam injector campaign remains an active concern: outdated pre-5.X Joomla sites are still being mass-compromised in 2026 (e.g. SEO-spam via actively-exploited Astroid CVE-2026-21628) and no takedown, sinkhole, or arrest has hit its erpsaz/saholerp C2. Specific C2 domains are expected to rotate, so the exact infra may go quiet, but the technique and remote-loader family stay live.
Sources cited for Joomla SEO Spam Injector
- Sucuri Blog: Joomla SEO Spam Injector — Obfuscated PHP Backdoor Hijacking Site Visitors
- Sucuri Labs Signature: php.spam-seo.joomla-injector.002
- Joomla! 5.X Downloads and Upgrade Information
- Joomla! Security Announcements
- MITRE ATT&CK: Server Software Component — Web Shell (T1505.003)
- MITRE ATT&CK: Obfuscated Files or Information — Encrypted/Encoded File (T1027.013)
- MITRE ATT&CK: Obfuscated Files or Information — Command Obfuscation (T1027.010)
- MITRE ATT&CK: Application Layer Protocol — Web Protocols (T1071.001)
- MITRE ATT&CK: Data Encoding — Standard Encoding (T1132.001)
- MITRE ATT&CK: Resource Hijacking (T1496)
- MITRE ATT&CK: Exploit Public-Facing Application (T1190)
- CWE-506: Embedded Malicious Code
- CWE-94: Improper Control of Generation of Code (Code Injection)
- CWE-601: URL Redirection to Untrusted Site ('Open Redirect')
- Google Search Central: Hacked sites — cloaking
Detection coverage for TL-2026-0385
As of 2026-04-17, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-0385 across Splunk SPL, Microsoft KQL and Sigma, covering 28 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.