
Analyse indépendante des causes profondes et preuve de concept pour une injection SQL non authentifiée menant à une exécution de code à distance (RCE) dans WordPress (CVE-2026-63030 + CVE-2026-60137), avec un laboratoire Docker et une documentation détaillée de la chaîne d'exploitation.
WordPress core a divulgué wp2shell le 17 juillet 2026 comme une RCE critique non authentifiée affectant les installations par défaut (WordPress 6.9.0-6.9.4, 7.0.0-7.0.1, zéro plugin requis). Le découvreur original (Searchlight Cyber) a retenu les détails techniques au moment de la divulgation. Ce dépôt documente une analyse indépendante de la cause racine dérivée entièrement du diff du code source de WordPress core entre les versions vulnérable (6.9.4) et corrigée (6.9.5), plus une vérification en direct dans un laboratoire local.
Crédit : la reproduction ici suit la forme de la requête de sergiointel/wp2shell-poc, confirmée octet par octet et recoupée avec le diff réel du correctif.
root_cause_analysis.md - rapport complet : les deux bogues enchaînés, le code vulnérable exact, le diff du correctif, la chaîne d'exploitation, et la vérification avant/après en direct contre une vraie instance WP 6.9.4.poc_upstream.py - copie non modifiée du PoC original de sergiointel (SQLi uniquement).poc_upstream_rce.py - PoC de sergiointel mis à jour environ 22 heures après la divulgation, ajoutant l'escalade de privilèges non authentifiée et la RCE sans casser aucune information d'identification. Voir section 7 de .root_cause_analysis.mdpoc_extract.py / poc_extract2.py - une variante ajustée (SLEEP() plus grand, seuil de temporisation plus élevé, plage de recherche de caractères plus longue) nécessaire pour obtenir un signal fiable dans un laboratoire Dockerisé/proxifié où le SLEEP(0.15) par défaut du script amont était perdu dans la gigue réseau.docker-compose.yml - lancer le même laboratoire WordPress 6.9.4 + MariaDB utilisé pour la vérification.payload.json, response.json, response_patched.json - une requête artisanale reproduisant la structure du PoC et les réponses brutes du serveur, avant et après application des fichiers de correctif 6.9.5 en place.Un second PoC écrit indépendamment (github.com/Icex0/wp2shell-poc) a été examiné en entier et décrit le même mécanisme de cause racine de manière indépendante, corroborant l'analyse ci-dessous. En utilisant son extraction SQLi aveugle basée sur le contenu (booléenne, non basée sur la temporisation), le hachage des identifiants d'administrateur de ce laboratoire a été récupéré avec une précision de 100 %, et, en utilisant cette information d'identification connue, une chaîne complète SQLi-à-RCE a été démontrée en direct : injection SQL vers extraction d'identifiants vers webshell de téléchargement de plugin authentifié vers exécution de code en tant que www-data. Voir section 6 de root_cause_analysis.md.
Ce chemin de cassage d'identifiants est réel mais n'est pas le seul. Le PoC de sergiointel a ensuite été mis à jour pour réaliser une RCE non authentifiée sans aucun cassage d'identifiants, en utilisant UNION SELECT pour forger des lignes de base de données factices que le propre code Customizer/nav-menu/oEmbed-cache de WordPress considère assez fiable pour permettre à une requête de création d'utilisateur non authentifiée de réussir. Voir section 7 de root_cause_analysis.md. L'injection SQL non authentifiée seule est suffisante pour une RCE complète sur une installation par défaut.
CVE-2026-63030 (Confusion de route de lot REST, CWE-436) :
WP_REST_Server::serve_batch_request_v1() ajoute à un tableau $matches[] par simple push, mais saute l'ajout lorsque le chemin d'une sous-requête échoue à l'analyse (par exemple une entrée délibérément malformée "http://:"). Ce seul saut désynchronise $matches[] de $requests[] d'un index pour chaque entrée suivante. Au moment de l'envoi, $matches[$i] ne correspond plus à $requests[$i], donc le code finit par exécuter les données d'une requête sous le gestionnaire correspondant à une route différente de celle contre laquelle elle a été effectivement validée.
CVE-2026-60137 (Injection SQL) : WP_Query::get_posts() n'exécutait la sanitisation absint() sur author__not_in que dans une branche is_array(). Une valeur scalaire de type chaîne ignorait entièrement la sanitisation et était concaténée directement dans ... post_author NOT IN ($value).
Enchaîné : le bogue de confusion de route permet à un attaquant de déclarer une requête contre /wp/v2/categories (qui ne reconnaît pas author_exclude, donc elle n'est jamais nettoyée) mais de l'envoyer effectivement via le contrôleur posts (qui lit author_exclude et le transmet à WP_Query). Aucune authentification requise.
Sur la revendication RCE : confirmé en direct que l'injection SQL aveugle non authentifiée fonctionne et peut exfiltrer un contenu arbitraire de la base de données, y compris wp_users.user_pass. Un seul passage d'extraction basé sur la temporisation dans un laboratoire virtualisé présentait un bruit d'erreur de bit significatif (~94 % de précision par caractère dans les tests ici) ; un oracle basé sur le contenu (booléen) ne partageait pas ce mode de défaillance et récupérait le même champ avec une précision de 100 %. La RCE a été confirmée via deux chemins distincts : casser un hachage de mot de passe récupéré (conditionnel à la force du mot de passe), et une chaîne de gadgets d'escalade de privilèges non authentifiée utilisant des lignes de base de données forgées par UNION que le propre code Customizer/nav-menu/oEmbed-cache de WordPress considère comme fiables (inconditionnel, aucun compromis d'identifiants requis). Voir section 7 de root_cause_analysis.md.
docker compose up -d
# attendre que l'assistant d'installation de WordPress soit accessible sur :8890, puis terminer la configuration
HTTP_PROXY=http://127.0.0.1:8080 HTTPS_PROXY=http://127.0.0.1:8080 \
python3 poc_extract2.py http://localhost:8890 "SELECT DATABASE()"
Voir root_cause_analysis.md pour le rapport technique complet.
WordPress a publié des correctifs officiels : 6.9.5 et 7.0.2 (7.1 Beta 2 pour la branche bêta), publiés le 17 juillet 2026. Mettez à jour immédiatement si vous utilisez une version affectée. Ce dépôt est publié à des fins défensives et éducatives après que le correctif était déjà public. N'exécutez aucun code ici que sur des systèmes que vous possédez ou pour lesquels vous êtes explicitement autorisé à tester.