{"uuid": "c62a0c6b-812e-4c9d-8157-66787b7a3e2a", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2025-49116", "type": "seen", "source": "https://gist.github.com/paolobarbolini/c332c93a8c8bfd060db55517d4829fd6", "content": "# Distributed Web-Scanner Campaigns \u2014 14-Day Observations (Public Version)\n\n**Window:** 2026-08-22 \u2192 2026-09-05 (14 days)\n**Source:** access logs of our HTTP load-balancer frontends, covering all publicly exposed sites and APIs.\n**Anonymization:** this version has been sanitized for publication \u2014 all client IP addresses and all internal hostnames, backend names, and proprietary paths/domains have been removed. Request volumes, timing, and publicly known scanner tool identities (user agents, CVEs, well-known probe paths) are preserved.\n\n**Headline:** during this window our edge absorbed a sustained, multi-vendor scanner load \u2014 roughly **210k rate-limited (429) requests from 600+ distinct clients**, thousands of malformed-request fuzzing attempts, and coordinated WordPress, secrets-file, and catch-all probing campaigns. **Every sensitive-path probe was blocked (400/403/429/422); no scanner obtained a successful response on any sensitive path.** The only 200s scanners got were on genuinely public content.\n\n---\n\n## 1. Coordinated port-80 API / SSRF probing (cloud-provider fleets)\n\nThe dominant campaign. Distributed, rate-limited by the edge, and still decaying at the end of the window.\n\n- **209,670 \u00d7 HTTP 429** from **603 distinct clients** on the public web frontends, all 08-22 \u2192 09-05.\n- Clients concentrated in **major cloud-provider and CDN IP ranges (Azure, Google Cloud, Akamai)** \u2014 i.e. scanner infrastructure running out of clouds, not residential networks.\n- Daily volume peaked at **~23,600 rate-limited requests/day (08-27/28)** and decayed to ~2,200/day by 09-04.\n- Burst behavior (per-minute spikes on our busiest frontends):\n  - **2,699 requests in one minute** (08-26 10:17) vs a ~8/min baseline\n  - 1,489 requests/min (08-26 03:55\u201303:58)\n  - single-client peak: **1,765 requests/min** from one cloud IP (08-25 14:14)\n- Probe profile (all blocked or redirected):\n  - WordPress file-manager and webshell names: `wp-content/plugins/hellopress/wp_filemanager.php` (3,611 hits), `this_is_a_new_hello_world.php` (3,453), random-name `.php` shells (`4PJcpMFsD8B.php`, `classwithtostring.php`, \u2026), `wp-login.php` (1,181).\n  - **SSRF-style endpoint enumeration**: `/api/fetch`, `/api/proxy`, `/api/download`, `/api/webhook`, `/api/preview` \u2014 ~50 hits each from the same ~24 clients.\n  - Malformed-request fuzzing: **22,536 unparseable requests** from 1,913 clients across all frontends, plus ~40 single-shot **random 4-letter \"HTTP methods\"** (`WJEL`, `QGGG`, `ERTO`, \u2026), **335 HTTP/0.9** probes, and 95 truncated-`H` requests.\n- Notable success: a **publicly hosted software-release file** on the edge was fetched **1,312 times by 142 distinct scanner clients** (HTTP 200). The scanners are mining public artifacts as expected \u2014 no sensitive data involved, but worth knowing your public files are inventorized.\n\n## 2. WordPress mass-scan (`wp-json/batch/v1`, CVE-2025-49116 style)\n\nA coordinated scan for the WordPress Batch API, run against multiple of our domains (which do not run WordPress on the affected paths):\n\n- ~**1,900 probes** across path-permutation variants \u2014 `/wp-json/batch/v1`, `/blog/wp-json/batch/v1`, `/wordpress/wp-json/batch/v1`, double-slash variants, casing variants (`Batch`), trailing slashes \u2014 from ~73 clients.\n- **All responses 400 / 404 / 429. Zero successes.**\n- On one legacy site the overall 4xx load from scanners grew from ~134/day (08-22) to **~1,275/day (09-01)** before dropping as the campaign rotated away; 74\u2013117 distinct client IPs per day.\n\n## 3. Secrets and credential-file scanning\n\nStandard \"dump the config\" wordlist probing, all blocked:\n\n- `/api/.env` \u2014 210 hits / 49 clients \u2192 **403**\n- `/api/.git/config` \u2014 81 hits / 66 clients \u2192 **403**\n- The full kit from a single persistent scanner (08-22 \u2192 08-28, ~3,000 requests across **every one of our frontends**): `/.env` (+ 10 `.env.*` variants), `/.git/config`, `/.git/HEAD`, `/.aws/credentials`, `/.npmrc`, `/.git-credentials`, `/terraform.tfstate`, `/appsettings.json`, `/actuator/env`, `/phpinfo.php`, `/info.php` \u2014 every hit returned 302/400/403/429.\n- Additional 422-blocked probes from cloud-provider IPs against deeper paths (e.g. `/var/www/.git/config`, `/.dev.vars`, `/.esmtprc`).\n\n## 4. Catch-all / unknown-Host probing (trending up)\n\nClients sending **no valid Host header at all** \u2014 raw IPv4 addresses, bracketed IPv6 addresses, `host:443` forms, reverse-DNS names \u2014 landing on our default catch-all vhost (all returned 400):\n\n- 15,862 hits from **648 distinct clients** in the window.\n- **Trending up during the window: ~850/day (08-30) \u2192 ~1,650/day (09-04).**\n- Scanner identities in the user agents: the **L9 scanner family** (`l9tcpid`, `l9explore` \u2014 ~5,000 hits), **Censys**, `CyberConvoyScout` (one persistent IPv6 client polling at a steady ~1 request/10 min for all 14 days), `jscrawler`, and spoofed ancient Firefox UAs.\n\n## 5. Cross-host scanners (hit every frontend)\n\nA smaller set of clients probed **all of our load-balancer frontends** during the window. Identifying signals (IPs omitted):\n\n| Scanner signature | Behavior | Errors generated |\n|---|---|---|\n| Fake 2004-era UA `Mozilla/5.0 (Windows; \u2026; rv:1.7) Gecko/20040803 Firefox/0.9.3` | Steady multi-host probing, all 7 frontends | 3,740 hits |\n| (secrets-kit scanner from \u00a73) | Full wordlist across all frontends | 1,652 |\n| Rotating browser UAs | Multiple distinct fake UAs per session | 1,268 / 1,103 |\n| `visionheight.com/scan` (cloud-hosted) | Fleet of ~7 workers | ~700 |\n| `FlowIQLabsBot` | Declared scanner, still probing everything | 114 |\n| (unidentified) | 355 errors within 36 h | 355 |\n\n## 6. Protocol fuzzing (low volume, continuous)\n\n- `PROPFIND` (WebDAV probing): 65 total, mostly one client.\n- `SSTP_DUPLEX_POST` (non-standard method probing): 37 hits / ~26 clients.\n- `CONNECT` (proxy/tunnel probing): 161 hits / 34 clients \u2014 **all answered 302; no tunnel was established**.\n\n## 7. Unidentified steady IPv6 poller\n\nA stream of ~**200 distinct IPv6 clients** sending bracketed-IPv6 addresses as the Host header, each issuing `GET /` at a near-constant ~7 requests/min per frontend, starting 08-22 ~09:59 and running unbroken through 09-05 (~145k requests total, overwhelmingly 302 responses), with small interleaved Censys-style vulnerability-path probes. The rate and perfect regularity are atypical of manual browsing or declared crawlers. **Origin unconfirmed** \u2014 either a large monitoring/scan platform or misconfigured IPv6 clients. Flagged for follow-up.\n\n---\n\n## Defense outcomes\n\n| Control | Result |\n|---|---|\n| Edge rate limiting (429) | 209,751 requests throttled across the window |\n| WAF / path rules (403, 422) | All secrets-file and config probes blocked |\n| Default catch-all (400 on unknown Host) | 15.9k misdirected/attack requests rejected |\n| Redirect default (302) | 302-answered probes (CONNECT, PROPFIND, legacy scanners) never reached backends |\n\n**Zero successful (2xx) responses to any scanned sensitive path.** The only scanner-visible successes were on intentionally public content (homepage redirects and one public release artifact).\n\n## Takeaways for operators\n\n1. **Cloud-provider IP space is the dominant scanner substrate** \u2014 most of the load in \u00a71 originates from Azure/GCP/Akamai ranges; edge-level ASN or per-IP rate limiting is the effective control.\n2. **Per-IP rate limits get gamed by botnet-scale fleets** (600+ clients), but per-minute spike capping (as exercised in \u00a71) contained the worst bursts (2,700/min \u2192 no backend impact observed).\n3. **WordPress batch-API scanning is a standing background noise** across any internet-facing estate; non-WordPress paths should answer 404, not 5xx, to keep the signal clean.\n4. **Public artifacts (release files, sitemaps) are inventory targets** \u2014 assume everything served with 200 is fingerprinted daily.\n5. **Catch-all vhost traffic can be a leading indicator**: it was the only campaign with a clear *rising* trend over the 14 days.\n\n*All client identifiers removed before publication. Volume figures, timings, and scanner user-agent strings are as recorded by our edge.*\n", "creation_timestamp": "2026-09-05T10:20:06.336863Z"}