The number in every headline is 1.4 million. It is the least useful figure in the whole disclosure. When the operators of a mass-compromise crew that researchers named WP-SHELLSTORM left one of their own servers open to the public internet for 22 days, the leaked activity logs let investigators measure something a target count never can: how often an exploit attempt turned into a backdoored site. That conversion rate is the story, because it shows the severity score of a flaw predicted almost nothing about who got hit.
Here is the shape of the incident. On June 11, 2026, the threat-intelligence team at SOCRadar found an open directory on a rented server, its owner's home folder sitting online with no authentication at all. Inside were roughly 800MB of tooling, command history, target lists, and results. A second firm, Ctrl-Alt-Intel, deduplicated the logs and counted 25,195 confirmed WordPress and Joomla compromises, with more than 5,700 webshells still live. The crew had weaponized 27 separate vulnerabilities. SOCRadar assessed with medium-to-high confidence that the operators are a financially motivated, Chinese-speaking group rather than a state actor, citing Simplified Chinese throughout the code and reconnaissance tooling that requires a Chinese phone number to register.
Severity scored the flaws. Configuration picked the victims.
The leaked logs pair each vulnerability with how many sites it was fired at and how many it backdoored. Line those up and the ranking is upside down from what a vulnerability feed would predict.
| Entry point | CVE | Targets fired at | Webshells landed | Conversion |
|---|---|---|---|---|
| WordPress Breeze cache plugin | CVE-2026-3844 | 45,000+ | 17,000+ | ~38% |
| WordPress ThemeREX Addons | CVE-2026-1969 | 46,600 | 3,378 | ~7% |
| Joomla JCE editor | CVE-2026-48907 | 560,000+ | 77 | ~0.01% |
The Joomla JCE editor flaw, CVE-2026-48907, is a maximum-severity bug that CISA lists as actively exploited. The operators aimed it at over 560,000 sites and compromised just 77, a hit rate near one in seven thousand. CVE-2026-3844 in Breeze, an ordinary WordPress cache plugin, backdoored more than 17,000 of the 45,000 sites it was aimed at.
The Breeze result carries the detail that matters most, and no severity score captures it: the flaw only works when a site has switched on a non-default option that hosts gravatar images locally. So the 17,000 sites that fell were not simply unpatched. They were unpatched and running one specific setting. A program that measures exposure by asking only "is the plugin current" cannot see that second dimension, and that dimension is what decided the outcome. Your real attack surface is a property of which plugins you run and how they are configured, not the severity number attached to this week's advisory.
27 ways in, one place to catch them
For a small team, patching 27 tracked vulnerabilities across a dozen plugins on every site you run is a race you will not win cleanly. The useful news hides in the same logs: every one of those entry paths funneled into a small, shared set of post-exploitation artifacts. That convergence is a defender's opening.
The primary webshell was dropped as a PHP file with a leading dot, so it hides from a casual directory listing, and the operators reused a handful of naming patterns across victims. A second-stage implant renamed its own process to [kworker/0:2] to pass as a routine Linux kernel worker thread. Both are cheap to catch. A real kernel thread has no program on disk, so any [kworker] process whose /proc/[pid]/exe resolves to an actual file is a strong signal of compromise. And a web root is a place where content changes on deploys, not at random, so a new PHP file appearing there between deploys is exactly what file integrity monitoring exists to flag.
This is the trade every defender should make on purpose. You can chase 27 patches across a moving fleet, or you can watch two things that all 27 exploits eventually touch: the files in your web root and the process table on the host. The first task is unbounded. The second is bounded. Pairing plugin patching with post-exploitation hunting is how you cover the window between the day a flaw is disclosed and the day you get to it. We made the same point when police scrubbed a webshell campaign off 15,000 WordPress sites while the way back in stayed open.
The louder crime was the cheaper one
The webshell brokerage is the visible half of this group's work, and probably the lower-value half. The same logs recorded an earlier, quieter campaign in May 2026 against enterprise Java systems, using a 2021 authentication-bypass flaw in Apache Nacos. Over two days the operators took 613 configuration files from 11 systems across nine organizations, walking off with cloud credentials for AWS, Alibaba, Oracle, and Tencent, production database strings, JSON web token secrets, and Alipay signing keys. Mass-backdooring WordPress sites for resale is a volume business with thin margins per site. Quietly lifting the keys to nine companies' cloud accounts is where the real money and the real damage sit, and it barely made the coverage. If you run self-managed Java services, that half of the story is the one to read twice.
It fits a run of WordPress incidents we have tracked this summer, from an unauthenticated file-upload bug in Super Forms to a paid plugin update that shipped a backdoor and a recycled account-takeover flaw in Branda. The plugins change. The economics do not.
Inventory your plugins, then watch the web root
Start with an honest inventory, and go past version numbers. List the plugins on every site, then note the non-default settings you have enabled, because those toggles are what turned a patchable flaw into 17,000 compromises here. Update or remove the plugins named in this operation: Breeze, ThemeREX Addons, Simple File List, Ninja Forms, WavePlayer, WPBookit, WP File Manager, and the Joomla JCE editor, among the 27 tracked. If you ever exposed an Apache Nacos instance, treat its stored credentials as burned and rotate them. Then set file integrity monitoring on your web roots and add a hunt for processes wearing kernel-thread names to your detection stack. The patch race is unwinnable on its own. The detection is not.