TI-2026-095H โ The Seven: Exploit Breadth and the Toolkit Families Behind the Web Attacks
Classification: HIGH ยท Forensic threat intelligence ยท Web-threats vector ยท Series: Below the Noise Floor
The previous seven letters each held up one campaign. This one steps back and asks a single question of all of them at once: when an IP throws an exploit at us, how many other exploits does it throw? The answer is sharper than folklore expects. Out of 318 web attackers, two-thirds throw exactly one. Ninety-nine throw two. Seven throw three. None throws four. And the moment you look at which exploits the versatile few combine, the anonymous mass resolves into something clean: not a spectrum of skill, but three separate toolkits, each run by its own operators, that never touch each other's tools. This is the map under the series.
1. One Question, Asked of Everyone
Every earlier letter was a portrait: the /dev/tcp dropper, the tunnel scout, the Equifax ghost, the config vultures, the roll call, the siege. Each was one campaign, examined closely. But a portrait cannot tell you how the subjects relate โ whether the config vultures and the Struts2 fleet are the same people in different clothes, or genuinely different populations.
The web-threats CVE-correlation engine lets us ask the relational question directly. It records, per IP, every CVE that IP was seen targeting. So intersect the actor rosters of every web CVE โ eleven of them, from the 2005 XML-RPC RCE to the 2023 git flaw โ and you get, for each of 318 distinct attacker IPs, its full set of exploits. The breadth of that set, and the composition of it, is the subject of this letter.
It is a synthesis, not a campaign. There is no single fleet here. There is the shape of all of them.
2. The Power Law: Most Attackers Know One Trick
The first result is the distribution of breadth, and it is steep:
| Exploits thrown | Number of IPs | Share |
|---|---|---|
| 1 CVE | 212 | 67% |
| 2 CVEs | 99 | 31% |
| 3 CVEs | 7 | 2% |
| 4+ CVEs | 0 | 0% |
Two-thirds of the population throws exactly one exploit. Not a repertoire โ a single canned request, fired at everyone, forever. Another third throws two. And the entire "versatile" tail of the internet's web-attack traffic against this estate is seven addresses, each of which stops at three.
This cuts against the intuition of the omnivorous scanner that "throws everything." The overwhelming majority of web attackers are single-purpose tools: one exploit, one payload, run at scale by an operator who found something that works and does only that. The generalist is not the rule; the generalist barely exists.
There is an immediate, useful corollary. Because most IPs are single-exploit specialists, the one exploit you observe from an IP is, most of the time, its whole repertoire. When you see an IP POST to xmlrpc.php, you have โ two times in three โ seen everything it will ever do. And the rare IP that shows you a second, or a third, is by that fact disproportionately worth your attention.
3. The Sharper Result: Breadth Never Leaves the Family
The distribution alone is interesting. The composition is the finding.
Look at who the versatile IPs combine, and the overlap graph does not form one connected blob of shared tooling. It forms three separate components โ three toolkit families โ and no IP bridges them.
Family one โ WordPress / xmlrpc / PHP-legacy. All seven of the triple-polyglots live here. Their exploit sets are drawn from CVE-2005-1921 (XML-RPC RCE), CVE-2007-1893, CVE-2010-0397 (PHP xmlrpc DoS), and CVE-2017-5487 (WordPress user enumeration):
90.156.142.60,5.101.157.130(BeGet, Russia),62.164.177.224(the /24 cluster),159.89.172.177,47.93.192.43โ all three of2005-1921 + 2007-1893 + 2010-0397.157.22.126.251and146.19.78.227โ2005-1921 + 2007-1893 + 2017-5487. These two are the shared addresses that, in the previous letters, linked the roll call (095F user enumeration) to the siege (095G xmlrpc POST). Here they resolve as what they are: WordPress-family generalists.
This family is offshore-weighted (BeGet, the /24 cluster, the ColocaTel Seychelles anchor from 095F), wears browser user-agents, and persists for weeks. It runs the full WordPress kit โ read the register, find xmlrpc, POST the amplified brute-force. And it never, once, throws Struts2 or PHPUnit.
Family two โ the RCE-sweep. The Struts2 + Spring-actuator pair (CVE-2017-5638 + CVE-2018-1273). These are the one-node-per-host cloud fleets of the Equifax-ghost (095D, DigitalOcean) and config-vultures (095E, Google Cloud) letters: 142.93.143.8 (turn.shuffle-on.com), 167.172.232.142 (lsn-wifi), 167.99.181.249 (mail.sonatural.life) and their kin, each throwing both the Struts OGNL RCE and the actuator secret-sweep, each partitioning the estate one node per subdomain. And they never throw WordPress or PHPUnit.
Family three โ PHP-RCE. The PHPUnit + Laravel + ThinkPHP trio (CVE-2017-9841 / 2021-3129 / 2018-20062) โ the weaponizers of 095C, the only CVEs the entity graph promoted to first-class targets edges. Their heaviest node, 209.182.216.63 (Kamatera, 10,920 hits), throws two of the three. And they never throw xmlrpc or Struts2.
Three families. Overlap inside each; zero overlap between. A WordPress operator is never a Struts2 operator. A Struts2 fleet never reaches for PHPUnit. The versatility that exists is entirely intra-family.
4. What the Structure Means
That disjointness is not what you would see if the web-attack population were one big pool of scanners rotating through a shared exploit database. If it were, breadth would smear across families โ you would find IPs that throw a WordPress probe and a Struts payload and a PHPUnit POST, because a generic scanner does not care which framework it is hitting. Instead the boundaries are clean. The exploits an IP combines are always from one toolkit, never mixed.
The honest reading is that these are three distinct operator ecosystems, each with its own tooling, its own hosting posture, and its own target logic:
- The WordPress family rents offshore/bulletproof-adjacent boxes, wears browser identities, swarms single hosts, and runs a recon-then-siege kit โ because WordPress attacks are a mature, commodity, credential-driven economy with its own toolchains.
- The RCE-sweep family rents clean mainstream cloud (DigitalOcean, Google Cloud), partitions the estate one node per host, and hunts framework RCE and exposed secrets โ a different economy with a different tool.
- The PHP-RCE family reaches for genuine, promotable code execution against modern PHP frameworks โ the sharpest and rarest end.
Exploit breadth, in other words, is not a measure of an attacker's skill. It is a signature of their toolkit membership. And because the families are disjoint and internally coherent, that signature is a cheap, reliable attribution primitive: an IP's exploit set names its family, and its family predicts the rest of its kit and its likely next move โ better than any single request ever could.
5. The Series, Resolved Into a Taxonomy
This is why the letter closes the arc. The seven case studies were not seven unrelated curiosities; they were samples from three populations, and the breadth graph proves the populations are real and separate:
- PHP-RCE family โ TI-2026-095C (the weaponizers).
- RCE-sweep family โ TI-2026-095D (Equifax-ghost Struts2) and TI-2026-095E (config-vultures actuator).
- WordPress/xmlrpc family โ TI-2026-095F (the roll call) and TI-2026-095G (the siege).
The campaigns did not overlap because the operators do not overlap. Struts2 fleets and WordPress swarms hit the same estate in the same months and never shared a single IP, because they are different people running different tools for different ends. The individual dossiers showed what each did; this one shows that they are genuinely three, not one โ and gives the population a map.
6. The Counter-Narrative
Steelman: "This is an artefact of your dictionary. You only correlate eleven CVEs; of course breadth looks small and families look clean โ you're not measuring the attackers, you're measuring your own signature set. And 'seven' is a rounding error."
The objection is fair on its face and the finding survives it, with caveats stated:
- "Artefact of the dictionary." Partly true, and bounded: the absolute breadth numbers depend on how many CVEs the engine tracks, so "seven triple-polyglots" is specific to this eleven-CVE lens, not a universal constant. But the structural result โ that breadth clusters into disjoint families and never crosses them โ does not depend on the dictionary's size. Even within eleven CVEs spanning WordPress, Struts, PHP frameworks and actuator, the families could have smeared together; they did not. The disjointness is the finding, and it is robust to the count.
- "Seven is a rounding error." The seven are not the point โ the shape is. 212 : 99 : 7 : 0 is a steep, short power law, and the direction of it (specialists dominate, generalism is shallow and in-family) is the claim, not the exact tail length.
- "You're measuring yourself." To a degree every honeypot does; we say so. But the target set is one real estate, seen by one instrument, over the same window for all three families โ a fair internal comparison, and the families' different hosting and tradecraft (offshore swarm vs single-cloud partition vs mixed-cloud RCE) is independent corroboration that they are distinct populations, not a measurement artefact.
What is not claimed: that the three families are the only web-attacker toolkits (they are the ones resolvable in this CVE set); that no operator anywhere bridges them (only that none did against this estate in this window); or named attribution for any family (the anchors are hosting postures and toolkits, not people).
Confidence: HIGH that exploit breadth across the 318-IP, 11-CVE population is a steep power law and that breadth clusters into three disjoint toolkit families with no cross-family IP; MEDIUM on the interpretation that these are three fully separate operator ecosystems rather than partly-shared tooling.
7. Defence Response
- Resolve an IP to its family, then act on the family's playbook. The single request under-describes the attacker; the exploit set names the toolkit, and the toolkit predicts the rest. A WordPress-family IP seen enumerating will POST xmlrpc next (095Fโ095G); an RCE-sweep IP will move host to host; a PHP-RCE IP is reaching for code execution now. Triage on the family, not the packet.
- Weight the rare generalist. Two-thirds of attackers are single-exploit specialists whose one observed request is their whole story. The IP that shows you a second or third exploit is rare and disproportionately worth investigating โ it is a more committed operator, not a stray scanner.
- Harden per family, because the families are stable. The three toolkits map to three hardening tracks: disable WordPress enumeration +
xmlrpc.php(family one), keepvendor//actuator/Struts paths unreachable and patch the KEV long tail (family two), and WAF the PHPUnit/Laravel/ThinkPHP RCE endpoints (family three). The families don't mix, so the defences compose cleanly.
8. A Note on Method
Built entirely through the web-threats MCP layer, with no direct database access โ the per-CVE actors endpoint (wt_cve_actors / GET /api/web-threats/cves/{cve}) fetched for eleven CVEs and intersected on source IP to build the exploit set of each of the 318 attackers. The breadth distribution and the family structure fall straight out of that intersection โ the same cross-CVE correlation that proved the 095Fโ095G link, generalised to the whole population. This letter is the reason the per-CVE endpoint was worth building: it turns a pile of single-campaign observations into a taxonomy.
9. Investigation Metadata
| Field | Value |
|---|---|
| Dossier ID | TI-2026-095H |
| Series | Below the Noise Floor (part 8 โ synthesis) |
| Population | 318 distinct web-attacker IPs across 11 CVEs |
| Breadth | 212 threw 1 CVE ยท 99 threw 2 ยท 7 threw 3 ยท 0 threw 4+ |
| Families (disjoint) | WordPress/xmlrpc (all 7 triples) ยท RCE-sweep (Struts2+actuator) ยท PHP-RCE (PHPUnit/Laravel/ThinkPHP) |
| Key finding | Breadth clusters into three toolkit families and NEVER crosses them โ exploit set = family membership |
| Notable IPs | 5.101.157.130 (BeGet, WP-family triple) ยท 209.182.216.63 (Kamatera, PHP-RCE, 10,920 hits) ยท 142.93.143.8 (DO, RCE-sweep) ยท 146.19.78.227 / 157.22.126.251 (the 095Fโ095G link, WP-family) |
| Maps to | PHP-RCE=095C ยท RCE-sweep=095D/E ยท WordPress/xmlrpc=095F/G |
| Method | Built entirely via the web-threats MCP layer (11-CVE roster intersection) โ no direct SQL |
| Confidence | HIGH (power law + disjoint families); MEDIUM (three-separate-ecosystems interpretation) |
Cristian Liศneanu ยท shuffle-on.com ยท Threat Intelligence