Laboratorio de validación con Docker y PoC en Python para CVE-2026-89274, que demuestra la ejecución arbitraria de shortcodes en WP Recipe Maker <= 10.8.1 a través de rating-comment reviewBody.
Material de investigación de seguridad para reproducir y validar CVE-2026-89274: WP Recipe Maker <= 10.8.1 ejecuta shortcodes arbitrarios registrados de WordPress dentro de los metadatos JSON-LD de la receta, insertados mediante un comentario de valoración aprobado.
do_shortcode_safe que solo elimina)AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) - CWE-94Úsese únicamente en sistemas propios o para los que se tenga autorización explícita de prueba. El PoC publica un comentario de valoración que contiene un shortcode marcador registrado en el laboratorio. No se utiliza ningún shortcode destructivo y no se escribe nada en disco.
Estado: demostrado en el laboratorio proporcionado.
WP Recipe Maker 10.8.1 (WordPress 7.1.2, modelo de tarjeta de receta predeterminado):
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)
Esto demuestra la ejecución del lado del servidor de un shortcode arbitrario registrado con la salida incrustada en los metadatos de la página, revelada a cada visitante. No demuestra RCE; el impacto depende de qué shortcodes estén registrados en el objetivo (exposición de posts/meta, shortcodes proporcionados por plugins con efectos secundarios).
WPRM_Metadata::sanitize_metadata() sanea recursivamente cada campo escalar
del array de metadatos estructurados de la receta:
// 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() ejecuta el shortcode primero; el envoltorio strip_shortcodes()
solo elimina las etiquetas de la salida ya ejecutada. Uno de los
campos, reviewBody, se rellena literalmente desde comment_content de los comentarios
aprobados que llevan un valor meta wprm-comment-rating
(class-wprm-metadata.php:1016), consultado contra el post padre de la receta
(post_id => $recipe->parent_post_id(), línea 973) - el post o página
donde está incrustada la tarjeta de receta.
El reemplazo de 10.8.2, WPRM_Instacart::do_shortcode_safe()
(class-wprm-instacart.php:501), conserva solo el contenido interno y no ejecuta
nada.
[wprm-recipe])./wp-comments-post.php con el shortcode en el cuerpo
y wprm-comment-rating=5.review del JSON-LD, y
sanitize_metadata() ejecuta el shortcode. Su salida reemplaza el
texto del comentario dentro de reviewBody, visible para cada visitante.Requisitos: Docker con Compose v2, Python 3.10+ en el host.
./lab verify
Construye el laboratorio 10.8.1, exige que el marcador se dispare, luego construye el laboratorio
10.8.2 y exige su ausencia. Elimina todo con ./lab reset.
Control vulnerable:
[!!!] SHORTCODE EXECUTION CONFIRMED
evidence: 'CVE89274-SHORTCODE-FIRED' present in the rendered recipe page
context : ..."reviewBody":"CVE89274-SHORTCODE-FIRED","author":...
RESULT: VULNERABLE CONTROL CONFIRMED
Control parcheado:
[=] shortcode text present but NOT executed: output was stripped
RESULT: PATCHED CONTROL CONFIRMED
Un marcador en la página solo dentro del comentario mostrado (texto sin procesar) no se acepta como prueba; el marcador debe aparecer como salida ejecutada en los metadatos.
./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
Ejecutar el PoC a mano (loopback por defecto; los objetivos externos autorizados necesitan la anulación explícita):
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]
La plantilla de nuclei (nuclei/cve-2026-89274.yaml) es solo una comprobación de versión
(readme.txt stable tag <= 10.8.1). La cadena de comportamiento requiere el envío de un comentario
más una transición de aprobación, lo cual no es práctico de expresar en
nuclei; el PoC de Python realiza el flujo completo.
| Versión | Evaluación |
|---|---|
| WP Recipe Maker 10.8.1 | Ejecución de shortcode reproducida de principio a fin |
| WP Recipe Maker 10.8.2 | Control negativo parcheado reproducido |
| WP Recipe Maker <= 10.8.0 | Afectado según el aviso; no probado individualmente |
.
├── .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
No incluido en el repositorio: assets/ (zips de plugins), .lab-state, __pycache__/.
| Afirmación | Estado |
|---|---|
| Ejecución de shortcode mediante reviewBody del comentario de valoración | Demostrado (10.8.1) |
| Salida de ejecución revelada en el JSON-LD renderizado | Demostrado |
| Control negativo parcheado (10.8.2) | Demostrado |
| Configuración predeterminada (CPT de receta privada + post padre) | Demostrado (esta es la topología del laboratorio) |
| Configuración de tipo de post de receta pública | No probado |
| Endpoint REST de valoración propio de WPRM como entrada alternativa | No probado |
| Impacto más allá de la salida del shortcode registrado (RCE) | No afirmado |
Ejecuta este repositorio solo en sistemas propios o para los que tengas autorización explícita de
prueba. El controlador del laboratorio rechaza variantes distintas de vulnerable/patched, el
PoC rechaza objetivos que no sean loopback a menos que se proporcione --allow-authorized-non-loopback,
y el puerto de Compose está vinculado a 127.0.0.1.
Consulta SECURITY.md para el manejo de divulgación. Este repositorio no incluye objetivos de producción, datos de clientes, tokens de acceso ni evidencia de sistemas reales.
MIT - consulta LICENSE.