
Analyse WordPress Core 4.7.0–7.1.1 pour la LFI non authentifiée CVE-2026-87902 via un traversal pagename doublement encodé, avec escalade RCE optionnelle via PEAR config-create et analyse de masse.
Outil d'exploitation de traversée de répertoires pour get_page_template() / locate_template() du cœur de WordPress
Réservé aux tests de sécurité autorisés. Tout accès non autorisé à des systèmes informatiques est illégal.
| Élément | Détails |
|---|---|
| ID CVE | CVE-2026-87902 |
| ID GHSA | GHSA-7hp8-65ch-5whp |
| Type de vulnérabilité | CWE-98 — Contrôle inapproprié du nom de fichier pour Include/Require |
| CVSS v3.1 | 8.1 (Élevé) / CVSS 4.0 : 9.2 (Critique) |
| Composant affecté | Cœur de WordPress |
| Versions affectées | 4.7.0 à 7.1.1 (toutes les branches) |
| Versions corrigées | 7.1.2 (et rétroportages jusqu'à 4.7.37) |
| Authentification requise | Aucune (non authentifiée) |
| Vecteur d'attaque | Une seule requête GET |
| Découverte par | Robert Ressl (via le programme HackerOne de WordPress) |
| Date de divulgation | 22 septembre 2026 |
| Exploitée dans la nature | Oui — répertoriée dans le catalogue CISA KEV |
CVE-2026-87902 est une vulnérabilité de traversée de répertoires et d'inclusion de fichier local (LFI) non authentifiée dans le cœur de WordPress qui affecte toutes les versions de WordPress publiées depuis 2016 (4.7.0 à 7.1.1). Un attaquant n'a besoin d'aucun compte ni d'aucune authentification. En forgeant un paramètre de requête pagename malveillant, l'attaquant peut amener le mécanisme de résolution de modèle de page de WordPress à inclure n'importe quel fichier .php lisible en dehors du répertoire du thème actif. Dans certaines conditions serveur (PHP register_argc_argv = On et un fichier pearcmd.php lisible), la vulnérabilité peut être escaladée en exécution de code à distance (RCE).
| Branche | Version corrigée |
|---|---|
| 4.7.x | 4.7.37 |
| 5.0.x | 5.0.29 |
| 5.3.x | 5.3.25 |
| 5.9.x | 5.9.18 |
| 6.0.x | 6.0.16 |
| 6.6.x | 6.6.9 |
| 6.9.x | 6.9.9 |
| 7.0.x | 7.0.6 |
| 7.1.x | 7.1.2 |
La vulnérabilité réside dans get_page_template() dans wp-includes/template.php. Lorsque la variable de requête pagename est présente, la fonction construit page-{$pagename}.php mais omet d'appeler validate_file() sur cette valeur pour détecter une traversée de répertoires. Le nom de fichier candidat est ensuite transmis à locate_template(), qui le concatène avec le chemin du répertoire du thème et se contente de vérifier file_exists() — elle ne vérifie pas que le chemin résolu reste à l'intérieur du répertoire du thème. Un nom de modèle contenant ../ peut donc se résoudre en un fichier PHP lisible en dehors du thème actif, puis être inclus et exécuté.
GET /?page_id=&pagename= → WP_Query resolves page_id, matches a published page (avoids 404) → get_page_template() urldecode()s pagename, builds page-{$pagename}.php → locate_template() concatenates candidate to theme directory, resolves via file_exists() → template-loader executes realpath() + include
WordPress applique sanitize_title_for_query() à pagename, qui remplace les points littéraux (.) par des traits d'union (-) pour bloquer la traversée. Cette fonction opère sur une entrée déjà décodée une fois et ne décode pas récursivement. L'attaquant envoie %252e%252e%252f (../ doublement encodé) :
%252e → %2e, %252f → %2fsanitize_title_for_query() voit %2e%2e%2f (aucun point littéral) et le laisse passerget_page_template() appelle ensuite urldecode() en interne : %2e%2e%2f → ../page- (par exemple, page-templates/).page_id..php (WordPress ajoute l'extension).Note sur les hôtes Windows : Win32 normalise .. de manière lexicale, de sorte que la traversée peut fonctionner même si le répertoire page- n'existe pas. Sous Linux, ce répertoire doit réellement exister.
Conditions :
register_argc_argv est défini sur Onpearcmd.php lisible existe sur le serveurL'attaquant inclut pearcmd.php via LFI et abuse de sa commande config-create pour écrire un fichier PHP sur le serveur, puis inclut à nouveau ce fichier via LFI pour exécuter des commandes arbitraires.
CVE-2026-87902 a été découverte et signalée par Robert Ressl, un chercheur en sécurité basé en Suisse.
Signalée via le programme HackerOne de WordPress en juillet 2026. L'équipe de sécurité de WordPress a coordonné le correctif et l'a publié en même temps que WordPress 7.1.2 le 22 septembre 2026.
| Date | Événement |
|---|---|
| Juillet 2026 | Robert Ressl signale la vulnérabilité via le programme HackerOne de WordPress |
| 22 septembre 2026 | WordPress 7.1.2 publié avec le correctif ; l'avis de sécurité est publié |
| 22 septembre 2026 | Correctifs de sécurité rétroportés publiés pour les branches 7.0 à 4.7 |
| 23 septembre 2026 | Les attaquants commencent à sonder les sites vulnérables |
| 25 septembre 2026 | La CISA ajoute CVE-2026-87902 au catalogue KEV |
| Fonctionnalité | Description |
|---|---|
| Empreinte de version | Identifie la version de WordPress via la balise meta generator, le flux RSS, OPML, readme.html, le paramètre ?ver= des ressources |
| Verdict intelligent sur la version | Utilise une correspondance des versions corrigées pour déterminer si la cible se situe dans la plage affectée |
| Découverte du thème | Extrait le slug du thème actif, détecte le thème parent, découvre les répertoires page-* |
| Découverte des ID de page | Trouve les ID de page valides via l'API REST, la classe de corps page-id-, les liens courts |
| Validation de l'oracle LFI | Utilise des fichiers sûrs comme wp-links-opml.php et wp-trackback.php comme oracles avec des contrôles négatifs |
| Traversée doublement encodée | Encode automatiquement en double pourcentage / et . afin de contourner sanitize_title_for_query() |
| Exploitation RCE via PEAR | Essaie les chemins PEAR courants, écrit et exécute des fichiers marqueurs via config-create |
| Analyse de masse | Analyse concurrente multithread de listes de cibles |
| Sortie des résultats | Persiste les résultats dans vuln_lfi.txt et vuln_lfitorce.txt |
pip install requests
python3 CVE-2026-87902.py
Menu interactif :
[1] Analyse unique LFI [2] Analyse unique LFI + RCE [3] Analyse de masse LFI [4] Analyse de masse LFI + RCE [5] Quitter
Choisissez [1], saisissez l'URL cible :
url > https://target.example.com
Choisissez [2], saisissez l'URL et la commande (par défaut id) :
url > https://target.example.com cmd > id
Choisissez [3] ou [4], saisissez le fichier contenant les URL cibles (une par ligne, # pour les commentaires) :
file > targets.txt
| Fichier | Contenu |
|---|---|
| vuln_lfi.txt | Cibles LFI confirmées |
| vuln_lfitorce.txt | Cibles RCE réussies |
TIMEOUT = 8 # Délai d'expiration des requêtes (secondes) THREADS = 200 # Threads concurrents pour l'analyse de masse USE_ALL_ORACLES = False # Utiliser tous les oracles (plus précis mais plus lent)