## https://sploitus.com/exploit?id=DDC081B9-F006-5916-9D90-943695587499
π₯ XSS2Shell β CVE-2026-64638 Scanner & PoC Toolkit
Behavior-first mass scanner and evidence-grade PoC generator for the WordPress
pre-auth XSS-to-RCE chain affecting 500M+ websites.
Detection only. No weaponization. Built for bug bounty programs and blue teams.
Official Checker: https://pwn.ai/xss2shell-checker.html
What is this? β’
Quick Start β’
Shodan Dorks β’
Usage β’
Decision Matrix β’
Detection β’
FAQ
---
## π Shodan Dorks
Hunt for potentially vulnerable WordPress instances across the internet before scanning:
### Core WordPress Discovery
```
http.component:"wordpress" -http.title:"Just a moment"
```
Finds WordPress sites while excluding Cloudflare "I'm Under Attack" mode / bot-protection pages that will block or challenge automated requests.
### Narrow to Login Pages
```
http.component:"wordpress" http.title:"Log In"
```
Returns only WordPress login pages β the exact attack surface for CVE-2026-64638.
### Version-Specific Hunting
```
http.component:"wordpress" "wp-content" "?ver=7.0" -"?ver=7.0.3"
```
Flags WordPress 7.0.x instances without the 7.0.3 patch by asset version fingerprinting.
### Widen the Surface
```
http.component:"wordpress" http.html:"wp-login.php"
```
Catches sites where wp-login.php is reachable but may not be the current page β broader coverage.
### Cloudflare Exclusions (Combined)
```
http.component:"wordpress" -http.title:"Just a moment" -http.title:"Attention Required" -org:"Cloudflare"
```
Aggressive filter that strips out most Cloudflare-fronted targets. Use when scanning at scale with `--active` β Cloudflare will rate-limit or block the probe request.
> **Tip:** Export Shodan results with `shodan download` and pipe the hostnames directly into `xss2shell_mass.py -i`.
---
## π¨ What Is CVE-2026-64638?
On August 7, 2026, **pwn.ai disclosed CVE-2026-64638 (XSS2Shell)** β a critical pre-authentication cross-site scripting vulnerability in WordPress Core that chains all the way to **remote code execution** on the server. [citation:pwn.ai blog]
The bug exploits a parser disagreement between PHP's `strip_tags()` and WordPress's `wp_kses_post()`:
- **`strip_tags()`** uses `` (with a space) is treated as **text** β it survives.
- **`wp_kses_post()`** (KSES) recognizes `` element β and `` is **allowlisted** in KSES. [citation:pwn.ai blog]
One failed login with a specially crafted username `...` bypasses both sanitizers, gets rendered as live DOM on the login page, hijacks WordPress's own `user-profile.js` script via DOM clobbering, and fires `alert()` in the WordPress origin β **zero clicks, zero authentication, zero cookies required**. [citation:pwn.ai blog]
Escalated to a logged-in administrator? The same primitive steals Application Passwords via Same Origin Method Execution (SOME), uploads a malicious plugin, and executes PHP as `www-data`. [citation:pwn.ai blog] [citation:hadrian.io blog]
> **Affected:** WordPress 6.4 through 7.0.2 β patched in 7.0.3 with backports to 4.7+.
> **Impact:** ~500 million websites at time of disclosure. [citation:pwn.ai blog]
### π° Key Resources
| Resource | Link |
|---|---|
| **Original Disclosure (pwn.ai)** | [pwn.ai/blog/xss2shell](https://pwn.ai/blog/xss2shell) |
| **Hadrian Technical Analysis** | [hadrian.io/blog/wordpress-xss2shell](https://hadrian.io/blog/wordpress-xss2shell-unauthenticated-login-screen-xss-to-php-code-execution-cve-2026-64638) |
| **WordPress Advisory (GHSA)** | [GHSA-52p2-r8wf-jcrf](https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-52p2-r8wf-jcrf) |
| **SOME Attack Research (2022)** | [pwn.ai/blog/bypass-csp-using-wordpress](https://pwn.ai/blog/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution) |
| **WordPress 7.0.3 Release** | [wordpress.org/news/2026/08/wordpress-7-0-3-release](https://wordpress.org/news/2026/08/wordpress-7-0-3-release/) |
---
## β‘ What This Toolkit Does
This is a **detection-only** toolkit. It does not weaponize the vulnerability β it gives security researchers, bug bounty hunters, and blue teams everything needed to:
1. **Mass-scan** hundreds of WordPress hosts in minutes with behavioral-first accuracy
2. **Generate evidence-grade PoC pages** to prove the XSS fires (alert() only)
3. **Classify findings** with precise confidence levels β no false positives from version-matching
### π Why Behavior-First?
> "A version string says what patch level the code *should* be.
> Only the login-page sanitizer behavior says whether the bug *fires*."
Managed hosts silently backport security patches without bumping version strings. Login-hardening plugins replace the error message entirely, killing the reflection channel even on insecure versions. **Version-only scanners produce false positives and false negatives.** This scanner sends a single benign probe and classifies the *actual sanitizer behavior*.
---
## π Quick Start
### Installation
```bash
git clone https://github.com/jakestone/xss2shell.git
cd xss2shell
pip install -r requirements.txt
```
### 5-Minute Scan
```bash
# Passive β no probes sent to target, version + endpoint fingerprinting only
python3 xss2shell_mass.py -i domains.txt -o results
# Active β sends ONE benign failed-login per host (authorized assets only!)
python3 xss2shell_mass.py -i domains.txt -o results --active --workers 80
```
### Generate Evidence PoCs
```bash
# Single target
python3 make_poc.py --target https://blog.example.com
# Batch from scanner output
python3 make_poc.py --from-results results.csv -o pocs/
```
Open the generated `.poc.html` in your browser while recording video β if `alert()` fires, you've captured pre-auth XSS evidence.
---
## π Usage
### Mass Scanner (`xss2shell_mass.py`)
```
usage: xss2shell_mass.py [-h] -i INPUT [-o OUTPUT]
[--active] [--workers WORKERS]
[--timeout TIMEOUT] [--quiet]
```
| Flag | Description |
|---|---|
| `-i, --input` | File with one host per line (bare domain or full URL) |
| `-o, --output` | Base path for output files (generates `.csv` + `.json`) |
| `--active` | Enable behavioral probe β one failed login per host |
| `--workers` | Thread pool size (default: 50, max ~200 for good connections) |
| `--timeout` | HTTP timeout in seconds (default: 10) |
| `--quiet` | Only print `confirmed_vulnerable`, `vulnerable`, and `likely_vulnerable` |
#### Passive Scan Evidence (no active probe, always collected)
1. **Homepage** β WordPress fingerprint (meta generator, asset `?ver=` params, wp-content references)
2. **Login page** β Reachability, stock login form detection, `user-profile.js` gadget enqueued, core asset versions
3. **REST JSONP smoke test** β Harmless GET on `/?rest_route=/&_method=GET&_jsonp=` β is the JSONP pathway open?
4. **Feed/Readme fallback** β Version extraction if homepage fingerprint is missing
#### Active Probe (one POST, `--active` flag)
Sends a single failed login with username ` href=/x2s>` and classifies the HTML response:
- **`bypass`** β Real `` element with our marker survived β strip_tags/KSES mismatch CONFIRMED
- **`escaped`** β Marker present but entity-encoded β patch or hardening present
- **`stripped`** β Default WP error shown, tags removed β `acevomod` or patched
- **`closed`** β No username reflection at all β login-hardening plugin installed
### PoC Generator (`make_poc.py`)
```
usage: make_poc.py [-h] [--target TARGET] [--from-results FROM_RESULTS]
[-o OUTDIR]
```
Generates the **published pwn.ai PoC page** for each target β the exact HTML form that triggers `alert()` on an unpatched WordPress. Three payload variants are included in comments:
| Variant | `href` value | When to use |
|---|---|---|
| **Default** | `/?rest_route=/&_method=GET&_jsonp=alert` | Standard WordPress |
| **Envelope** | `/?rest_route=/&_method=GET&_envelope=1&_jsonp=alert` | REST returns 401 (wraps in 200) |
| **WAF Pivot** | `/wp-json/wp/v2/statuses/publish?_jsonp=alert&_method=GET` | `?rest_route=` blocked by WAF |
---
## π§ Decision Matrix
The scanner's decision engine combines version classification (from WordPress.org's stable-check API) with behavioral evidence to produce 10 distinct verdicts:
| Verdict | Conditions |
|---|---|
| **`confirmed_vulnerable`** π΄ | Version is insecure AND probe marker survived as `` element AND `user-profile.js` gadget is present |
| **`vulnerable`** π΄ | Version is insecure per wordpress.org; behavioral probe NOT run (re-run with `--active`) |
| **`likely_vulnerable`** π | Probe marker survived BUT `user-profile.js` not enqueued (published auto-fire gadget missing) |
| **`mitigated`** π£ | Version is insecure BUT probe marker was escaped/stripped/closed (silent backport or hardening) |
| **`likely_patched`** π’ | Version hidden/unknown BUT probe marker was escaped/stripped |
| **`patched`** π’ | Version is `latest` or `outdated` (has security backports) |
| **`not_wordpress`** β« | No WordPress fingerprint detected |
| **`unreachable`** β« | Connection failed (timeout, SSL, DNS) |
| **`inconclusive`** π‘ | WAF block, Cloudflare challenge, hidden version without probe, or login page absent |
| **`error`** π‘ | Unexpected failure during scan |
### Output Format
**CSV columns:** `host`, `url`, `status`, `checker_status`, `wp_version`, `branch_status`, `evidence`, `http`, `ms`, `error`
The `checker_status` column maps to the **pwn.ai public checker's vocabulary** (`vulnerable` / `patched` / `not_wordpress` / `unreachable` / `inconclusive` / `error`) for direct correlation.
---
## π Detection Signatures (Blue Team / SOC)
If you're on the defending side, here are the forensic signals this vulnerability leaves:
### Server-Side (Web Server / WAF Logs)
```
# Primary signal: encoded '
POST /wp-admin/update.php?action=upload-plugin
GET /wp-content/plugins//shell.php
```
### Edge / WAF Blocking Rule
Block `POST /wp-login.php` where the `log` parameter contains `%3C` (URL-encoded `` element survived both sanitizers β **the published chain can fire**.
**Q: Can I use this for my bug bounty program reports?**
A: Yes! The `checker_status` column maps directly to pwn.ai's public checker vocabulary for easy correlation. Pair scan results with PoC video evidence from `make_poc.py` for complete reports.
**Q: Does this detect the RCE chain?**
A: No. This toolkit detects the **pre-auth XSS entry point**. The full RCE chain requires a logged-in administrator, Application Passwords enabled, and plugin upload permissions β conditions this scanner does not evaluate. The scanner focuses on what's externally observable: the sanitizer bypass.
---
## π Credits & References
- **Discovery & Disclosure:** [pwn.ai](https://pwn.ai) β autonomously discovered by a multi-agent AI system
- **SOME Technique Foundation:** [Paulos Yibelo](https://x.com/@paulosyibelo) β 2022 research nominated for Top Web Hacking Techniques
- **Technical Analysis:** [Hadrian](https://hadrian.io) β comprehensive detection and mitigation guidance
- **CVE:** CVE-2026-64638 / GHSA-52p2-r8wf-jcrf
- **Patch:** [WordPress 7.0.3](https://wordpress.org/news/2026/08/wordpress-7-0-3-release/)
---
Built by 0xlipon β’ Detection-only β’ For authorized use only