
Le plugin Gravity Forms pour WordPress (testé jusqu'à la version 2.9.28) est vulnérable à un cross-site scripting (XSS) réfléchi non authentifié via le paramètre `form_ids` dans l'action AJAX `gform_get_config`.
form_ids de gform_get_config| Champ | Valeur |
|---|---|
| Logiciel concerné | Gravity Forms (Plugin WordPress) |
| Éditeur | Rocketgenius, Inc. |
| Type de vulnérabilité | CWE-79 : Neutralisation incorrecte de l'entrée lors de la génération de pages Web (Cross-Site Scripting réfléchi) |
| Chaîne CWE | CWE-20 → CWE-116 → CWE-838 → CWE-79 (voir l'analyse CWE ci-dessous) |
| Versions concernées | Confirmé sur 2.9.28 (dernière version au moment de la découverte) ; les versions antérieures sont probablement concernées |
| Version corrigée | 2.9.30.1 (correctif d'urgence) |
| Score CVSS 3.1 | 6.1 (Moyen) |
| Vecteur CVSS 3.1 | AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N |
| Authentification requise | Aucune (non authentifié) |
| Interaction utilisateur | Requise (la victime doit visiter une page contrôlée par l'attaquant ou cliquer sur un lien conçu à cet effet) |
| Découvert par | Anthony Cihan — Obviam |
| Date de découverte | 2026-03-04 |
| Date de divulgation | 2026-03-18 |
| Identifiant CVE | CVE-2026-4406 |
Enregistrement public Wordfence
Le plugin Gravity Forms pour WordPress (testé jusqu'à la version 2.9.28) est vulnérable à un cross-site scripting (XSS) réfléchi non authentifié via le paramètre form_ids de l'action AJAX gform_get_config. La vulnérabilité existe parce que les valeurs form_ids fournies par l'utilisateur sont reflétées textuellement dans la réponse HTTP du serveur sans aucune assainissement, encodage ou échappement de sortie. La réponse est servie avec un en-tête Content-Type: text/html; charset=UTF-8, ce qui amène le navigateur à analyser et à rendre le contenu reflété comme du HTML, y compris tout élément de script injecté.
Un attaquant non authentifié peut exploiter cette vulnérabilité pour exécuter du JavaScript arbitraire dans le contexte de l'origine du site WordPress cible. Étant donné que l'action gform_get_config nécessite un config_nonce valide, et que ce nonce est publiquement intégré dans le code source HTML de chaque page qui charge un formulaire Gravity Forms, un attaquant peut trivialement obtenir un nonce valide en demandant n'importe quelle page publique du site cible avant de construire la requête d'exploitation.
Une exploitation réussie permet à un attaquant de voler les cookies de session, d'effectuer des actions au nom d'utilisateurs authentifiés (y compris les administrateurs WordPress), de rediriger les utilisateurs vers des sites malveillants, de défigurer le contenu des pages ou d'établir un accès persistant via la création de comptes administratifs.
POST /wp-admin/admin-ajax.php
### Action vulnérable```
gform_get_config
Le paramètre POST args accepte un objet JSON contenant un tableau form_ids. Les valeurs de ce tableau sont utilisées comme clés d'objet dans la structure de la réponse JSON sans assainissement :```json
{"form_ids":["ATTACKER_CONTROLLED_VALUE"]}
### Comportement de la réponse
Le serveur traite les valeurs de `form_ids` et les reflète comme clés JSON dans le corps de la réponse. La réponse est encapsulée dans des marqueurs de commentaire HTML et servie en tant que `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 ne sont pas validées comme entiers, ni assainies, ni filtrées. Le serveur accepte tout contenu de chaîne arbitraire, y compris des balises HTML et des gestionnaires d'événements.form_ids sont reflétées dans le corps de la réponse sans encodage des entités HTML. Les caractères tels que <, >, " et ' transitent sans modification.Content-Type: text/html; charset=UTF-8, ce qui indique au navigateur d'analyser le corps de la réponse comme du HTML. Toute balise HTML présente dans la valeur reflétée est instanciée et rendue par l'analyseur HTML du navigateur.config_nonce requis par l'action gform_get_config est intégré dans l'objet de configuration JavaScript (gform_theme_config) sur chaque page qui charge un formulaire Gravity Forms. Ce nonce est identique sur toutes les pages et n'est lié à aucune session utilisateur spécifique, ce qui le rend trivialement accessible aux utilisateurs non authentifiés.Cette vulnérabilité résulte de plusieurs faiblesses contributives qui s'enchaînent pour produire la condition exploitable. Bien que CWE-79 soit la classification principale à des fins de rapport CVE, la chaîne complète documente comment chaque défaillance se cumule pour permettre l'exploitation.
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 : Validation incorrecte des entrées (facteur contribuant)
**Rôle :** Facilitateur racine — permet à des données malveillantes d'entrer dans le pipeline de traitement.
Le paramètre `form_ids` dans l'objet JSON `args` est censé contenir des identifiants numériques de formulaires, mais accepte toute chaîne de caractères arbitraire sans aucune validation. Aucune vérification de type (`intval()`), aucun filtrage par expression régulière (`^[0-9]+$`), aucune comparaison avec une liste blanche d'identifiants de formulaires connus, et aucune restriction de longueur ne sont appliqués.
**Preuve :** Le serveur accepte et traite des valeurs `form_ids` contenant des balises HTML, des gestionnaires d'événements JavaScript et tout caractère Unicode arbitraire sans les rejeter.```json
{"form_ids":["<svg onload=alert(1)>"]} ← Accepted
{"form_ids":["3"]} ← Expected
Rôle : Vulnérabilité principale — la cause directe de la condition XSS.
Lorsque le serveur construit la réponse JSON contenant les valeurs form_ids, il n'applique pas l'encodage des entités HTML à la sortie. Les caractères ayant une signification spéciale en HTML (<, >, ", ', &) transitent sans modification dans le corps de la réponse. Les fonctions PHP htmlspecialchars(), esc_html(), wp_json_encode() avec JSON_HEX_TAG, ou les fonctions d'encodage de sortie équivalentes ne sont pas appliquées aux valeurs form_ids avant qu'elles ne soient écrites dans la réponse.
Preuve : La chaîne littérale <svg onload=alert(document.domain)> apparaît dans le corps de la réponse octet pour octet identique à l'entrée, plutôt que sous la forme <svg onload=alert(document.domain)>.
Rôle : Escalade de contexte — transforme un problème de réflexion de données en injection de code exécutable.