SC: Self-Healing WordPress Backdoor Mesh

Blockchain-controlled, multi-point-persistence WordPress backdoor (file + database + System V shared memory) · file-path, content-marker and behavioral detection pack · no published hashes, domains or wallet addresses
Threat
SC WordPress Backdoor Mesh
Severity
HIGH
Type
Web backdoor / self-healing persistence mesh
Access
Compromised WordPress site (initial vector unconfirmed)
Version
v1.0 · 2026-10-02
Author
HuntPack
Confidence
High (TTPs, multi-source) · Low (initial access vector, unknown)
01

Executive Summary

Sucuri documented a WordPress backdoor family it codenamed SC (from the SC_ markers in its injected content): a self-healing mesh that spreads one payload across at least eight interdependent persistence points (files, the WordPress database, and System V shared memory) such that deleting any single component triggers another to rebuild it. The attacker's objective is durable, stealthy, full control of the site: a hidden, fully-privileged administrator; front-end JavaScript injection (skimming on checkout pages); arbitrary additional PHP deployment; and the ability to detect and remove competing security plugins. Command and control runs over roughly twenty public, legitimate Ethereum JSON-RPC gateways rather than a single attacker-owned domain, so no single network block stops it.

The highest-value defensive angle is not matching a hash or a domain: Sucuri published neither. It is (1) file-integrity monitoring on a small, fixed set of WordPress bootstrap paths that legitimate sites almost never touch at runtime (wp-content/db.php, wp-content/advanced-cache.php, wp-content/mu-plugins/*), (2) behavioral detection of the web-server worker process doing things it normally never does (spawning a shell, writing a ZIP, talking to MySQL directly), and (3) a host/database audit for the off-disk persistence (wp_options blob, SysV shared memory segment, cron hooks, database triggers) that no EDR agent can see into.

Defender priority: assume file cleanup alone will fail. Sucuri is explicit that the order of remediation matters: off-disk copies (database option row, shared-memory segment, cron hooks, triggers) must be cleared before or alongside the files, or the very next page load silently restores everything that was just deleted.

02

Source Review & Web Hunter Notes

Five sources were fetched and saved verbatim to SC-SelfHealing-WordPress-Backdoor-Hunt-sources/ for provenance. No fetched page contained any text addressed to an AI agent, any instruction to take an action, or any attempt to alter these build instructions. All five are clean of prompt injection.

TierSourceKey FindingCarry Forward
1Sucuri Blog (primary research, 2026-09-30): 01-sucuri-sc-wordpress.txtFull technical writeup: eight persistence points, self-healing mechanics, backdoor capabilities, off-disk persistence, IOC list, cleanup order, explicit statement of NO hashes/domains/wallets/function names publishedyes, primary source for every technical claim in this pack
1The Hacker News (2026-10-01): 02-thehackernews.txtCorroborates all eight components verbatim from Sucuri; quotes Sucuri researcher Gabriel Barbosa; notes initial access vector is unconfirmed; unrelated wpForo CVE-2026-1581 item in the same article is NOT part of this campaign and was excludedyes, corroboration plus initial-access-unknown caveat
2GBHackers (2026-10-01): 03-gbhackers.txtDerivative security-journalism coverage corroborating the same eight components and C2 mechanism; adds remediation-ordering guidance consistent with Sucuriyes, corroboration only, no new atomic facts
2CyberPress (2026-10-01): 04-cyberpress.txtDerivative coverage; introduces the term "EtherHiding" for the RPC-gateway C2 technique and corroborates capabilities listpartial, used only for the EtherHiding terminology note, not as an independent technical source
3CleanTalk Research (2026-09-10 snapshot): 05-cleantalk.txtCleanTalk's own, separately-labelled "SC" family (their report states explicitly: "It is not a known public acronym"). Overlapping TTPs (db.php / advanced-cache.php / functions.php bounded injection, mu-plugins restoration, SysV shared memory, wp_options persistence, hidden-admin creation) but distinct sample set, distinct filenames, and a distinct naming convention from Sucuri's SC.no, saved for completeness and TTP cross-reference only; not cited for any atomic indicator or fact in this pack to avoid conflating two vendors' independently-named families (per dedupe-by-TTP-not-name discipline)

Per the task's own constraint and Sucuri's explicit disclosure, this pack ships zero hashes, C2 domains, wallet/contract addresses, or PHP function names as hard indicators. Every atomic indicator below is a stable file path/basename quoted directly from a snapshot, or a clearly labelled REPLACE_WITH_ placeholder.

03

Hunt Brief & Attack Chain

Hunt Hypotheses (ordered by fidelity)

#HypothesisMITREFalcon TelemetryExpected FPConfidence
H1A web-server worker process (php-fpm/httpd/nginx) writes or rewrites a WordPress bootstrap drop-in (db.php, advanced-cache.php) at runtime, outside a deploy windowT1505.003File-integrity monitoring on wp-contentlow-medium (caching-plugin activation)high
H2A hidden, dot-prefixed PHP file appears under wp-content where WordPress core/plugin conventions never place oneT1564.001, T1505.003File-integrity monitoring on wp-contentlowhigh
H3A new PHP file is written to wp-content/mu-plugins at runtime; mu-plugins almost never changes outside a deliberate deployT1505.003File-integrity monitoring on mu-pluginslowhigh
H4The web-server worker process spawns an interactive shell: a PHP process has no legitimate reason to exec sh/bashT1505.003, T1059.004ProcessRollup2 parent/childlowhigh
H5The active theme's functions.php is rewritten by the web worker (the SC_ bounded-block re-injection) rather than by an authenticated admin's Theme Editor saveT1505.003File-integrity monitoring + correlation to WP audit loghighmedium
H6A randomly-named ZIP restore bundle is written under wp-content/uploads or a theme folderT1505.003, T1027ZipFileWrittenmedium (legit backup plugins)medium
H7The web-server worker initiates outbound HTTPS to one of roughly twenty public Ethereum RPC gateways, polling for C2 instructionsT1102.002, T1071.001NetworkConnectIP4 / DnsRequest, joined to a tenant RPC watchlisthigh (shared legitimate infra)low without a watchlist join
H8System cron invokes wp-cron.php on a schedule that correlates with a randomized cron-hook name registered in wp_options (visible only via native DB audit, not Falcon)T1053.003ProcessRollup2 (baseline only) + native wp_options auditvery high (this is also a standard hardening practice)low (Falcon side), supports a native hunt

Attack Chain

StepActionTelemetryHunt Angle
1Initial access (unconfirmed; Sucuri does not state the vector for this sample)WAF / access logsPatch cadence review; the campaign's own prevention note says most of Sucuri's cases exploit already-fixed vulnerabilities
2Drop .user.ini setting auto_prepend_file + a visible PHP shim + a hidden dot-prefixed loaderFile-integrity monitoringQ1, Q2
3Loader rebuilds the fake plugin into mu-plugins; injects db.php, advanced-cache.php, and the theme's functions.phpFile-integrity monitoringQ3, Q4, Q5
4Backdoor payload runs on every request: hides itself, fingerprints the site, creates/forges a hidden administratorNative WP audit (not Falcon-visible)Section 7
5Payload polls public Ethereum RPC gateways for instructions; receives JS/PHP to deploy or a list of security plugins to disableNetworkConnectIP4 / DnsRequestQ10, Q11
6Payload writes itself off-disk (wp_options blob, SysV shared memory, randomized cron hooks, DB triggers in related variants) so file cleanup alone failsNot Falcon-visible; native DB/host audit onlySection 7
7Capability actions: front-end JS injection (skimming), additional PHP deployment, security-plugin removal, shell spawn for operator convenienceProcessRollup2Q7, Q9
04

Consolidated IOC Table

TypeValueConfidenceActionContext
filenamedb.phphighdetectWordPress bootstrap drop-in; stable name required by WP core itself; verify content for an SC_ marker before escalating
filenameadvanced-cache.phphighdetectEarliest-loading drop-in; stable name required by WP core when WP_CACHE is set
filename.user.inimediumdetectCommon filename; suspicious only when combined with an auto_prepend_file directive pointing at a hidden dot-prefixed loader
path (rotates)wp-content/mu-plugins/hyper-engine-kit.phpmediumdetectObserved sample path; Sucuri states the name varies per site; starting hunt term, not a guaranteed match
path (rotates)wp-content/plugins/hyper-engine-kit/hyper-engine-kit.phpmediumdetectDuplicate redundant copy of the payload; name varies per site
content-markerSC_-prefixed begin/end guard block in db.php/advanced-cache.phphighhuntNot Falcon-queryable (file content); use native grep/WP malware scanner
content-markerBounded begin/end block appended to active theme functions.phphighhuntNot Falcon-queryable (file content)
behavioralwp_options row (random name) holding an oversized gzip+base64 blobhighenrichOff-disk persistence; native DB audit only
behavioralSystem V shared-memory segment (fixed numeric key) holding readable PHPhighenrichOff-disk persistence; ipcs -m audit only, not Falcon-visible
behavioralHidden administrator with capabilities under the default capabilities meta key, absent from the user-list UIhighenrichNative WP/DB audit only
sha256REPLACE_WITH_SHA256n/adetectNo hashes published as of this pack's research date; populate if a sample is recovered
domain (watchlist)REPLACE_WITH_RPC_GATEWAY_WATCHLISTlowdetectNo specific gateway domains published; ~20 PUBLIC, legitimate Ethereum RPC gateways are abused as transport. Populate your own current watchlist; never block outright

Expiry per conventions: detect rows +6 months (2027-04-02), hunt/enrich rows +1-3 months given how fast attacker-chosen filenames rotate.

05

Affected Surface & Telemetry Matrix

SurfaceRequired TelemetryPriorityGap / Risk
WordPress web application (PHP-FPM / Apache / Nginx host, Linux)Falcon Linux sensor: ProcessRollup2/SyntheticProcessRollup2, CriticalFileModified (FIM), ZipFileWritten, NetworkConnectIP4, DnsRequestHighCriticalFileModified only fires for paths registered in the tenant's FIM / Critical File policy; WordPress paths are not covered by default
MySQL/MariaDB database hostNative DB audit (information_schema.TRIGGERS, wp_options content, general/audit log)HighFalcon has no SQL-level visibility; this surface is entirely native-audit territory
Linux kernel SysV IPC (shared memory)ipcs -m / host auditHighNo Falcon event model for SysV shared-memory segment creation/content; confirmed gap, not a tenant config issue
PHP runtime internals (opcache, auto_prepend_file caching)None available to EDRMediumopcache_invalidate() calls and the up-to-300-second .user.ini cache window are invisible to any process/file telemetry; documented here only as an operational hazard for responders
Egress to third-party blockchain infrastructureNetworkConnectIP4 / DnsRequest joined to a maintained RPC-provider watchlistMediumHigh false-positive surface; the infrastructure is shared and legitimate, so this is a triage signal, never an automated block
06

ATT&CK Mapping

TacticTechnique IDTechnique NameObserved Behavior
PersistenceT1505.003Server Software Component: Web ShellEight interdependent drop-ins / mu-plugin / duplicate plugin / theme injection, each able to rewrite the others
Defense EvasionT1564.001Hide Artifacts: Hidden Files and DirectoriesDot-prefixed hidden loader; hidden administrator absent from user-list UI
Defense EvasionT1027Obfuscated Files or InformationScrambled-string table with a positional-substitution-cipher decoder; no readable function names
Defense EvasionT1562.001Impair Defenses: Disable or Modify ToolsDeactivates and deletes security plugins on operator command; can reassign/elevate an account first
PersistenceT1136Create AccountHidden, fully-privileged administrator written directly to users/usermeta tables when the WP API is unavailable
Credential Access / Defense EvasionT1556Modify Authentication ProcessForges valid authentication cookies for the hidden administrator (passwordless operator login)
Command and ControlT1102.002Web Service: Bidirectional CommunicationPolls ~20 public Ethereum RPC gateways and smart-contract method selectors for instructions, with failover across the pool
Command and ControlT1071.001Application Layer Protocol: Web ProtocolsHTTPS transport to the RPC gateways; short-prefix-plus-fixed-value beacon answered before WordPress finishes bootstrapping
ExecutionT1059.004Command and Scripting Interpreter: Unix ShellOperator-convenience shell spawned from the web-server worker process
PersistenceT1053.003Scheduled Task/Job: CronRandomized WP-Cron hook names alongside a known fetch hook, re-triggered by system cron executing wp-cron.php
Command and Control / Resource DevelopmentT1105Ingress Tool TransferFetches and deploys additional PHP and front-end JavaScript on command
Impact / CollectionT1659Content InjectionInjects front-end JavaScript into visitor-facing pages, enabling checkout skimming on e-commerce sites
07

Native Audit-Log Hunts (non-CQL)

The off-disk persistence Sucuri describes (the database row, the shared-memory segment, cron hooks, and, in related variants, database triggers) is the part no EDR agent can see. These checks run on the host or against the WordPress/MySQL application layer directly, and they are what actually closes the reinfection loop.

WordPress / filesystem

ls -la wp-content/.*.php wp-content/*.php 2>/dev/null          # hidden dot-prefixed PHP in wp-content root
cat .user.ini php.ini 2>/dev/null | grep -i auto_prepend_file   # confirm the prepend target before touching it
grep -rl "SC_" wp-content/db.php wp-content/advanced-cache.php wp-content/themes/*/functions.php 2>/dev/null
find wp-content/uploads wp-content/themes -maxdepth 3 -iname '*.zip' -regex '.*/[0-9a-f]\{8,\}\.zip' 2>/dev/null

WordPress database

wp cron event list --fields=hook,next_run_relative            # look for randomized hook names beside a known fetch hook
wp option list --search="*" --format=csv | awk -F, 'length($2)>20000 {print}'   # oversized option blobs
wp user list --fields=ID,user_login,roles,user_registered      # cross-check against user_list_table ajax output for a hidden admin
wp db query "SELECT user_id, meta_key, LENGTH(meta_value) FROM wp_usermeta WHERE meta_key LIKE '%capabilities' ORDER BY LENGTH(meta_value) DESC LIMIT 20;"
wp db query "SELECT TRIGGER_NAME, EVENT_OBJECT_TABLE, ACTION_STATEMENT FROM information_schema.TRIGGERS;"  # audit for an admin-recreating trigger

Host-level shared memory

ipcs -m                     # list System V shared-memory segments; cross-reference fixed numeric keys across scans
ipcs -m -p                  # creator PID per segment -- correlate to the PHP-FPM/web worker pool
# A segment that persists across a full file + database cleanup and still decodes to readable PHP
# starting "<?php" is live malware, not a stale leftover; purge with ipcrm -m <id> only after confirming
# the drop-ins that would read it back (advanced-cache.php) are already removed.

Web-server / WAF access logs

egrep -i '\?[a-z]{1,4}=[0-9a-f]{6,}' /var/log/{httpd,nginx,apache2}/*access*.log | less
# Hunt for the magic beacon parameter: a short prefix followed by a fixed value, answered with a
# normal-looking response and no corresponding WordPress page render in the timing/size profile.
# No exact parameter name is published -- baseline your own site's legitimate query-string vocabulary
# first, then flag anything short, fixed-value, and unexplained by app behavior.
08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first: every "Open in Falcon" button below uses this selection.

All eleven queries below are detect / hunt only. None of them, and nothing in the IOC appendix (Section 10), should be wired to a blocking action: the egress and DNS queries in particular hit shared, legitimate third-party infrastructure (public Ethereum RPC gateways) that many unrelated benign systems also use.

Q1 · New or Modified .user.ini Setting auto_prepend_file
CONF HIGHFP LOWCOST LOW

Looks for: a web-server worker process writing .user.ini at runtime, the #1 persistence point (auto_prepend_file), cached by PHP for up to five minutes. FP: legitimate deploy pipelines touching .user.ini during a release window.

// HUNT: New or modified .user.ini setting auto_prepend_file
// MITRE: T1505.003
// CONF: high
// FP: low
// COST: low
// REQUIRES: CriticalFileModified (Falcon FIM / Critical File policy covering the web document root) -- ⚠ validate in tenant: .user.ini must be added to your Falcon File Integrity Monitoring path list, it is not covered by default
// FALSE POSITIVES: deploy pipelines (Composer/WP-CLI/CI runners) touching .user.ini during a scheduled release window
#event_simpleName=/CriticalFileModified/
| FileName=/^\.user\.ini$/i
| ContextBaseFileName=/^(php-fpm|php-fpm[0-9.]*|php|httpd|apache2|nginx)/i
| table([aid, ComputerName, FileName, FilePath, ContextBaseFileName, ContextProcessId, UserName, @timestamp])
Q2 · Hidden Dot-Prefixed PHP Loader Appears Under wp-content
CONF HIGHFP LOWCOST LOW

Looks for: a dot-prefixed PHP file written anywhere under wp-content, not a WordPress core or plugin convention. FP: none expected.

// HUNT: Hidden dot-prefixed PHP loader appears under wp-content
// MITRE: T1564.001, T1505.003
// CONF: high
// FP: low
// COST: low
// REQUIRES: CriticalFileModified scoped to the web document root -- ⚠ validate in tenant
// FALSE POSITIVES: none expected -- dot-prefixed PHP is not a WordPress core/plugin naming convention
#event_simpleName=/CriticalFileModified/
| FilePath=/\/wp-content\//i
| FileName=/^\.[A-Za-z0-9_-]+\.php$/i
| table([aid, ComputerName, FileName, FilePath, ContextBaseFileName, ContextProcessId, UserName, @timestamp])
Q3 · db.php / advanced-cache.php Drop-In Rewritten by a Running Web-Server Process
CONF HIGHFP MEDCOST LOW

Looks for: the two earliest-loading WordPress drop-ins rewritten at runtime by the web worker itself, not by a deploy tool. FP: legitimate caching plugins (WP Super Cache, W3TC) write advanced-cache.php during their own activation/save-settings flow.

// HUNT: WordPress bootstrap drop-in (db.php / advanced-cache.php) rewritten by a running web-server process
// MITRE: T1505.003
// CONF: high
// FP: medium
// COST: low
// REQUIRES: CriticalFileModified scoped to wp-content -- ⚠ validate in tenant
// FALSE POSITIVES: caching-plugin activation or settings-save from within a logged-in admin's own wp-admin request
// TUNING: exclude writes whose ContextProcessId / timestamp correlates to an authenticated admin's own plugin-settings-save request in the WP audit log; escalate only when no matching admin action exists
#event_simpleName=/CriticalFileModified/
| FileName=/^(db|advanced-cache)\.php$/i
| FilePath=/\/wp-content\//i
| ContextBaseFileName=/^(php-fpm|php-fpm[0-9.]*|php|httpd|apache2|nginx)/i
| table([aid, ComputerName, FileName, FilePath, ContextBaseFileName, ContextProcessId, UserName, @timestamp])
Q4 · Active Theme functions.php Rewritten by the Web-Server Process at Runtime
CONF MEDFP HIGHCOST LOW

Looks for: the theme-resident twin of the db.php drop-in: the SC_ bounded block appended to functions.php. FP: legitimate edits via the WordPress Theme Editor or a deploy pipeline are common and look identical at the file-write level.

// HUNT: Active theme functions.php rewritten by the web-server process at runtime
// MITRE: T1505.003
// CONF: medium
// FP: high
// COST: low
// REQUIRES: CriticalFileModified scoped to wp-content/themes -- ⚠ validate in tenant
// FALSE POSITIVES: legitimate theme edits via theme-editor.php, or a deploy pipeline pushing a theme update
// TUNING: exclude writes that occur within seconds of an authenticated administrator's own theme-editor.php POST (correlate aid + UserName + timestamp against the WP audit log); escalate only when no matching admin edit exists in the same window
#event_simpleName=/CriticalFileModified/
| FileName=/^functions\.php$/i
| FilePath=/\/wp-content\/themes\//i
| ContextBaseFileName=/^(php-fpm|php-fpm[0-9.]*|php|httpd|apache2|nginx)/i
| table([aid, ComputerName, FileName, FilePath, ContextBaseFileName, ContextProcessId, UserName, @timestamp])
Q5 · New File Written to wp-content/mu-plugins at Runtime
CONF HIGHFP LOWCOST LOW

Looks for: the must-use-plugin copy of the backdoor landing in mu-plugins, a directory that almost never changes outside a deliberate deploy. FP: a genuine mu-plugin deploy during a maintenance window.

// HUNT: New file written to wp-content/mu-plugins at runtime
// MITRE: T1505.003
// CONF: high
// FP: low
// COST: low
// REQUIRES: CriticalFileModified scoped to wp-content/mu-plugins -- ⚠ validate in tenant
// FALSE POSITIVES: a deliberate mu-plugin deploy during a maintenance window
#event_simpleName=/CriticalFileModified/
| FilePath=/\/wp-content\/mu-plugins\//i
| FileName=/\.php$/i
| table([aid, ComputerName, FileName, FilePath, ContextBaseFileName, ContextProcessId, UserName, @timestamp])
Q6 · Randomly Named ZIP Archive Written Under wp-content/uploads or a Theme Folder
CONF MEDFP MEDCOST LOW

Looks for: the ZIP restore bundle the loader falls back to when its other sources are missing. FP: legitimate backup plugins and manual plugin/theme installs via wp-admin also write ZIPs here.

// HUNT: Randomly named ZIP archive written under wp-content/uploads or a theme folder
// MITRE: T1505.003, T1027
// CONF: medium
// FP: medium
// COST: low
// REQUIRES: ZipFileWritten
// FALSE POSITIVES: legitimate backup plugins (e.g. UpdraftPlus) and manual plugin/theme installs via wp-admin
// TUNING: exclude ZIP writes whose ContextProcessId correlates to a logged-in admin's plugin-upload or backup-plugin request; prioritize purely-hex 8+ character basenames with no companion admin action
#event_simpleName=/ZipFileWritten/
| FilePath=/\/wp-content\/(uploads|themes)\//i
| FileName=/^[0-9a-f]{8,}\.zip$/i
| table([aid, ComputerName, FileName, FilePath, ContextBaseFileName, ContextProcessId, UserName, @timestamp])
Q7 · PHP-FPM / httpd / nginx Worker Spawns an Interactive Shell
CONF HIGHFP LOWCOST LOW

Looks for: classic web-shell-style behavior: a web worker process has no legitimate reason to exec a shell. FP: rare plugin shell-out helpers (e.g., ImageMagick wrappers); baseline once.

// HUNT: PHP-FPM / httpd / nginx worker spawns an interactive shell
// MITRE: T1505.003, T1059.004
// CONF: high
// FP: low
// COST: low
// REQUIRES: ProcessRollup2 or SyntheticProcessRollup2
// FALSE POSITIVES: a rare legitimate exec() from a plugin's own shell-out helper -- baseline your app's known child-process list once before promoting to an IOA
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^(php-fpm|php-fpm[0-9.]*|php|httpd|apache2|nginx)/i
| FileName=/^(sh|bash|dash|zsh)$/i
| table([aid, ComputerName, ParentBaseFileName, FileName, CommandLine, UserName, @timestamp])
Q8 · System Cron Triggers wp-cron.php (Baseline for Scheduled Redeployment Hooks)
CONF LOWFP HIGHCOST LOW

Looks for: system cron invoking wp-cron.php, the mechanism SC abuses to re-trigger redeployment on schedule. FP: this is also the standard, recommended way to run WordPress cron on a hardened site: this query is a baseline-builder, not a detection by itself.

// HUNT: System cron triggers wp-cron.php (baseline for scheduled redeployment hooks)
// MITRE: T1053.003
// CONF: low
// FP: high
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: running wp-cron.php via system cron instead of WordPress's default pseudo-cron is a widely RECOMMENDED hardening practice -- it fires on every site that has adopted it
// TUNING: this query alone is not a detection -- it is a baseline-builder. Pair every hit with the native wp_options cron-array audit in Section 7 to surface randomized hook names system cron is unknowingly executing alongside the legitimate wp-cron.php invocation
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^cron(d)?$/i
| CommandLine=/wp-cron\.php/i
| table([aid, ComputerName, ParentBaseFileName, FileName, CommandLine, UserName, @timestamp])
Q9 · Web-Server Worker Spawns a MySQL Client Directly
CONF MEDFP MEDCOST LOW

Looks for: the web worker shelling out to a MySQL CLI rather than using the normal PHP DB abstraction layer: a proxy for the "direct database connection bypassing WordPress APIs" Sucuri describes. FP: scheduled backup scripts that legitimately shell out to mysqldump.

// HUNT: Web-server worker spawns a MySQL client directly
// MITRE: T1505.003
// CONF: medium
// FP: medium
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: scheduled backup jobs (e.g. "wp db export" via WP-CLI, cPanel backup jobs) that legitimately shell out to mysqldump
// TUNING: exclude known backup-job service accounts/cron wrappers; flag only when the parent is the LIVE PHP-FPM/httpd worker servicing an HTTP request, not a cron-invoked backup script
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^(php-fpm|php-fpm[0-9.]*|php|httpd|apache2|nginx)/i
| FileName=/^(mysql|mysqldump)$/i
| table([aid, ComputerName, ParentBaseFileName, FileName, CommandLine, UserName, @timestamp])
Q10 · Web-Server Worker Makes Outbound HTTPS Connections (Blockchain RPC Egress Triage)
CONF LOWFP HIGHCOST MED

Looks for: the web worker reaching out to public Ethereum RPC gateways for C2 instructions. FP: nearly everything: CDNs, payment gateways, license/update checks. Triage only, never an automated block; never promote to prevent.

// HUNT: Web-server worker makes outbound HTTPS connections (blockchain RPC egress triage)
// MITRE: T1102.002, T1071.001
// CONF: low
// FP: high
// COST: medium
// REQUIRES: NetworkConnectIP4; a tenant-maintained public-RPC-provider watchlist for manual cross-reference
// FALSE POSITIVES: nearly everything -- CDNs, payment gateways, license/update checks, and every other legitimate third-party API the app calls over 443
// TUNING: REPLACE_WITH_RPC_WATCHLIST -- join RemoteAddressIP4 / resolved DomainName against your current public-Ethereum-RPC-provider watchlist before triaging; without that join this returns ordinary CDN/API noise. Detect/hunt only -- never action=prevent, this is shared legitimate third-party infrastructure
#event_simpleName=/NetworkConnectIP4/
| ContextBaseFileName=/^(php-fpm|php-fpm[0-9.]*|php|httpd|apache2|nginx)/i
| RemotePort=443
| table([aid, ComputerName, ContextBaseFileName, ContextProcessId, RemoteAddressIP4, RemotePort, LocalAddressIP4, @timestamp])
Q11 · DNS Resolution From a Web-Server Process to a Public Ethereum RPC Provider (Watchlist Match)
CONF LOWFP HIGHCOST LOW

Looks for: DNS lookups from the web host matching a tenant-supplied RPC-provider watchlist pattern. FP: any benign site integrating wallet/crypto-payment features, browser extensions, or shared-hosting neighbors. Detect/hunt only.

// HUNT: DNS resolution from a web-server process to a public Ethereum RPC provider (watchlist match)
// MITRE: T1102.002
// CONF: low
// FP: high
// COST: low
// REQUIRES: DnsRequest; same tenant RPC watchlist as Q10
// FALSE POSITIVES: any benign site legitimately integrating wallet/crypto-payment features, browser extensions resolving the same public gateways, or shared-hosting neighbors
// TUNING: REPLACE_WITH_RPC_PROVIDER_DOMAIN_PATTERN -- populate with your current public RPC-provider domain watchlist before running. Detect/hunt only -- never block shared legitimate infrastructure
#event_simpleName=/DnsRequest/
| DomainName=/REPLACE_WITH_RPC_PROVIDER_DOMAIN_PATTERN/i
| table([aid, ComputerName, ContextProcessId, DomainName, QueryType, @timestamp])
09

CrowdStrike Custom IOA Recommendations

Four queries are low-noise and specific enough to promote from hunt query to Custom IOA. The remaining seven stay as investigate-only hunt queries (medium/high FP, or dependent on a tenant-supplied watchlist).

CandidateIOA NamePatternExclusionsDeployment Path
Q2DETECT-SC-HiddenDotPHPLoaderCriticalFileModified under wp-content, FileName matches a dot-prefixed .php basenamenone knownCustom IOA rule in Falcon console, severity High, action Detect only
Q3DETECT-SC-DropInRewriteCriticalFileModified on db.php/advanced-cache.php under wp-content, writer is a web-server worker processexclude writes within 60s of an authenticated admin plugin-settings-save (requires WP audit-log join)Custom IOA rule, severity High, action Detect; pair with the WP audit-log join as a Falcon Fusion workflow enrichment
Q5DETECT-SC-MuPluginDropCriticalFileModified, new .php file under wp-content/mu-pluginsmaintenance-window deploy allowlist by change-ticket tagCustom IOA rule, severity High, action Detect only
Q7DETECT-SC-WebWorkerShellSpawnProcessRollup2, ParentBaseFileName in web-worker set, FileName in {sh,bash,dash,zsh}known plugin shell-out helper, baselined per tenant before enablingCustom IOA rule, severity Critical, action Detect; strong promotion candidate for automated SOC ticket creation

Do not promote Q10/Q11 (RPC egress/DNS) to a Custom IOA until a maintained, tenant-specific RPC-provider watchlist is wired in via a lookup join; without it, both fire on routine CDN/API/update-check traffic.

10

Machine-Readable IOC Appendix

Grouped quick-copy blocks, tailored to a file-path/content-marker/behavioral campaign with no published hashes or domains. Every CSV row below is action=detect; nothing here ships as prevent.

Falcon IOC Management CSVbulk import, detect only
type,value,action,severity,expiration,description,tags
filename,db.php,detect,high,2027-04-02,WordPress bootstrap drop-in carrying the SC backdoor as a gzip+base64 blob; stable filename required by WordPress core itself; verify content for an SC_ marker before escalating,campaign:SC
filename,advanced-cache.php,detect,high,2027-04-02,Earliest-loading WordPress drop-in; rebuilds the backdoor from five fallback sources when WP_CACHE is enabled; stable filename required by WordPress core itself,campaign:SC
filename,.user.ini,detect,medium,2027-04-02,PHP config file abused to set auto_prepend_file ahead of every request; common filename -- pair with content/behavioral review before escalating,campaign:SC
path,wp-content/mu-plugins/hyper-engine-kit.php,detect,medium,2027-04-02,Observed must-use-plugin path for the SC payload; Sucuri notes the file name varies per site -- starting hunt term not a guaranteed match,campaign:SC
path,wp-content/plugins/hyper-engine-kit/hyper-engine-kit.php,detect,medium,2027-04-02,Duplicate redundant copy of the SC payload shipped as a normal plugin; name varies per site,campaign:SC
sha256,REPLACE_WITH_SHA256,detect,critical,2027-04-02,No file hashes have been published for SC as of this pack's research date; populate if a sample is recovered during your own incident response,campaign:SC
domain,REPLACE_WITH_RPC_GATEWAY_WATCHLIST,detect,low,2027-04-02,No specific C2 domains were published for SC; the backdoor polls roughly twenty PUBLIC Ethereum RPC gateways (legitimate shared infrastructure). Populate with your current RPC-provider watchlist and treat matches as detect-only triage -- NEVER block these domains outright,campaign:SC
Behavioral Signaturesfile-content & structural markers
# SC behavioral signatures -- Sucuri published no hashes/domains, so structure/content is the signal
- wp-content/db.php or wp-content/advanced-cache.php containing an SC_-prefixed begin/end guard-constant block
- Active theme functions.php containing a bounded injected block fenced by matching begin/end markers (begin marker sometimes duplicated)
- .user.ini / php.ini / .htaccess setting auto_prepend_file to a hidden dot-prefixed PHP path
- Identical PHP payload present in BOTH wp-content/mu-plugins/*.php and wp-content/plugins/*/*.php with a matching fake settings page
- wp_options row (random option name) holding an oversized gzip+base64 blob, plus control options/transients using an sc_-style prefix
- System V shared-memory segment (fixed numeric key) holding readable PHP starting with <?php
- WordPress administrator with capabilities stored under the default capabilities meta key, absent from the user-list UI
- Orphaned wp_options row pointing at an administrator user ID, left behind after a partial cleanup
- Outbound HTTPS from the web-server process to public Ethereum JSON-RPC gateways (~20 observed, rotating; legitimate shared infrastructure abused as C2 transport)
- A single magic request parameter (short prefix + fixed value) answered with a normal-looking response before WordPress finishes bootstrapping
Named Malware / Toolingreporting identifiers
# Identifiers used in public reporting (rotating names flagged as such)
SC                               - Sucuri's codename for this family, from the SC_ markers in injected content
hyper-engine-kit                 - example mu-plugin/plugin folder name in Sucuri's analyzed sample (ROTATES per site, not a fixed indicator)
khorshidi                        - example theme name carrying the injected functions.php block (site-specific; the theme itself is not inherently malicious)
c1b12371.php / .c1b12371.php     - example shim + hidden-loader basenames from Sucuri's sample (ROTATES per site; illustrates the shim+hidden-loader PAIR pattern, not a fixed filename)
Hosting / DB Audit Checklisthost-side, not Falcon
# Run from the hosting account / DB admin session -- see Section 7 for the full command set
[ ] ls -la wp-content/.*.php                         -- hidden dot-prefixed PHP in wp-content root
[ ] grep -i auto_prepend_file .user.ini php.ini        -- confirm the prepend directive and its target
[ ] grep -rl "SC_" wp-content/db.php wp-content/advanced-cache.php wp-content/themes/*/functions.php
[ ] ipcs -m                                            -- System V shared-memory segments
[ ] wp cron event list --fields=hook,next_run_relative -- randomized hook names
[ ] wp option list --search="*" | check for oversized blobs
[ ] information_schema.TRIGGERS audit for an admin-recreating trigger
[ ] wp user list -- cross-check for a hidden fully-privileged administrator
11

Detection Validation Gates

GateQ2 (hidden loader)Q3 (drop-in rewrite)Q5 (mu-plugins drop)Q7 (shell spawn)
Telemetry readyPending FIM path addPending FIM path addPending FIM path addReady ProcessRollup2 is default-on
Benign baseline establishedn/a: no legitimate dot-prefixed PHP expectedpending: must capture one caching-plugin activation cycle firstpending: must capture one scheduled mu-plugin deploypending: must capture one app-lifetime of normal child processes
Positive-control test firedNot yet runNot yet runNot yet runNot yet run
Promotion statusHunt query → IOA candidate (Section 9)Hunt query → IOA candidate (Section 9), needs WP audit-log joinHunt query → IOA candidate (Section 9)Hunt query → IOA candidate (Section 9)

Before enabling any of the four as a live IOA: (1) add the listed WordPress paths to the tenant's Falcon FIM / Critical File policy, (2) run each query over at least one full deploy/release cycle to capture benign writes, (3) fire a positive-control test (a deliberate, authorized write to the same path from the same process family) to confirm the event actually lands, then (4) promote.

12

Hardening: Tiered

Immediate (this week)

Deny PHP execution inside writable upload/theme directories. M1038 (Execution Prevention). The single highest-leverage control: it breaks the shim, the hidden loader, the mu-plugin drop, and the ZIP-restore fallback in one move, because none of them can run if the web server refuses to execute PHP from those paths. Cite: OWASP WordPress hardening guidance; CIS Apache/Nginx benchmarks (web-root execution restrictions).
Verify: curl -s -o /dev/null -w '%{http_code}' https://SITE/wp-content/uploads/test.php should return 403/404 after a harmless test file is placed and the rule is live.

Immediate (this week)

Lock down .user.ini handling at the PHP-FPM pool level. M1038 (Execution Prevention) / M1022 (Restrict File and Directory Permissions). Kills persistence point #1 (auto_prepend_file). ⚠ best-practice, no formal benchmark: php.net documents user_ini.filename but no CIS/vendor baseline covers this specific control; include it anyway, it is sound and directly threat-relevant.
Verify: php -i | grep user_ini.filename on the pool shows an empty value, or a changed .user.ini under the web root produces no behavior change after PHP-FPM reload.

Near term (1-4 weeks)

Deploy File Integrity Monitoring on the fixed drop-in set (db.php, advanced-cache.php, theme functions.php, mu-plugins/*, .user.ini) and rotate WordPress/DB/hosting credentials and salts. M1047 (Audit) / M1032-adjacent credential hygiene. Ties directly to CQL Q1-Q5.
Verify: a deliberate test write to any listed path produces a CriticalFileModified event within the expected latency window; wp config shuffle-salts run and confirmed via a forced re-login of all sessions.

Near term (1-4 weeks)

Add a WAF rule flagging (not necessarily blocking) the short-prefix/fixed-value beacon parameter, and an egress-monitoring rule surfacing web-server HTTPS connections to public blockchain RPC providers for SOC review. M1037 (Filter Network Traffic).
Verify: a synthetic request carrying a candidate beacon-shaped parameter appears in the WAF log/alert queue; a test outbound connection to a known public RPC endpoint from the web host appears in the egress-monitoring queue.

Strategic (1-3 months)

Run PHP-FPM under a dedicated, least-privilege user per site; enable open_basedir; disable exec/shell_exec/system/proc_open/popen in the web-facing pool's disable_functions; reduce the WordPress DB user's grants to remove CREATE TRIGGER/DROP rights. M1018 (User Account Management) / M1042 (Disable or Remove Feature or Program). Directly blocks the shell-spawn (Q7), the direct-mysql-client path (Q9), and the database-trigger reinfection vector Sucuri flags in related variants.
Verify: php -i | grep disable_functions lists the disabled set; SHOW GRANTS FOR 'wp_user'@'%'; no longer includes TRIGGER/DROP.

Strategic (1-3 months)

Formalize a WordPress core/plugin/theme patch-management SLA. M1051 (Update Software). Sucuri's own prevention guidance states most of the compromises they handle exploit already-fixed vulnerabilities; this is the actual root-cause control for the unconfirmed initial-access step in Section 3.
Verify: wp plugin list --update=available and wp core check-update return empty against the documented SLA window.

13

Deployable Playbooks

Playbook 1: Deny PHP execution in uploads (Nginx)

Prerequisites: shell access to the Nginx config for the vhost; ability to reload Nginx. Reboot required: no (config reload only). Rollback: remove the added location block and reload; no data is modified.

location ~* /wp-content/uploads/.*\.php$ {
    deny all;
    return 403;
}
# Reload (no restart, no downtime):
sudo nginx -t && sudo systemctl reload nginx

Playbook 2: Deny PHP execution in uploads (Apache / .htaccess)

Prerequisites: mod_rewrite/mod_authz_core enabled; write access to wp-content/uploads/.htaccess. Reboot required: no. Rollback: delete the added <FilesMatch> block from the .htaccess file.

<FilesMatch "\.php$">
    Require all denied
</FilesMatch>

Playbook 3: Lock down PHP-FPM pool (disable_functions + .user.ini)

Prerequisites: access to the PHP-FPM pool's php.ini / pool conf; a maintenance window (some legacy plugins may call shell_exec and will break; test on a staging ring first). Reboot required: PHP-FPM service restart (brief request-queue pause, not a host reboot). Rollback: restore the previous php.ini from backup and restart PHP-FPM; re-enabling individual functions is also possible without a full revert if one legitimate plugin is found to need one.

; php.ini (web-facing pool)
disable_functions = exec,shell_exec,system,passthru,proc_open,popen
user_ini.filename =
open_basedir = /var/www/site/:/tmp/

; Reload the pool:
sudo systemctl restart php8.3-fpm

Playbook 4: WordPress DB user least privilege

Prerequisites: MySQL/MariaDB admin access; confirm no legitimate plugin relies on the WP DB user holding TRIGGER/CREATE/DROP (most do not). Reboot required: no. Rollback: re-grant the removed privileges with the equivalent GRANT statement if a legitimate plugin breaks.

REVOKE TRIGGER, CREATE, DROP, SUPER, FILE ON *.* FROM 'wp_user'@'%';
GRANT SELECT, INSERT, UPDATE, DELETE, ALTER, INDEX ON wordpress_db.* TO 'wp_user'@'%';
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'wp_user'@'%';   -- confirm TRIGGER/CREATE/DROP/SUPER/FILE are gone
14

Containment Runbook

Order matters. Sucuri is explicit that removing files first, in the wrong order, simply triggers a rewrite from an off-disk copy.

PhaseActionsOwnerEvidence
1 · Isolate / PreparePreserve a forensic copy of the site and database. Empty the .user.ini prepend target to an inert stub FIRST (the directive is cached by PHP for up to 300 seconds; deleting the target while the cache is warm takes down every PHP request on the account). Place the site in maintenance mode or isolate if active skimming is confirmed.Incident lead + hosting adminPre-change filesystem/DB snapshot; timestamped copy of .user.ini before edit
2 · Eradicate off-diskRemove the payload row from wp_options; purge the System V shared-memory segment (ipcrm -m, only after confirming the drop-ins that would read it back are already gone); clear malicious cron hooks; audit and drop any admin-recreating database trigger.DBA + incident leadDump of removed options row; ipcs -m before/after; information_schema.TRIGGERS before/after
3 · Eradicate on-diskRemove the hidden administrator account and its orphaned option; delete the shim, hidden loader, both plugin copies, and the ZIP restore bundle; strip only the SC_ bounded block from the theme's functions.php (preserve the rest of the file); delete db.php and advanced-cache.php.Incident leadBefore/after file listing of wp-content; diff of functions.php showing only the bounded block removed
4 · RecoverRescan the full site; monitor the cleaned paths for recreated files; rotate WordPress admin, hosting, database, and SSH credentials; regenerate WordPress salts; patch core/plugins/themes before returning to production.Incident lead + hosting adminClean scan report; credential-rotation log; patch-level report post-update
15

Detection Coverage Map

Persistence Point / BehaviorCQLIOANativeCoverage
1. .user.ini (auto_prepend_file)Q1n/aSection 7Good
2. Visible PHP shimpartial (Q2 covers the hidden pair-file, not the shim's own first write)n/aSection 7Partial
3. Hidden dot-prefixed loaderQ2Q2Section 7Good
4. db.php drop-inQ3Q3Section 7Good
5. advanced-cache.php drop-inQ3Q3Section 7Good
6. Theme functions.php injectionQ4n/a (FP too high without audit-log join)Section 7Partial
7/8. mu-plugin + duplicate plugin payloadQ5Q5Section 7Good
ZIP restore bundleQ6n/aSection 7Partial
Off-disk: wp_options blobnone: no Falcon event for DB contentn/aSection 7GAP (native-only)
Off-disk: SysV shared memorynone: no Falcon event model for SysV IPCn/aSection 7GAP (native-only)
Off-disk: randomized cron hooks / DB triggersQ8 (baseline only)n/aSection 7GAP (native-only)
Shell spawn from web workerQ7Q7n/aGood
Direct DB access bypassing WP APIsQ9 (proxy only)n/aSection 7Partial
Blockchain RPC C2 egressQ10, Q11n/a (needs watchlist first)n/aPartial (watchlist-dependent)
Hidden administrator / forged auth cookiesnone: WP-application-layer state, not EDR-visiblen/aSection 7GAP (native-only)
Front-end JS injection / skimmingnone: rendered content, not EDR-visiblen/aexternal JS-integrity monitoring (out of scope)GAP

Validation-gate summary: four queries (Q2, Q3, Q5, Q7) are IOA-ready pending the FIM-policy additions and benign-baseline captures described in Section 11; the remaining gaps above are architectural (no Falcon telemetry exists for SysV shared memory, SQL content, or rendered front-end JavaScript) and are covered instead by the native audit hunts in Section 7 and the hardening controls in Section 12.

16

Hunt Summary Ticket

TITLE:      Hunt for SC self-healing WordPress backdoor mesh (blockchain C2)
SEVERITY:   High
SCOPE:      All Linux web hosts (PHP-FPM / Apache / Nginx) serving WordPress sites in scope
HYPOTHESIS: A web-server worker process is writing/rewriting WordPress bootstrap drop-ins
            (db.php, advanced-cache.php), a theme's functions.php, or new mu-plugins files
            at runtime; and/or spawning a shell or MySQL client it has no legitimate reason
            to spawn; and/or the host is polling public Ethereum RPC gateways for instructions.
QUERIES:    Q1-Q11 (Section 8); native audit hunts (Section 7)
DO FIRST:   1) Add wp-content/db.php, advanced-cache.php, themes/*/functions.php, mu-plugins/*,
               and .user.ini to the Falcon FIM / Critical File policy for in-scope hosts.
            2) Run the native wp_options / ipcs -m / information_schema.TRIGGERS audit
               (Section 7) in parallel -- this is the part Falcon cannot see.
            3) Run Q7 (shell spawn) first; it is the highest-confidence, lowest-FP query.
FINDINGS:   [fill in after execution]
GAPS:       No Falcon telemetry for SysV shared memory, SQL content, WP-Cron hook names
            stored in wp_options, or rendered front-end JavaScript -- all native-audit-only.
            Initial access vector for this campaign is unconfirmed in public reporting.
ACTIONS:    Promote Q2/Q3/Q5/Q7 to Custom IOA after the validation gates in Section 11 pass.
            Deploy Playbooks 1-4 (Section 13) per the tiering in Section 12.
OWNER:      HuntPack
VERSION:    v1.0 -- 2026-10-02
17

Changelog

v1.02026-10-02Initial HuntPack. Built from the Sucuri primary research (2026-09-30) plus four corroborating/derivative sources. No hashes, domains, wallet/contract addresses, or PHP function names published by any source as of this date, so detection is built entirely on file-path, content-marker, and behavioral signals. All IOC/Falcon-import rows ship action=detect; the Ethereum RPC egress queries are explicitly detect/hunt-only and never promoted to prevent.
18

References

TierSourceUsed ForAccess Date
1Sucuri Blog: "SC WordPress Malware, A Self-Healing Mesh of Loaders, Drop-Ins, and a Blockchain-Controlled Backdoor" (2026-09-30)Primary technical source for all eight persistence points, self-healing mechanics, backdoor capabilities, off-disk persistence, IOC list, and cleanup ordering2026-10-02
1The Hacker News: "WordPress Backdoor Rebuilds Itself After Cleanup Using Files, Database, and Shared Memory" (2026-10-01)Corroboration of all eight components; initial-access-vector-unconfirmed caveat2026-10-02
2GBHackers: "SC WordPress Malware Rebuilds Itself After Removal Using Database and Memory Persistence" (2026-10-01)Corroboration; remediation-ordering guidance2026-10-02
2CyberPress: "SC WordPress Malware Rebuilds Itself From 8 Locations and Uses Ethereum for C2" (2026-10-01)Corroboration; "EtherHiding" terminology note2026-10-02
3CleanTalk Research: "SC WordPress Malware in functions.php, db.php, and 1j2d192.php" (2026-09-10 snapshot)TTP cross-reference only: CleanTalk's own, separately-labelled "SC" family; explicitly NOT used for any atomic indicator or fact in this pack2026-10-02

All five sources saved verbatim to SC-SelfHealing-WordPress-Backdoor-Hunt-sources/ for provenance re-verification.