If you've ever cleaned a compromised WordPress site only to watch the malware reappear within hours, you now know exactly what that feels like at an architectural level. Security researchers at Sucuri have dissected a WordPress intrusion in which the attackers deployed multiple redundant persistence mechanisms designed to regenerate the final malicious payload even after partial cleanup — a design Sucuri describes as a "self-healing mesh." The malware has been codenamed SC, after the distinctive SC_ markers embedded in the injected content.
This matters to every defender running WordPress — which, given that WordPress powers a massive share of the public web, is effectively everyone with a digital presence. The critical lesson from the SC campaign is this: removing the visible payload is not remediation. If you delete the injected file but leave the database-resident loader and the shared-memory rehydration logic intact, the malware reconstructs itself without the attacker ever touching your site again. No new exploitation. No new phishing lure. It simply grows back.
This post breaks down the SC persistence architecture from a defender's perspective, provides detection content your SOC can deploy today, and walks through a complete eradication methodology that accounts for every layer of the mesh.
Technical Analysis
What SC Is
SC is not a vulnerability — it is a post-exploitation persistence framework deployed after an initial compromise (typically via vulnerable plugins, stolen credentials, or abused file-upload functionality). There is no CVE associated with this activity; the tradecraft is the story. Once the attackers achieve initial code execution, they implant multiple independent persistence mechanisms that cross-monitor and rebuild one another:
-
File-based persistence — Malicious PHP code is written into legitimate-looking locations within the WordPress directory tree: core files,
wp-content/uploads/, theme files, or innocuously-named files likeclass-wp-cache.phporwp-statistics.php. TheSC_string markers appear in the injected content, which is the primary forensic artifact that gave the malware its name. -
Database-resident persistence — Malicious code is stored in the WordPress database itself (commonly in
wp_optionsrows, injected into posts, or hidden in autoloaded options). Because most file-integrity scanners ignore the database, this layer survives standard file cleanup. A loader in the file system reads the payload from the database and re-executes it; conversely, a database-backed routine can rewrite deleted files. -
Shared memory persistence — This is the most novel and least commonly hunted layer. Payload components are staged in shared memory segments (
/dev/shmon Linux, or SysV IPC shared memory). Because these artifacts live in RAM-backed filesystems rather than the document root, they survive file-system scans, file deletions, and even some naive "restore from backup" operations. A watcher process or a small on-disk stub can reconstitute the full payload from the shared-memory copy after cleanup wipes the web root.
Why This Design Defeats Standard IR Playbooks
The mesh is deliberately redundant. Each persistence layer contains enough logic to regenerate the others:
- Delete the infected files → the database loader (triggered on the next page load via an autoloaded option or injected theme hook) rewrites them, pulling content from shared memory.
- Clean the database → the file-based stub re-injects the malicious rows.
- Kill the watcher process → the next legitimate web request re-spawns it, because the trigger is embedded in code that executes on every request.
This is the defining characteristic of the threat: cleanup must be atomic and comprehensive, or it fails completely. Partial remediation is functionally equivalent to no remediation — it just gives you a false sense of closure while the site remains attacker-controlled.
Exploitation Status
- Status: Confirmed in-the-wild. Sucuri documented this from a live incident response engagement, not a lab sample.
- Attribution: No specific threat actor has been publicly attributed; the final payload is consistent with monetization-oriented WordPress compromises (SEO spam, redirect injection, credential harvesting, downstream malware delivery).
- CISA KEV: Not applicable — no CVE is involved. This is tradecraft, not a patchable flaw.
- Initial access vectors: Consistent with the broader WordPress threat landscape — vulnerable/outdated plugins and themes, weak or reused administrator credentials, exposed
xmlrpc.phpbrute forcing, and abused file upload handlers.
What Defenders Should Assume
If you find one SC artifact, assume all three persistence layers are present until proven otherwise. Treat the host, the database, and the application as a single compromised unit.
Detection & Response
The detections below target the observable behaviors of the SC mesh: PHP code executing shells or downloading payloads, PHP artifacts dropped into directories that should never contain executable code, database options carrying embedded PHP, and artifacts in shared memory.
Sigma Rules
---
title: PHP-FPM or Web Server Spawning Shell or Downloader
tid: 3f7a1c94-2e85-4b61-a9d3-8c4f5e6a7b01
status: experimental
description: Detects PHP-FPM, Apache, or Nginx worker processes spawning shells, downloaders, or encoding utilities — consistent with SC backdoor watcher and rehydration logic executing under the web server context.
references:
- https://thehackernews.com/2026/10/wordpress-backdoor-rebuilds-itself.html
- https://attack.mitre.org/techniques/T1059/
- https://attack.mitre.org/techniques/T1505/003/
author: Security Arsenal
date: 2026/05/20
tags:
- attack.execution
- attack.persistence
- attack.t1059
- attack.t1505.003
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentImage|endswith:
- '/php-fpm'
- '/php'
- '/apache2'
- '/httpd'
- '/nginx'
selection_child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- '/curl'
- '/wget'
- '/base64'
- '/python'
- '/perl'
condition: selection_parent and selection_child
falsepositives:
- WordPress plugins invoking curl for legitimate API calls (review command line for external payload fetches)
- Backup or migration plugins spawning shell utilities
level: high
---
title: Executable PHP Artifact Created in WordPress Uploads or Shared Memory
tid: 8b2e4d15-7a3c-4f89-b6d1-5e9a2c7f3042
status: experimental
description: Detects creation of PHP files in wp-content/uploads (which should never contain executable code) or in /dev/shm, consistent with SC file-layer implants and shared-memory payload staging.
references:
- https://thehackernews.com/2026/10/wordpress-backdoor-rebuilds-itself.html
- https://attack.mitre.org/techniques/T1505/003/
author: Security Arsenal
date: 2026/05/20
tags:
- attack.persistence
- attack.t1505.003
- attack.defense_evasion
logsource:
category: file_event
product: linux
detection:
selection_uploads:
TargetFilename|contains: '/wp-content/uploads/'
TargetFilename|endswith:
- '.php'
- '.phtml'
- '.phar'
- '.php5'
- '.php7'
selection_shm:
TargetFilename|startswith: '/dev/shm/'
condition: 1 of selection_*
falsepositives:
- Rare legitimate plugin install operations writing PHP to uploads (validate against plugin install logs)
- Legitimate applications using /dev/shm for caching (correlate with web server process context)
level: high
---
title: Suspicious PHP eval or Encoding Patterns in Web Request Logs
tid: c4d9f827-1b6a-4e52-9034-6f8d2a5b17c3
status: experimental
description: Detects HTTP requests to WordPress sites containing eval, base64_decode, gzinflate, or SC_ marker patterns — indicative of interaction with injected SC persistence stubs and webshell-style loaders.
references:
- https://thehackernews.com/2026/10/wordpress-backdoor-rebuilds-itself.html
- https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/05/20
tags:
- attack.initial_access
- attack.t1190
- attack.t1027
logsource:
category: webserver
detection:
selection_uri:
cs-uri-query|contains:
- 'eval('
- 'base64_decode'
- 'gzinflate'
- 'str_rot13'
- 'SC_'
- 'assert('
selection_method:
cs-method: 'POST'
condition: selection_uri or (selection_method and selection_uri)
falsepositives:
- Security scanners and WAF self-tests
- Legitimate admin-ajax operations with encoded parameters (rare — validate source IP against admin ranges)
level: medium
KQL — Microsoft Sentinel / Defender
The query below hunts Linux Syslog/CEF-ingested web tier telemetry for PHP spawning shells and for writes to high-risk paths. It assumes your WordPress hosts forward process and file audit data (auditd/Sysmon-for-Linux) into Sentinel.
// Hunt 1: PHP/web server spawning shells or downloaders
Syslog
| where TimeGenerated > ago(7d)
| where Facility == 'user' or Facility == 'daemon'
| where ProcessName in~ ('php-fpm', 'php', 'apache2', 'httpd', 'nginx', 'sh', 'bash')
| where SyslogMessage has_any ('/bin/sh', '/bin/bash', 'curl ', 'wget ', 'base64 -d', 'eval(', 'SC_')
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated desc;
// Hunt 2: File artifacts in uploads, tmp, or shared memory with PHP extensions
// (Requires Defender for Endpoint on Linux or auditd file-watch ingestion)
DeviceFileEvents
| where TimeGenerated > ago(7d)
| where FolderPath has_any ('/wp-content/uploads/', '/dev/shm/', '/tmp/', '/var/tmp/')
| where FileName endswith '.php' or FileName endswith '.phtml'
| project TimeGenerated, DeviceName, FolderPath, FileName, InitiatingProcessCommandLine, InitiatingProcessAccountName
| order by TimeGenerated desc;
// Hunt 3: MySQL/MariaDB queries writing suspicious autoloaded options (SC database layer)
// (Requires database audit log ingestion, e.g., MariaDB audit plugin -> Syslog)
Syslog
| where TimeGenerated > ago(7d)
| where SyslogMessage has_all ('wp_options', 'autoload')
| where SyslogMessage has_any ('base64_decode', 'eval', 'gzinflate', 'create_function', 'SC_')
| project TimeGenerated, Computer, SyslogMessage
| order by TimeGenerated desc;
Velociraptor VQL
This artifact hunts a WordPress host for the SC triad: recently created PHP files in non-code directories, shared memory artifacts, and PHP processes with suspicious command lines. Run it as a hunt across your WordPress fleet.
-- SC Backdoor Triage: uploads PHP files, /dev/shm artifacts, suspicious PHP processes
-- Part 1: PHP files planted in uploads or temp locations
SELECT FullPath, Size, Mtime, Ctime,
upload(file=FullPath) AS Sample
FROM glob(globs=[
'/var/www/**/wp-content/uploads/**/*.php',
'/var/www/**/wp-content/uploads/**/*.phtml',
'/tmp/*.php*',
'/var/tmp/*.php*',
'/dev/shm/**'
])
WHERE Mtime > now() - 2592000
-- Part 2: PHP processes executing from unusual paths or with shell-like command lines
SELECT Pid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE (Name =~ 'php' OR Exe =~ 'php')
AND (CommandLine =~ 'eval|base64|curl|wget|/dev/shm|/tmp/|uploads'
OR Exe =~ '/tmp|/dev/shm')
-- Part 3: Search recently modified core/theme files for SC markers
SELECT FullPath, Mtime,
read_file(filename=FullPath, length=4096) AS Header
FROM glob(globs=[
'/var/www/**/wp-content/themes/**/*.php',
'/var/www/**/wp-includes/*.php',
'/var/www/**/wp-content/mu-plugins/**/*.php'
])
WHERE Mtime > now() - 604800
AND read_file(filename=FullPath, length=4096) =~ 'SC_|base64_decode|eval\(|gzinflate'
Remediation & Verification Script
Run the following on the compromised host (as root or with sudo). It inventories all three SC persistence layers. This script is read-only triage — review output before deleting anything.
#!/bin/bash
# SC Backdoor Triage — Security Arsenal IR
# Usage: sudo bash sc_triage.sh /var/www/html
WEBROOT="${1:-/var/www/html}"
REPORT="/root/sc_triage_$(date +%Y%m%d_%H%M%S).txt"
echo "=== SC Backdoor Triage Report: $(hostname) $(date) ===" | tee "$REPORT"
# 1. Hunt for SC_ markers across the web root
echo -e "\n[1] Files containing SC_ markers:" | tee -a "$REPORT"
grep -rIl --include='*.php' --include='*.phtml' --include='*.inc' 'SC_' "$WEBROOT" 2>/dev/null | tee -a "$REPORT"
# 2. Executable PHP inside uploads (should almost always be zero)
echo -e "\n[2] PHP files in wp-content/uploads:" | tee -a "$REPORT"
find "$WEBROOT" -path '*/wp-content/uploads/*' -name '*.php*' -o -path '*/wp-content/uploads/*' -name '*.phtml' 2>/dev/null | tee -a "$REPORT"
# 3. Recently modified PHP files (last 30 days)
echo -e "\n[3] PHP files modified in last 30 days:" | tee -a "$REPORT"
find "$WEBROOT" -name '*.php' -mtime -30 -printf '%TY-%Tm-%Td %TH:%TM %p\n' 2>/dev/null | sort -r | tee -a "$REPORT"
# 4. Shared memory artifacts (SC RAM-resident layer)
echo -e "\n[4] /dev/shm contents and SysV IPC segments:" | tee -a "$REPORT"
ls -la /dev/shm/ 2>/dev/null | tee -a "$REPORT"
ipcs -m 2>/dev/null | tee -a "$REPORT"
# 5. Obfuscated-code indicators in PHP files
echo -e "\n[5] Files with eval/base64/gzinflate chains (top hits):" | tee -a "$REPORT"
grep -rIlE 'eval\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13)' "$WEBROOT" 2>/dev/null | head -50 | tee -a "$REPORT"
# 6. Cron and systemd persistence
echo -e "\n[6] Cron entries for web user and root:" | tee -a "$REPORT"
for u in root www-data apache nginx $(stat -c '%U' "$WEBROOT" 2>/dev/null); do
echo "--- crontab for $u ---" | tee -a "$REPORT"
crontab -u "$u" -l 2>/dev/null | tee -a "$REPORT"
done
ls -la /etc/cron.d/ /etc/cron.daily/ 2>/dev/null | tee -a "$REPORT"
# 7. Database layer: dump suspicious wp_options (requires wp-cli)
echo -e "\n[7] Suspicious autoloaded wp_options (wp-cli):" | tee -a "$REPORT"
if command -v wp &>/dev/null; then
cd "$WEBROOT" && wp db query \
"SELECT option_id, option_name, LEFT(option_value,120) FROM wp_options \
WHERE option_value LIKE '%base64_decode%' \
OR option_value LIKE '%eval(%' \
OR option_value LIKE '%SC_%' \
OR option_value LIKE '%gzinflate%';" --allow-root 2>/dev/null | tee -a "$REPORT"
else
echo "wp-cli not found — manually query wp_options for base64_decode/eval/SC_ patterns" | tee -a "$REPORT"
fi
# 8. Core file integrity check against official checksums
echo -e "\n[8] WordPress core checksum verification:" | tee -a "$REPORT"
if command -v wp &>/dev/null; then
cd "$WEBROOT" && wp core verify-checksums --allow-root 2>/dev/null | tee -a "$REPORT"
fi
echo -e "\n=== Triage complete. Report saved to $REPORT ==="
Remediation
Because SC is a self-healing mesh, remediation must be executed as a single coordinated operation, not incrementally over days. Follow this sequence:
1. Isolate Before You Clean
- Take the site offline or place it behind a maintenance page/WAF block. Every page load potentially triggers the rehydration logic — cleaning a live site is a race you will lose.
- Snapshot the host and export the database before any changes (forensic preservation — you will want this for root cause analysis).
2. Kill the Runtime Layer First
- Restart PHP-FPM and the web server to flush in-memory watcher processes:
systemctl restart php-fpm httpd(adjust for your stack). - Clear shared memory: remove suspicious artifacts from
/dev/shm/and reviewipcs -moutput for rogue SysV segments (ipcrm -m <shmid>for anything not attributable to a legitimate service).
3. Clean All Layers Atomically
- File system: Remove identified malicious files. Verify core integrity with
wp core verify-checksumsand replace any modified core files withwp core download --force --skip-content. Audit themes and plugins against clean vendor copies — do not trust in-place "cleaning" of premium/proprietary themes. - Database: Remove malicious rows from
wp_options(especially autoloaded entries), audit posts/widgets for injected script tags, and check for rogue admin accounts:wp user list --role=administrator. Cross-reference every admin against HR/owner records. - Uploads directory: Delete any PHP found in
wp-content/uploads/and harden the directory to deny PHP execution (see below).
4. Rotate Everything
The attackers had code execution — assume total credential compromise:
- Rotate all WordPress admin passwords, database credentials (
wp-config.php), API keys, salts/nonces inwp-config.php(this invalidates all sessions), FTP/SFTP/SSH credentials, and hosting panel passwords. - Revoke any stored OAuth tokens or application passwords.
5. Harden Against Re-Compromise
- Deny PHP execution in uploads via
.htaccessor nginx config (location ~* /uploads/.*\.php { deny all; }). - Disable the theme/plugin file editor:
define('DISALLOW_FILE_EDIT', true);inwp-config.php. ConsiderDISALLOW_FILE_MODSfor production sites managed via deployment pipelines. - Update WordPress core, all plugins, and all themes to current versions. Delete (don't just deactivate) unused themes and plugins.
- Deploy a file-integrity monitor (OSSEC, Wazuh, or a WordPress-native scanner) covering both the file system and the
wp_optionstable — most setups only watch files, which is exactly the blind spot SC exploits. - Enforce MFA on all admin accounts and restrict
xmlrpc.phpand/wp-adminby IP where operationally feasible.
6. Root Cause Analysis Is Mandatory
SC is a persistence framework — it tells you nothing about how the attackers got in. If you clean the mesh without closing the initial access vector (a vulnerable plugin, a stolen password, an abused upload handler), you will be re-infected and the cycle restarts. Review web access logs for the window preceding the earliest malicious file's creation timestamp, and identify the entry point before declaring the incident closed.
Key Takeaways for Defenders
- Partial cleanup is failed cleanup. SC's architecture means any surviving layer regenerates the rest. Remediation must cover files, database, and shared memory simultaneously, with the site offline.
- Your database is a file system. The
wp_optionsautoload mechanism is a persistence primitive. If your integrity monitoring doesn't include the database, you have a known blind spot that active adversaries are exploiting today. /dev/shmis in scope for web IR. Shared-memory staging evades every file-system-centric scanner. Add it to your triage checklists and your hunt artifacts.- PHP in uploads is never normal. A zero-tolerance rule for executable code in
wp-content/uploads/— enforced at the web server level, not just by policy — eliminates an entire class of implant locations. - The
SC_marker is your high-fidelity tripwire. Grep for it across files, database dumps, and request logs. It's the cheapest, most reliable detection this campaign offers.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.