
El plugin Gravity Forms para WordPress (probado hasta la versión 2.9.28) es vulnerable a cross-site scripting (XSS) reflejado no autenticado a través del parámetro `form_ids` en la acción AJAX `gform_get_config`.
form_ids de gform_get_config| Campo | Valor |
|---|---|
| Software Afectado | Gravity Forms (Plugin de WordPress) |
| Proveedor | Rocketgenius, Inc. |
| Tipo de Vulnerabilidad | CWE-79: Neutralización Incorrecta de Entrada Durante la Generación de Páginas Web (Cross-Site Scripting Reflejado) |
| Cadena CWE | CWE-20 → CWE-116 → CWE-838 → CWE-79 (ver Análisis CWE a continuación) |
| Versiones Afectadas | Confirmado en 2.9.28 (la más reciente al momento del descubrimiento); es probable que versiones anteriores estén afectadas |
| Versión Corregida | 2.9.30.1 (parche de emergencia) |
| Puntuación CVSS 3.1 | 6.1 (Media) |
| Vector CVSS 3.1 | AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N |
| Autenticación Requerida | Ninguna (No autenticado) |
| Interacción del Usuario | Requerida (la víctima debe visitar una página controlada por el atacante o hacer clic en un enlace manipulado) |
| Descubierto Por | Anthony Cihan — Obviam |
| Fecha de Descubrimiento | 2026-03-04 |
| Fecha de Divulgación | 2026-03-18 |
| ID CVE | CVE-2026-4406 |
El plugin Gravity Forms para WordPress (probado hasta la versión 2.9.28) es vulnerable a cross-site scripting (XSS) reflejado no autenticado a través del parámetro form_ids en la acción AJAX gform_get_config. La vulnerabilidad existe porque los valores de form_ids proporcionados por el usuario se reflejan textualmente en la respuesta HTTP del servidor sin ningún tipo de saneamiento, codificación o escape de salida. La respuesta se sirve con una cabecera Content-Type: text/html; charset=UTF-8, lo que hace que el navegador analice y renderice el contenido reflejado como HTML, incluidos los elementos de script inyectados.
Un atacante no autenticado puede explotar esta vulnerabilidad para ejecutar JavaScript arbitrario en el contexto del origen del sitio WordPress objetivo. Debido a que la acción gform_get_config requiere un config_nonce válido, y este nonce está incrustado públicamente en el código fuente HTML de cada página que carga un formulario de Gravity Forms, un atacante puede obtener trivialmente un nonce válido solicitando cualquier página pública del sitio objetivo antes de construir la solicitud de explotación.
Una explotación exitosa permite a un atacante robar cookies de sesión, realizar acciones en nombre de usuarios autenticados (incluidos administradores de WordPress), redirigir a los usuarios a sitios maliciosos, alterar el contenido de la página o establecer acceso persistente mediante la creación de cuentas administrativas.
POST /wp-admin/admin-ajax.php
### Acción Vulnerable```
gform_get_config
El parámetro POST args acepta un objeto JSON que contiene un array form_ids. Los valores de este array se utilizan como claves de objeto en la estructura de la respuesta JSON sin saneamiento:```json
{"form_ids":["ATTACKER_CONTROLLED_VALUE"]}
### Comportamiento de la respuesta
El servidor procesa los valores de `form_ids` y los refleja como claves JSON dentro del cuerpo de la respuesta. La respuesta está envuelta en marcadores de comentario HTML y se sirve como `text/html`:```
Content-Type: text/html; charset=UTF-8
<!-- gf:json_start -->{"success":true,"data":{"common":{"form":{"pagination":{"ATTACKER_CONTROLLED_VALUE":null}}}}}<!-- gf:json_end -->
form_ids no se validan como enteros, no se sanean ni se filtran. El servidor acepta contenido de cadena arbitrario, incluyendo etiquetas HTML y manejadores de eventos.form_ids se reflejan en el cuerpo de la respuesta sin codificación de entidades HTML. Caracteres como <, >, " y ' pasan sin modificaciones.Content-Type: text/html; charset=UTF-8, lo que indica al navegador que analice el cuerpo de la respuesta como HTML. Cualquier etiqueta HTML dentro del valor reflejado se instancia y se renderiza mediante el analizador HTML del navegador.config_nonce requerido por la acción gform_get_config está incrustado en el objeto de configuración de JavaScript (gform_theme_config) en cada página que carga un formulario de Gravity Forms. Este nonce es idéntico en todas las páginas y no está vinculado a una sesión de usuario específica, lo que lo hace trivialmente obtenible por usuarios no autenticados.Esta vulnerabilidad es el resultado de múltiples debilidades contribuyentes que se encadenan para producir la condición explotable. Si bien CWE-79 es la clasificación principal para fines de informes CVE, la cadena completa documenta cómo cada fallo se acumula para habilitar la explotación.
CWE-20 CWE-116 CWE-838 CWE-79 Improper Input → Improper Encoding → Inappropriate Encoding → Cross-Site Validation or Escaping of Output for Output Context Scripting (XSS) [EXPLOITABLE] form_ids accepts Reflected values are JSON data served as Browser parses arbitrary strings not HTML-entity text/html instead of injected HTML tags instead of integers encoded in response application/json and executes JS
### CWE-20: Validación de Entrada Incorrecta (Contribuyente)
**Rol:** Habilitador raíz — permite que datos maliciosos ingresen al pipeline de procesamiento.
Se espera que el parámetro `form_ids` en el objeto JSON `args` contenga identificadores de formularios numéricos, pero acepta entrada de cadena arbitraria sin ninguna validación. No se aplica verificación de tipo (`intval()`), ni filtrado con expresiones regulares (`^[0-9]+$`), ni comparación contra una lista blanca de IDs de formularios conocidos, ni restricciones de longitud.
**Evidencia:** El servidor acepta y procesa valores de `form_ids` que contienen etiquetas HTML, manejadores de eventos de JavaScript y Unicode arbitrario sin rechazarlos.```json
{"form_ids":["<svg onload=alert(1)>"]} ← Accepted
{"form_ids":["3"]} ← Expected
Rol: Vulnerabilidad principal — la causa directa de la condición XSS.
Cuando el servidor construye la respuesta JSON que contiene los valores de form_ids, no aplica codificación de entidades HTML a la salida. Los caracteres con significado especial en HTML (<, >, ", ', &) pasan sin modificar al cuerpo de la respuesta. Las funciones PHP htmlspecialchars(), esc_html(), wp_json_encode() con JSON_HEX_TAG, o funciones equivalentes de codificación de salida no se aplican a los valores de form_ids antes de que se escriban en la respuesta.
Evidencia: La cadena literal <svg onload=alert(document.domain)> aparece en el cuerpo de la respuesta byte por byte idéntica a la entrada, en lugar de como <svg onload=alert(document.domain)>.
Rol: Escalada de contexto — transforma un problema de reflexión de datos en inyección de código ejecutable.