
WordPress Events Manager < 7.4.1 के लिए बिना प्रमाणीकरण वाला विशेषाधिकार-वृद्धि (privilege-escalation) PoC; यह टकराने वाली (colliding) पोस्ट/यूज़र आईडी का पता लगाता है और REST या wp-admin के माध्यम से लक्ष्यों को व्यवस्थापक (administrator) तक बढ़ाता है।
| उत्पाद | Events Manager (वर्डप्रेस प्लगइन) |
| प्रभावित संस्करण | 7.1.0 – 7.4.0.x |
| सुधारित संस्करण | 7.4.1 |
| कमजोरी | CWE-269: अनुचित विशेषाधिकार प्रबंधन |
| गंभीरता | CVSS 3.1: 9.8 (क्रिटिकल) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| WPVDB आईडी | 82767ce2-01e4-46ad-a52b-72d3ab2049bd |
| मूल शोधकर्ता | Jakub Herman |
| विवरण और PoC | ghostpel |
poc.py)।Events Manager के 7.1.0 से 7.4.0.x संस्करणों में एक विशेषाधिकार वृद्धि भेद्यता है जो पूरी तरह से बिना प्रमाणीकरण वाले हमलावर को किसी भी उपयोगकर्ता खाते पर कब्ज़ा करने की अनुमति देती है जिसकी ID प्लगइन के अपने पोस्ट (event / location / event-recurring / location-recurring) में से किसी एक की ID से टकराती है। यह टक्कर (collision) उन साइटों पर बलपूर्वक की जा सकती है जहाँ अतिथि बुकिंग सक्षम है (डिफ़ॉल्ट): हर अतिथि बुकिंग एक वास्तविक उपयोगकर्ता खाता बनाती है और wp_users ऑटो-इन्क्रीमेंट काउंटर को एक से बढ़ा देती है, जिससे हमलावर उपयोगकर्ता ID स्पेस को किसी event/location पोस्ट ID पर "चल" सकता है।
मूल कारण: प्लगइन का map_meta_cap फ़िल्टर किसी भी मेटा क्षमता के लिए वर्डप्रेस द्वारा पहले से गणना की गई क्षमता सूची ($caps = []) को त्याग देता है, जब क्षमता का ऑब्जेक्ट ID किसी event/location पोस्ट पर हल होता है — जिसमें वर्डप्रेस कोर क्षमताएँ जैसे edit_user, delete_user, promote_user, और remove_user शामिल हैं। एक खाली क्षमता सूची "कोई क्षमता आवश्यक नहीं" के रूप में पढ़ी जाती है — अर्थात सभी के लिए अनुमति, जिसमें लॉग-आउट उपयोगकर्ता भी शामिल हैं।
परिणाम (सभी बिना प्रमाणीकरण, WP REST API के माध्यम से): किसी भी टकराने वाले खाते का पासवर्ड बदलें, उसे administrator में बढ़ाएँ, या उसे हटाएँ।
विश्लेषित संस्करण: 7.4.0.1 (असुरक्षित) — 7.4.1 (ठीक किया गया) से तुलना की गई।
| संस्करण | स्थिति |
|---|---|
| ≤ 7.0.5 | प्रभावित नहीं (legacy em_map_meta_cap केवल EM की अपनी क्षमताओं को संभालता है) |
| 7.1.0 – 7.4.0.x | असुरक्षित (त्रुटिपूर्ण map_meta_cap वाली आर्किटाइप प्रणाली 7.1.0 में शुरू की गई थी) |
| 7.4.1 | ठीक किया गया |
map_meta_cap $caps को खाली कर देता हैclasses/em-archetypes.php (संस्करण 7.4.0.1):
| पंक्ति | कोड | भूमिका |
|---|---|---|
:33 | add_filter( 'map_meta_cap', [ static::class, 'map_meta_cap'], 10, 4 ); | ग्लोबल, बिना शर्त फ़िल्टर — हर वर्डप्रेस मेटा-क्षमता जाँच के लिए चलता है, जिसमें कोर और लॉग-आउट उपयोगकर्ताओं के लिए भी शामिल है |
:547 | if ( !empty( $args[0] ) ) { | क्षमता का ऑब्जेक्ट पोस्ट ID के रूप में लिया जाता है |
:548 | $post = get_post($args[0]); | ID टक्कर: लक्षित यूज़र ID (जैसे edit_user कैप के लिए) को पोस्ट ID माना जाता है |
:551 | `if( empty($post->post_type) | |
:563 | `if ( !empty( $c['read'][$post->post_type] ) | |
:564–565 | $caps = []; | क्षमता सूची बिना शर्त त्याग दी जाती है — भले ही अनुरोधित कैप read/edit/delete_event आर्किटाइप कैप न हो |
:568/577/584 | if/elseif branches | $caps केवल तब भरी जाती है जब $cap किसी आर्किटाइप मेटा कैप से बिल्कुल मेल खाती है; edit_user, delete_user, promote_user, remove_user के लिए कोई शाखा मेल नहीं खाती → $caps खाली रहती है |
:597 | return $caps; | खाली सरणी = "कोई क्षमता आवश्यक नहीं" = सभी के लिए अनुमति, जिसमें यूज़र ID 0 भी शामिल है |
परिणाम: हर current_user_can('edit_user', X) / delete_user / promote_user / remove_user जाँच TRUE लौटाती है जब भी X किसी event/location पोस्ट की ID के बराबर होती है। प्लगइन "वर्डप्रेस द्वारा पहले से लिए गए अभिगम नियंत्रण निर्णयों को त्याग देता है" — बिल्कुल WPScan द्वारा वर्णित अनुसार।
7.4.0.1 की तुलना 7.4.1 से करके सत्यापित किया गया: अब रीसेट प्रत्येक शाखा में सटीक क्षमता मिलान द्वारा संरक्षित है (जैसे && $c['read'][$post->post_type] == $cap), इसलिए $caps केवल तब खाली होती है जब अनुरोधित क्षमता वास्तव में एक आर्किटाइप मेटा कैप होती है। पैच टिप्पणी: "किसी भी ऑब्जेक्ट-वाहक कैप पर रीसेट करने से असंबंधित कैप (जैसे edit_user, promote_user) के लिए आवश्यकता सूची खाली हो जाती थी, जो अनुमति के रूप में पढ़ी जाती है।"
REST Users एंडपॉइंट्स (/wp-json/wp/v2/users/{id}) में कोई ग्लोबल लॉगिन गेट नहीं है — अभिगम नियंत्रण पूरी तरह से अनुमति कॉलबैक के माध्यम से होता है, ये सभी उसी map_meta_cap फ़िल्टर से होकर गुजरते हैं:
| क्रिया | एंडपॉइंट / कोर फ़ंक्शन | बाइपास की गई क्षमता |
|---|---|---|
| लक्षित खाते का पासवर्ड बदलें | PUT /wp-json/wp/v2/users/{id} के साथ {"password":"..."} → wp_update_user() (आंतरिक edit_user जाँच) | edit_user |
| खाते को एडमिनिस्ट्रेटर तक बढ़ाएँ | PUT /wp-json/wp/v2/users/{id} के साथ {"roles":["administrator"]} | promote_user |
| खाता हटाएँ | DELETE /wp-json/wp/v2/users/{id}?reassign=... → wp_delete_user() (आंतरिक delete_user जाँच) | delete_user |
| (मल्टीसाइट) किसी उपयोगकर्ता को ब्लॉग से निकालें | remove_user | remove_user |
दुष्प्रभाव: edit_comment भी प्रभावित होता है जब एक टिप्पणी ID किसी event/location पोस्ट ID के बराबर होती है (wp_comments तालिका संख्यात्मक स्थान साझा करती है)।
टक्कर इसलिए मौजूद है क्योंकि wp_users.ID और wp_posts.ID स्वतंत्र ऑटो-इन्क्रीमेंट अनुक्रम हैं जो अनिवार्य रूप से ओवरलैप होते हैं। अतिथि बुकिंग इसे बलपूर्वक लागू करती है:
em-install.php:896 — dbem_bookings_anonymous = 1: अतिथि बुकिंग डिफ़ॉल्ट रूप से सक्षम; :871 dbem_bookings_registration_disable = 0 (पंजीकरण सक्षम)।em-actions.php:340-344 — booking_add $booking_nopriv_actions में है → बिना लॉगिन कॉल करने योग्य (wp_ajax_nopriv_booking_add के माध्यम से, प्राथमिकता 999999, पंक्तियाँ :817-830, या wp_loaded :11)।em-actions.php:360-375 — booking_add प्रवाह: em_verify_nonce('booking_add') → get_post() → validate() → em_booking_add_registration() → $EM_Bookings->add()। (नॉन्स केवल CSRF सुरक्षा है — booking_add नॉन्स सार्वजनिक बुकिंग फ़ॉर्म पर प्रस्तुत किया जाता है, इसलिए कोई भी इसे प्राप्त कर सकता है।)em-functions.php:405-417 — अतिथि शाखा: हमलावर के ईमेल के साथ em_register_new_user($user_data)।em-functions.php:510 — wp_insert_user($user_data) → wp_users ऑटो-इन्क्रीमेंट प्रति अतिथि बुकिंग 1 से बढ़ता है → हमलावर यूज़र ID काउंटर की वृद्धि दर को नियंत्रित करता है जब तक कि यह वांछित event/location पोस्ट ID पर न पहुँच जाए (WPScan: "प्रत्येक अतिथि बुकिंग एक वास्तविक उपयोगकर्ता खाता बनाती है और यूज़र ID काउंटर को एक से बढ़ाती है")।ऑडिट के दौरान देखी गई द्वितीयक श्रृंखला (बुकिंग विशेषता person_id के माध्यम से) — events-manager.php:430-437 (em_load_event, बिना लॉगिन $_REQUEST['person_id'] से $EM_Person), em-booking.php:1060-1072 (get_person() नई बुकिंग के person_id को ओवरराइड करता है), em-booking.php:2004-2006 (can_manage() = बिना ID वाली बुकिंग के लिए TRUE), em-functions.php:448-449 — 7.4.1 में अपरिवर्तित; यह एक अलग वेक्टर है (बुकिंग गलत-विशेषता), इस CVE का मूल नहीं है।