Lab de validation Docker et PoC Python pour CVE-2026-89274, prouvant l'exécution arbitraire de shortcode dans WP Recipe Maker <= 10.8.1 via rating-comment reviewBody.
Matériel de recherche de sécurité pour reproduire et valider CVE-2026-89274 : WP Recipe Maker <= 10.8.1 exécute des shortcodes WordPress enregistrés arbitraires à l'intérieur des métadonnées JSON-LD de recette, injectés via un commentaire de notation approuvé.
do_shortcode_safe de suppression uniquement)AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) - CWE-94À utiliser uniquement sur des systèmes que vous possédez ou que vous êtes explicitement autorisé à tester. Le PoC publie un commentaire de notation contenant un shortcode marqueur enregistré dans le lab. Aucun shortcode destructeur n'est utilisé et rien n'est écrit sur le disque.
Statut : prouvé dans le lab fourni.
WP Recipe Maker 10.8.1 (WordPress 7.1.2, modèle de carte de recette par défaut) :
comment posted : "[cve89274]" + wprm-comment-rating=5 on the recipe's parent post
result : JSON-LD on the rendered page contains
"reviewBody":"CVE89274-SHORTCODE-FIRED"
(marker shortcode executed server-side at render time)
10.8.2 : shortcode stripped, marker absent (patched negative control)
Cela démontre l'exécution côté serveur d'un shortcode enregistré arbitraire avec la sortie intégrée dans les métadonnées de la page, divulguée à chaque visiteur. Cela ne démontre pas de RCE ; l'impact dépend des shortcodes enregistrés sur la cible (exposition de post/meta, shortcodes fournis par des plugins avec effets de bord).
WPRM_Metadata::sanitize_metadata() assainit récursivement chaque champ scalaire
du tableau de métadonnées structurées de la recette :
// includes/public/class-wprm-metadata.php:553, WP Recipe Maker 10.8.1
$sanitized = strip_shortcodes( wp_strip_all_tags( do_shortcode( $metadata ) ) );
// 10.8.2
$sanitized = strip_shortcodes( wp_strip_all_tags( WPRM_Instacart::do_shortcode_safe( $metadata ) ) );
do_shortcode() exécute le shortcode en premier ; l'enveloppe strip_shortcodes()
ne fait que supprimer les balises de la sortie déjà exécutée. L'un des
champs, reviewBody, est rempli verbatim à partir de comment_content des commentaires approuvés
portant une valeur meta wprm-comment-rating
(class-wprm-metadata.php:1016), interrogés par rapport au post parent de la recette
(post_id => $recipe->parent_post_id(), ligne 973) - le post ou la page
où la carte de recette est intégrée.
Le remplacement en 10.8.2, WPRM_Instacart::do_shortcode_safe()
(class-wprm-instacart.php:501), ne conserve que le contenu interne et n'exécute
rien.
[wprm-recipe])./wp-comments-post.php avec le shortcode dans le corps
et wprm-comment-rating=5.review du JSON-LD, et
sanitize_metadata() exécute le shortcode. Sa sortie remplace le
texte du commentaire à l'intérieur de reviewBody, visible par chaque visiteur.Prérequis : Docker avec Compose v2, Python 3.10+ sur l'hôte.
./lab verify
Construit le lab 10.8.1, exige que le marqueur se déclenche, puis construit le lab 10.8.2
et exige son absence. Tout supprimer avec ./lab reset.
Contrôle vulnérable :
[!!!] SHORTCODE EXECUTION CONFIRMED
evidence: 'CVE89274-SHORTCODE-FIRED' present in the rendered recipe page
context : ..."reviewBody":"CVE89274-SHORTCODE-FIRED","author":...
RESULT: VULNERABLE CONTROL CONFIRMED
Contrôle corrigé :
[=] shortcode text present but NOT executed: output was stripped
RESULT: PATCHED CONTROL CONFIRMED
Un marqueur dans la page uniquement à l'intérieur du commentaire affiché (texte brut) n'est pas accepté comme preuve ; le marqueur doit apparaître comme sortie exécutée dans les métadonnées.
./lab start vulnerable # 10.8.1 lab on http://127.0.0.1:9482
./lab test # assert marker fires
./lab start patched # 10.8.2 lab
./lab test # assert absence
./lab status
./lab reset
Exécuter le PoC à la main (loopback par défaut ; les cibles externes autorisées nécessitent la surcharge explicite) :
python3 poc/poc_cve_2026_89274.py --url http://127.0.0.1:9482 --post-id 5
python3 poc/poc_cve_2026_89274.py --url https://target.example \
--allow-authorized-non-loopback [--insecure]
Le template nuclei (nuclei/cve-2026-89274.yaml) n'est qu'un contrôle de version
(readme.txt stable tag <= 10.8.1). La chaîne comportementale nécessite la soumission d'un commentaire
plus une transition d'approbation, ce qui n'est pas pratique à exprimer dans
nuclei ; le PoC Python effectue le flux complet.
| Version | Évaluation |
|---|---|
| WP Recipe Maker 10.8.1 | Exécution de shortcode reproduite de bout en bout |
| WP Recipe Maker 10.8.2 | Contrôle négatif corrigé reproduit |
| WP Recipe Maker <= 10.8.0 | Affecté selon l'avis ; non testé individuellement |
.
├── .github/workflows/validate.yml
├── .gitignore
├── LICENSE
├── README.md
├── SECURITY.md
├── docker-compose.yml
├── lab
├── nuclei/
│ └── cve-2026-89274.yaml
└── poc/
└── poc_cve_2026_89274.py
Non versionné : assets/ (zips de plugins), .lab-state, __pycache__/.
| Affirmation | Statut |
|---|---|
| Exécution de shortcode via reviewBody d'un commentaire de notation | Prouvé (10.8.1) |
| Sortie d'exécution divulguée dans le JSON-LD rendu | Prouvé |
| Contrôle négatif corrigé (10.8.2) | Prouvé |
| Configuration par défaut (CPT recette privée + post parent) | Prouvé (c'est la topologie du lab) |
| Configuration du type de post de recette publique | Non testé |
| Le propre endpoint REST de notation de WPRM comme entrée alternative | Non testé |
| Impact au-delà de la sortie de shortcode enregistré (RCE) | Non revendiqué |
N'exécutez ce dépôt que sur des systèmes que vous possédez ou que vous êtes explicitement autorisé à
tester. Le pilote du lab refuse les variantes autres que vulnerable/patched, le
PoC refuse les cibles non-loopback sauf si --allow-authorized-non-loopback est
fourni, et le port Compose est lié à 127.0.0.1.
Voir SECURITY.md pour la gestion de la divulgation. Ce dépôt n'inclut pas de cibles de production, de données clients, de jetons d'accès ou de preuves provenant de systèmes réels.
MIT - voir LICENSE.