
O plugin Gravity Forms para WordPress (testado até a versão 2.9.28) é vulnerável a cross-site scripting (XSS) refletido não autenticado por meio do parâmetro `form_ids` na ação AJAX `gform_get_config`.
form_ids de gform_get_config| Campo | Valor |
|---|---|
| Software Afetado | Gravity Forms (Plugin WordPress) |
| Fornecedor | Rocketgenius, Inc. |
| Tipo de Vulnerabilidade | CWE-79: Neutralização Incorreta de Entrada Durante a Geração de Página Web (Cross-Site Scripting Refletido) |
| Cadeia CWE | CWE-20 → CWE-116 → CWE-838 → CWE-79 (ver Análise CWE abaixo) |
| Versões Afetadas | Confirmado na 2.9.28 (mais recente na data da descoberta); versões anteriores provavelmente afetadas |
| Versão Corrigida | 2.9.30.1 (hotfix) |
| Pontuação CVSS 3.1 | 6.1 (Média) |
| Vetor CVSS 3.1 | AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N |
| Autenticação Necessária | Nenhuma (Não autenticado) |
| Interação do Usuário | Necessária (a vítima deve visitar uma página controlada pelo atacante ou clicar em um link manipulado) |
| Descoberto Por | Anthony Cihan — Obviam |
| Data da Descoberta | 2026-03-04 |
| Data da Divulgação | 2026-03-18 |
| ID CVE | CVE-2026-4406 |
O plugin Gravity Forms para WordPress (testado até a versão 2.9.28) é vulnerável a cross-site scripting (XSS) refletido não autenticado via o parâmetro form_ids na ação AJAX gform_get_config. A vulnerabilidade existe porque os valores de form_ids fornecidos pelo usuário são refletidos literalmente na resposta HTTP do servidor sem qualquer sanitização, codificação ou escape de saída. A resposta é servida com um cabeçalho Content-Type: text/html; charset=UTF-8, o que faz com que o navegador analise e renderize o conteúdo refletido como HTML, incluindo quaisquer elementos de script injetados.
Um atacante não autenticado pode explorar esta vulnerabilidade para executar JavaScript arbitrário no contexto da origem do site WordPress alvo. Como a ação gform_get_config exige um config_nonce válido, e este nonce está publicamente embutido no código-fonte HTML de toda página que carrega um formulário do Gravity Forms, um atacante pode obter trivialmente um nonce válido solicitando qualquer página pública do site alvo antes de construir a solicitação de exploração.
A exploração bem-sucedida permite que um atacante roube cookies de sessão, execute ações em nome de usuários autenticados (incluindo administradores do WordPress), redirecione usuários para sites maliciosos, desfigure o conteúdo da página ou estabeleça acesso persistente por meio da criação de contas administrativas.
POST /wp-admin/admin-ajax.php
### Ação Vulnerável```
gform_get_config
O parâmetro POST args aceita um objeto JSON contendo um array form_ids. Os valores nesse array são usados como chaves de objeto na estrutura da resposta JSON sem sanitização:```json
{"form_ids":["ATTACKER_CONTROLLED_VALUE"]}
### Comportamento da Resposta
O servidor processa os valores de `form_ids` e os reflete como chaves JSON dentro do corpo da resposta. A resposta é envolvida em marcadores de comentário HTML e servida 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 não são validados como inteiros, sanitizados ou filtrados. O servidor aceita conteúdo arbitrário em formato de string, incluindo tags HTML e manipuladores de eventos.form_ids são refletidos no corpo da resposta sem codificação de entidades HTML. Caracteres como <, >, " e ' passam sem modificação.Content-Type: text/html; charset=UTF-8, o que instrui o navegador a interpretar o corpo da resposta como HTML. Quaisquer tags HTML dentro do valor refletido são instanciadas e renderizadas pelo parser HTML do navegador.config_nonce exigido pela ação gform_get_config está embutido no objeto de configuração JavaScript (gform_theme_config) em toda página que carrega um formulário Gravity Forms. Esse nonce é idêntico em todas as páginas e não está vinculado a uma sessão de usuário específica, tornando-o trivialmente obtido por usuários não autenticados.Esta vulnerabilidade é o resultado de múltiplas fraquezas contribuintes que se encadeiam para produzir a condição explorável. Embora CWE-79 seja a classificação primária para fins de relatório CVE, a cadeia completa documenta como cada falha se combina para permitir a exploração.
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: Validação de Entrada Incorreta (Contribuinte)
**Papel:** Habilitador raiz — permite que dados maliciosos entrem no pipeline de processamento.
O parâmetro `form_ids` no objeto JSON `args` deve conter identificadores numéricos de formulários, mas aceita entrada de string arbitrária sem qualquer validação. Nenhuma verificação de tipo (`intval()`), nenhum filtro de regex (`^[0-9]+$`), nenhuma comparação de lista de permissões contra IDs de formulários conhecidos e nenhuma restrição de comprimento são aplicadas.
**Evidência:** O servidor aceita e processa valores de `form_ids` contendo tags HTML, manipuladores de eventos JavaScript e Unicode arbitrário sem rejeição.```json
{"form_ids":["<svg onload=alert(1)>"]} ← Accepted
{"form_ids":["3"]} ← Expected
Função: Vulnerabilidade central — a causa direta da condição de XSS.
Quando o servidor constrói a resposta JSON contendo os valores de form_ids, ele não aplica codificação de entidades HTML à saída. Caracteres com significado especial em HTML (<, >, ", ', &) passam sem modificação para o corpo da resposta. As funções PHP htmlspecialchars(), esc_html(), wp_json_encode() com JSON_HEX_TAG, ou funções equivalentes de codificação de saída não são aplicadas aos valores de form_ids antes de serem gravados na resposta.
Evidência: A string literal <svg onload=alert(document.domain)> aparece no corpo da resposta byte a byte idêntica à entrada, em vez de <svg onload=alert(document.domain)>.
Função: Escalonamento de contexto — transforma um problema de reflexão de dados em injeção de código executável.
O corpo da resposta contém dados estruturados em JSON, mas é servido com Content-Type: text/html; charset=UTF-8. Essa declaração de Content-Type instrui o parser HTML do navegador a processar todo o corpo da resposta como um documento HTML. Se a resposta fosse servida como application/json, o navegador renderizaria a resposta como texto simples e nenhum parsing HTML ocorreria — as tags injetadas seriam exibidas como texto literal em vez de serem instanciadas como elementos DOM.