
JupyterHub XSRF बायपास via क्रॉस-ओरिजिन फॉर्म POST (Sec-Fetch-Mode: no-cors) — CWE-352
Sec-Fetch-Mode: no-cors)गंभीरता: मध्यम
CWE: CWE-352 — क्रॉस-साइट रिक्वेस्ट फोर्जरी (XSRF)
प्रभावित: jupyterhub 4.1.0 ≤ version < 5.4.5 (में पैच किया गया 5.4.5)
एडवाइजरी: GHSA-m68r-v472-jgq9
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-40864
श्रेय: Romain Deperne
JupyterHub की XSRF सुरक्षा (4.1.0 में पुनः काम की गई) यह तय करने के लिए Sec-Fetch-Mode अनुरोध हेडर का उपयोग करती थी कि कोई अनुरोध समान-मूल का है या नहीं। इसने Sec-Fetch-Mode: no-cors को समान-मूल माना — लेकिन no-cors वही है जो ब्राउज़र एक क्रॉस-ओरिजिन "सरल" फॉर्म सबमिशन के लिए भेजता है। परिणामस्वरूप, Hub के फॉर्म एंडपॉइंट (/hub/spawn, /hub/accept-share) पर क्रॉस-ओरिजिन HTML फॉर्म POST ने XSRF जांच को पूरी तरह से बाइपास कर दिया।
JSON API प्रभावित नहीं है (इसे एक गैर-सरल कंटेंट टाइप की आवश्यकता है, जो CORS प्रीफ्लाइट को मजबूर करता है)। केवल HTML फॉर्म एंडपॉइंट इस तरह पहुंच योग्य हैं।
XSRF लॉजिक Sec-Fetch-* स्थितियों के एक सेट के लिए "विश्वसनीय" पर शॉर्ट-सर्किट होता है, जो समान-मूल नेविगेशन को कैप्चर करने के लिए होते हैं। Sec-Fetch-Mode: no-cors उस विश्वसनीय सेट में शामिल था। लेकिन no-cors वह मोड है जो ब्राउज़र एक सादे <form method=POST> को एक अलग मूल पर पोस्ट करने पर असाइन करता है — ठीक वही क्लासिक CSRF वेक्टर जिसे टोकन रोकने वाला है। इसलिए कोई भी स्थिति-परिवर्तन करने वाला एंडपॉइंट जो एक सरल फॉर्म बॉडी स्वीकार करता है, और केवल इस XSRF गेट पर निर्भर करता है, क्रॉस-ओरिजिन फोर्जेबल है।
इसे वास्तविक एंडपॉइंट पर मैप करते हैं: /hub/spawn (पीड़ित के सर्वर को शुरू करना) और /hub/accept-share (पीड़ित को हमलावर के सर्वर का शेयर स्वीकार करने के लिए बनाना) दोनों इस गेट के पीछे फॉर्म POST हैं।
/hub/spawn — एक हमलावर पेज बिना सहमति के पीड़ित के सिंगल-यूज़र सर्वर को स्पॉन कर सकता है (संसाधन खपत / अप्रत्याशित स्थिति; हमलावर को उस सर्वर तक पहुंच नहीं मिलती)।/hub/accept-share — जब हमलावर एक JupyterHub उपयोगकर्ता है जिसे अपने सर्वर को साझा करने की अनुमति है, तो वे पीड़ित को एक शेयर स्वीकार करने के लिए मजबूर कर सकते हैं, जिससे पीड़ित को हमलावर के सर्वर तक पहुंच मिलती है (आगे के सोशल-इंजीनियरिंग / डेटा-ड्रॉप परिदृश्यों के लिए एक सेटअप चरण)।Sec-Fetch-Mode को एक ओरिजिन ओरेकल के रूप में उपयोग करना अनुचित है: no-cors समान-मूल का संकेत नहीं देता है। 5.4.5 में फिक्स no-cors को समान-मूल के रूप में विश्वास करना बंद कर देता है। ऑपरेटर जो तुरंत अपग्रेड नहीं कर सकते, वे रिवर्स प्रॉक्सी पर Sec-Fetch-Mode: no-cors वाले अनुरोधों को ड्रॉप कर सकते हैं।
poc/csrf_spawn.html — इसे किसी भी हमलावर मूल पर होस्ट करें और एक लॉग-इन JupyterHub उपयोगकर्ता को इसे खोलने दें। ऑटो-सबमिट करने वाला फॉर्म /hub/spawn पर एक क्रॉस-ओरिजिन POST जारी करता है (ब्राउज़र Sec-Fetch-Mode: no-cors भेजता है); कमजोर बिल्ड इसे बिना किसी मान्य _xsrf टोकन के स्वीकार कर लेते हैं और पीड़ित के सर्वर को स्पॉन कर देते हैं। शेयर-स्वीकृति वेरिएंट के लिए action को /hub/accept-share पर पॉइंट करें।
1. Edit TARGET-JUPYTERHUB in poc/csrf_spawn.html
2. Serve the file from an attacker origin (any static host)
3. Open it in a browser already authenticated to the target Hub
4. Observe the victim's server spawn with no XSRF token supplied
जिम्मेदारी से खुलासा किया गया। फिक्स शिप होने के बाद PoC प्रकाशित किया गया।