OFFSEC · Offensive Security

Eight Copies, One Backdoor: Why Removal Order Decides Whether a WordPress Cleanup Holds

Sucuri has documented a WordPress infection replicated across eight locations that rebuild one another, plus a copy held in shared memory. The durable lesson is about the platform's documented extension points, not about the malware.

What was found

On 30 September, Sucuri published Gabriel Barbosa’s analysis of a WordPress infection it labels SC, after markers left in the injected content [1]. The capability list is unremarkable for a web backdoor: inject front-end JavaScript, execute supplied PHP, disable security plugins, create a hidden administrator. The topology is what matters: the same payload sits in eight places, several of which can rebuild the others.

Sucuri sets out the components as an interconnected set [1]:

  • A .user.ini file that “Sets auto_prepend_file to run #2 before every PHP request in the tree”.
  • A plaintext shim that includes a hidden counterpart and “Silently no-ops if removed”.
  • The hidden dot-prefixed loader wp-content/.c1b12371.php, which “Rebuilds the mu-plugin”.
  • The db.php drop-in, which “Carries the full backdoor as a gzip+base64 blob” and redeploys the plugin “whenever it’s missing or too small”.
  • The advanced-cache.php drop-in, which “Rebuilds the plugin, hooks plugins_loaded, and includes it”.
  • A block appended to the active theme’s functions.php, a “Theme-resident twin of db.php”.
  • The backdoor as a must-use plugin under wp-content/mu-plugins.
  • An identical copy as an ordinary plugin.

The consequence, in Sucuri’s words: “Delete the plugin and a drop-in rewrites it. Delete the drop-in and the theme rewrites it” [1][2]. A responder working through the artefacts one at a time will watch the site go clean and then dirty again, and may conclude it is being re-exploited.

The first move is not deletion

The entry point is the per-directory INI file, where cleanups most often go wrong. PHP processes .user.ini files “only by the CGI/FastCGI SAPI” and recognises only directives whose mode is INI_ALL, INI_PERDIR or INI_USER [3]. auto_prepend_file “Specifies the name of a file that is automatically parsed before the main file”, is included “as if it was called with the require function”, and carries the mode INI_PERDIR [4] — which is why a file written into a web root can set it.

Two operational facts follow. PHP caches these files: user_ini.cache_ttl “controls how often user INI files are re-read” and “The default is 300 seconds (5 minutes)” [3][4], so deleting the .user.ini does not take effect at once. And because the prepend is a require, deleting the prepended file while the directive is still cached makes every PHP request fail [4] — the fatal error that leads a responder to restore the backup which reinstates the infection.

Sucuri’s sequence therefore neutralises the prepend directive first, then clears database options, shared-memory segments and control transients, removes cron hooks and triggers, deletes hidden administrators, removes all files in one pass, and rescans [1]. The ordering is the finding: files last, not first.

Every hiding place is a documented feature

None of the eight locations is an undocumented trick. WordPress states of must-use plugins that “They are automatically enabled on all sites in the installation”, that “They cannot be disabled from wp-admin”, and that they “do not show in the default list of plugins on the Plugins screen in wp-admin, although they do appear in a separate Must-Use section” [6]. It also loads only “PHP files directly inside the mu-plugins directory”, not subdirectories [6] — which is why the redundant copy had to go in the ordinary plugins tree.

The drop-ins behave similarly: db.php and advanced-cache.php load ahead of the plugin layer and are not managed on the plugin screen. The infection used db.php as the compressed carrier and advanced-cache.php as a rebuilder attached to plugins_loaded [1]. Neither appears where an administrator habitually looks.

The scheduler is the third mechanism. WP-Cron “works by checking, on every page load, a list of scheduled tasks to see what needs to be run” and “is only triggered on page load” [8]. The infection registers cron hooks under randomised names alongside a known fetch hook, and where a system cron invokes the WordPress cron file, redeployment runs on schedule regardless of visitor traffic [1][8]. Taking a site out of public rotation to clean it does not necessarily make it quiet.

The copy that is not on disk

On servers supporting System V shared memory, the payload is also held in a RAM segment under a fixed numeric key [1]. Sucuri’s note on why this matters: “That segment lives in RAM, so it survives file deletion and database cleanup alike, and on shared hosting it can even be owned by a different account” [1].

PHP exposes this through its semaphore extension, which “provides also shared memory functions using System V shared memory”, keys derived from a pathname and project identifier by ftok(), and segments handled through shm_attach, shm_put_var, shm_get_var and shm_remove [5]. A fixed key means any process under that account can reattach and read the payload out.

A cleanup scoped to files and the database can verify clean and still fail on the next request. On shared hosting the segment may be owned by another account, leaving the site owner no way to remove it — which turns remediation into a hosting-provider ticket, worth raising early rather than after the third reinfection.

Blockchain as transport, not as payment

Sucuri reports that the payload resolves its control endpoint through “roughly twenty public Ethereum RPC gateways” using smart-contract method selectors [1], moving to another provider when one becomes unavailable [10]. The fingerprint it posts includes the site URL and host, versions, active themes, the mu-plugin list and current administrator session tokens [1].

The property that makes this work has nothing to do with cryptocurrency: reading contract state requires no transaction. Ethereum’s JSON-RPC documentation describes eth_call as a method that “Executes a new message call immediately without creating a transaction on the blockchain” and that “consumes zero gas” [9]. The operator pays nothing per lookup, leaves no on-chain transaction trail, and sends traffic to third-party API hosts that most organisations have no policy against. There is nothing to seize, and the detection opportunity moves to egress: a content host has no ordinary reason to make outbound JSON-RPC calls to blockchain gateways.

Administrators written around WordPress

The backdoor “either adopts an existing hidden admin or generates a new one, writing the account directly into the users and usermeta tables”, stores the privileges “under the default capabilities meta key”, and “forges valid authentication cookies” [1]. WordPress documents those cookies as containing “your username, the expiration time and hashed data that ensures you have a valid session”, with only four characters of the hashed password represented, and states that “any cookie will invalidated whenever your password is changed” [7].

Writing rows directly bypasses the hooks audit and activity-log plugins observe, so administrator enumeration must run against the database, not the admin screen. Because forged cookies derive from the stored password hash, a forced password change on every administrator invalidates them [7]: a credential reset is part of the remediation, not a hygiene step for later.

What to do

  • Follow the order: neutralise the prepend directive, clear database options, shared-memory segments and transients, remove cron hooks, delete hidden administrators, remove files in one pass, rescan [1].
  • Allow for the 300-second per-directory INI cache before concluding a change has taken effect [3][4].
  • Inventory drop-ins and must-use plugins in routine configuration review; neither is visible where administrators look [6].
  • Enumerate administrators from the database and reset every administrator credential [1][7].
  • Alert on outbound JSON-RPC traffic to blockchain gateways from web hosts [9].
  • On shared hosting, confirm the provider can clear shared-memory segments before certifying a site clean [1][5].

The malware will be renamed and file names will change. The eight extension points will not, because they are how WordPress and PHP are documented to work: per-directory configuration, drop-ins loaded before plugins, must-use plugins that cannot be switched off, a request-driven scheduler, and shared memory open to any process under the account. The defensive work is to inventory those surfaces while nothing is wrong, and clean them in an order that accounts for what rebuilds what.

Sources

Every R3KONX article cites its primary material. 10 sources, in order of first citation. Links open the original publication.

  1. SC WordPress Malware: A Self-Healing Mesh of Loaders, Drop-Ins, and a Blockchain-Controlled Backdoor Sucuri · 2026-09-30
  2. WordPress Backdoor Rebuilds Itself After Cleanup Using Files, Database, and Shared Memory The Hacker News · 2026-10-01
  3. .user.ini files (per-directory INI configuration) PHP Manual · 2026-10-03
  4. Description of core php.ini directives: auto_prepend_file, user_ini.cache_ttl PHP Manual · 2026-10-03
  5. Semaphore, Shared Memory and IPC PHP Manual · 2026-10-03
  6. Must-use plugins WordPress Developer Resources · 2026-10-03
  7. WordPress Cookies WordPress Developer Resources · 2026-10-03
  8. WP-Cron WordPress Developer Resources · 2026-10-03
  9. JSON-RPC API ethereum.org · 2026-10-03
  10. WordPress malware uses Ethereum RPC for self-healing attacks, Sucuri warns COINTURK News · 2026-10-01

Researched and written by the R3KONX analysis desk from the cited primary material. Component behaviour is reported as Sucuri described it; the platform and language behaviour around it is verified against the PHP and WordPress documentation rather than inferred. No exploitation or weaponisation detail is reproduced, and the initial access vector is not established in the published analysis. Corrections to event@r3konx.asia.

R3KONX 2027

Work in this domain? So does the programme

4–6 May 2027, World Trade Centre Kuala Lumpur. Curated talks, hands-on training and The BattleGrid.