
🔥 XSS2Shell — Scanner CVE-2026-64638 e Toolkit PoC
Scanner di massa behavior-first e generatore di PoC di livello probatorio per la catena
XSS-to-RCE pre-autenticazione di WordPress che colpisce oltre 500 milioni di siti web.
Solo rilevamento. Nessuna weaponizzazione. Progettato per programmi bug bounty e blue team.
Cos'è? • Avvio rapido • Shodan Dorks • Utilizzo • Matrice decisionale • Rilevamento • FAQ
Caccia alle istanze WordPress potenzialmente vulnerabili su internet prima della scansione:
http.component:"wordpress" -http.title:"Just a moment"
Trova i siti WordPress escludendo le pagine della modalità "I'm Under Attack" / protezione bot di Cloudflare che bloccheranno o sottoporranno a sfida le richieste automatizzate.
http.component:"wordpress" http.title:"Log In"
Restituisce solo le pagine di login di WordPress — l'esatta superficie d'attacco di CVE-2026-64638.
http.component:"wordpress" "wp-content" "?ver=7.0" -"?ver=7.0.3"
Contrassegna le istanze WordPress 7.0.x senza la patch 7.0.3 tramite fingerprinting della versione delle risorse.
http.component:"wordpress" http.html:"wp-login.php"
Individua i siti in cui wp-login.php è raggiungibile ma potrebbe non essere la pagina corrente — copertura più ampia.
http.component:"wordpress" -http.title:"Just a moment" -http.title:"Attention Required" -org:"Cloudflare"
Filtro aggressivo che elimina la maggior parte dei target protetti da Cloudflare. Da usare quando si scansiona su larga scala con --active — Cloudflare limiterà la frequenza o bloccherà la richiesta del probe.
Suggerimento: Esporta i risultati di Shodan con
shodan downloade convoglia i nomi host direttamente inxss2shell_mass.py -i.
Il 7 agosto 2026, pwn.ai ha divulgato CVE-2026-64638 (XSS2Shell) — una vulnerabilità critica di cross-site scripting pre-autenticazione nel core di WordPress che si estende fino alla remote code execution sul server. [citazione: blog pwn.ai]
La vulnerabilità sfrutta un disaccordo di parsing tra strip_tags() di PHP e wp_kses_post() di WordPress:
strip_tags() usa < immediatamente seguito da una lettera per identificare i tag HTML. < area id=...> (con uno spazio) viene trattato come testo — sopravvive.wp_kses_post() (KSES) riconosce < area come un elemento <area> valido — e <area> è in allowlist in KSES. [citazione: blog pwn.ai]Un singolo login fallito con un nome utente appositamente costruito < area id=ajaxurl href=/?rest_route=/&_method=GET&_jsonp=alert>... bypassa entrambi i sanitizer, viene renderizzato come DOM attivo nella pagina di login, dirotta lo script user-profile.js di WordPress tramite DOM clobbering e attiva alert() nell'origine di WordPress — zero click, zero autenticazione, zero cookie richiesti. [citazione: blog pwn.ai]
Scalato a un amministratore autenticato? La stessa primitiva ruba le Application Password tramite Same Origin Method Execution (SOME), carica un plugin malevolo ed esegue PHP come www-data. [citazione: blog pwn.ai] [citazione: blog hadrian.io]
Versioni interessate: WordPress 6.4 fino a 7.0.2 — corretto nella 7.0.3 con backport fino alla 4.7+.
Impatto: ~500 milioni di siti web al momento della divulgazione. [citazione: blog pwn.ai]
| Risorsa | Link |
|---|---|
| Divulgazione originale (pwn.ai) | pwn.ai/blog/xss2shell |
| Analisi tecnica di Hadrian | hadrian.io/blog/wordpress-xss2shell |
| Advisory WordPress (GHSA) | GHSA-52p2-r8wf-jcrf |
| Ricerca sull'attacco SOME (2022) | pwn.ai/blog/bypass-csp-using-wordpress |
| Rilascio WordPress 7.0.3 | wordpress.org/news/2026/08/wordpress-7-0-3-release |
Questo è un toolkit solo per il rilevamento. Non weaponizza la vulnerabilità — offre a ricercatori di sicurezza, cacciatori di bug bounty e blue team tutto ciò che serve per:
"Una stringa di versione dice quale livello di patch il codice dovrebbe avere.
Solo il comportamento del sanitizer della pagina di login dice se la vulnerabilità si attiva."
Gli host gestiti applicano silenziosamente backport di sicurezza senza aggiornare le stringhe di versione. I plugin di hardening del login sostituiscono completamente il messaggio di errore, eliminando il canale di riflessione anche su versioni non sicure. Gli scanner basati solo sulla versione producono falsi positivi e falsi negativi. Questo scanner invia un singolo probe benigno e classifica il comportamento effettivo del sanitizer.
git clone https://github.com/jakestone/xss2shell.git
cd xss2shell
pip install -r requirements.txt
# 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
# 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/
Apri il file .poc.html generato nel tuo browser mentre registri un video → se alert() si attiva, hai catturato la prova dell'XSS pre-autenticazione.
xss2shell_mass.py)usage: xss2shell_mass.py [-h] -i INPUT [-o OUTPUT]
[--active] [--workers WORKERS]
[--timeout TIMEOUT] [--quiet]
| Flag | Descrizione |
|---|---|
-i, --input | File con un host per riga (dominio nudo o URL completo) |
-o, --output | Percorso base per i file di output (genera .csv + .json) |
--active | Abilita il probe comportamentale — un login fallito per host |
--workers | Dimensione del thread pool (default: 50, max ~200 per connessioni buone) |
--timeout | Timeout HTTP in secondi (default: 10) |
--quiet | Stampa solo confirmed_vulnerable, vulnerable e likely_vulnerable |
?ver= delle risorse, riferimenti wp-content)user-profile.js accodato, versioni degli asset del core/?rest_route=/&_method=GET&_jsonp=<random> — il canale JSONP è aperto?--active)Invia un singolo login fallito con nome utente < area id=<RANDOM> href=/x2s> e classifica la risposta HTML:
bypass — Un vero elemento <area> con il nostro marcatore è sopravvissuto → mancata corrispondenza strip_tags/KSES CONFERMATAescaped — Marcatore presente ma codificato come entità → patch o hardening presentistripped — Errore WP predefinito mostrato, tag rimossi → acevomod o patchatoclosed — Nessuna riflessione del nome utente → plugin di hardening del login installatomake_poc.py)usage: make_poc.py [-h] [--target TARGET] [--from-results FROM_RESULTS]
[-o OUTDIR]
Genera la pagina PoC pubblicata da pwn.ai per ogni target — l'esatto modulo HTML che attiva alert() su un WordPress non patchato. Tre varianti di payload sono incluse nei commenti:
| Variante | Valore href | Quando usarla |
|---|---|---|
| Predefinita | /?rest_route=/&_method=GET&_jsonp=alert | WordPress standard |
| Envelope | /?rest_route=/&_method=GET&_envelope=1&_jsonp=alert | REST restituisce 401 (avvolge la risposta in un 200) |
| Pivot WAF | /wp-json/wp/v2/statuses/publish?_jsonp=alert&_method=GET | ?rest_route= bloccato dal WAF |
Il motore decisionale dello scanner combina la classificazione della versione (dall'API stable-check di WordPress.org) con le prove comportamentali per produrre 10 verdetti distinti:
| Verdetto | Condizioni |
|---|---|
confirmed_vulnerable 🔴 | La versione non è sicura E il marcatore del probe è sopravvissuto come elemento <area> E il gadget user-profile.js è presente |
vulnerable 🔴 | Versione non sicura secondo wordpress.org; probe comportamentale NON eseguito (rieseguire con --active) |
likely_vulnerable 🟠 | Il marcatore del probe è sopravvissuto MA user-profile.js non è in coda (gadget auto-fire pubblicato mancante) |
mitigated 🟣 | Versione non sicura MA il marcatore del probe ha subito escape/rimozione/chiusura (backport silenzioso o hardening) |
likely_patched 🟢 | Versione nascosta/sconosciuta MA il marcatore del probe ha subito escape/rimozione |
patched 🟢 | La versione è latest o outdated (ha backport di sicurezza) |
not_wordpress ⚫ | Nessun fingerprint WordPress rilevato |
unreachable ⚫ | Connessione fallita (timeout, SSL, DNS) |
inconclusive 🟡 | Blocco WAF, sfida Cloudflare, versione nascosta senza probe o pagina di login assente |
error 🟡 | Errore imprevisto durante la scansione |
Colonne CSV: host, url, status, checker_status, wp_version, branch_status, evidence, http, ms, error
La colonna checker_status corrisponde al vocabolario del checker pubblico di pwn.ai (vulnerable / patched / not_wordpress / unreachable / inconclusive / error) per una correlazione diretta.
Se sei sul lato difensivo, ecco i segnali forensi che questa vulnerabilità lascia:
# Primary signal: encoded '<' in the log parameter
POST /wp-login.php → log=%3C... (URL-encoded < in username field)
# Higher confidence: paired with REST pivoting
GET /?rest_route=/&_method=GET&_jsonp=... # JSONP callback
GET /wp-json/wp/v2/statuses/publish?_jsonp=... # WAF-bypass variant
# Escalation stage indicators
GET /wp-admin/authorize-application.php?success_url=<off-origin>
POST /wp-admin/update.php?action=upload-plugin
GET /wp-content/plugins/<random>/shell.php
Blocca POST /wp-login.php quando il parametro log contiene %3C (< codificato in URL). I nomi utente WordPress validi non contengono mai parentesi angolari. Non restringere a tag specifici — KSES consente tabulazione, nuova riga e carriage return dopo < e qualsiasi tag in allowlist, quindi una regola specifica per tag è banalmente aggirabile. [citazione: blog hadrian.io]
La callback _jsonp= nella fase di escalation usa i punti per la traversata delle proprietà (es. window.opener.approve.click). Segnala le richieste REST con callback JSONP punteggiate come forti indicatori di sfruttamento. [citazione: blog hadrian.io]
THIS TOOL IS DETECTION-ONLY. IT DOES NOT:
✗ Weaponize the JSONP callback beyond the public alert()
✗ Include admin-lure pages or Application Password capture
✗ Include REST abuse, plugin upload, or PHP shell code
✗ Execute more than one failed login per target per scan
YOU MUST:
✓ Only scan assets you own or have written authorization to test
✓ Only generate PoCs for your own browser on your own server
✓ Never send PoC links to site admins/users
✓ Never escalate past alert() without program written approval
✓ Follow the bug bounty program scope and rules
This toolkit exists for authorized security research, bug bounty
programs, and defensive detection engineering. Misuse is your
responsibility.
xss2shell/
├── README.md ← You are here
├── xss2shell_mass.py ← Behavior-first mass scanner (v1.1.0)
├── make_poc.py ← Evidence-grade PoC page generator
├── requirements.txt ← Python dependencies (just `requests`)
├── .gitignore ← Ignores scan outputs and cache
└── example/
├── domains.txt ← Example input file
└── example_output.csv ← Example scan output
D: Perché non limitarsi a controllare la stringa di versione di WordPress?
R: Gli host gestiti (WP Engine, Kinsta, Pantheon, ecc.) applicano spesso backport di sicurezza senza aggiornare la versione. I plugin di hardening del login sostituiscono completamente il messaggio di errore. Entrambi i casi producono falsi positivi negli scanner basati solo sulla versione e falsi negativi per le versioni nascoste. Questo scanner testa il comportamento effettivo del sanitizer.
D: Il probe --active è pericoloso?
R: No. Invia esattamente un login fallito con un nome utente marcatore benigno. Non tenta di eseguire JavaScript, non enumera nomi utente validi e non attiva alcun exploit reale. È meno invasivo di un tentativo di login standard.
D: Questo strumento può essere usato per scansioni non autorizzate?
R: No. Il probe attivo invia una POST HTTP a /wp-login.php, che è una richiesta al server target. Usalo solo su asset di tua proprietà o per i quali hai esplicita autorizzazione scritta a testarli.
D: Qual è la differenza tra vulnerable e confirmed_vulnerable?
R: vulnerable significa che l'API di WordPress.org dice che la versione non è sicura, ma non abbiamo confermato comportamentalmente la mancata corrispondenza strip_tags/KSES. confirmed_vulnerable significa che abbiamo inviato un probe e l'elemento <area> è sopravvissuto a entrambi i sanitizer — la catena pubblicata può attivarsi.
D: Posso usarlo per i report del mio programma bug bounty?
R: Sì! La colonna checker_status corrisponde direttamente al vocabolario del checker pubblico di pwn.ai per una facile correlazione. Abbina i risultati della scansione alle prove video PoC di make_poc.py per report completi.
D: Questo strumento rileva la catena RCE?
R: No. Questo toolkit rileva il punto di ingresso XSS pre-autenticazione. La catena RCE completa richiede un amministratore autenticato, Application Passwords abilitate e permessi di upload dei plugin — condizioni che questo scanner non valuta. Lo scanner si concentra su ciò che è osservabile esternamente: il bypass del sanitizer.
Creato da 0xlipon • Solo rilevamento • Solo per uso autorizzato