flawopen.com/Teardowns/cve-2026-71416-headroom-websocket-origin-hijacking
CVE-2026-71416: Headroom WebSocket Origin हाइजैक
Headroom ने WebSocket Origin की जाँच नहीं की; खोली गई साइट प्रॉक्सी से LLM अनुरोध भेज सकती थी। 0.35.0 या नए संस्करण पर जाएँ।
रिसेप्शन पर आने वाले का पहचान-पत्र जाँचे बिना उसे निजी सेवा-काउंटर तक जाने दिया जाता है। Origin वही पहचान-पत्र है: सहेजी गई API कुंजी इस्तेमाल करने वाला चैनल खोलने से पहले प्रॉक्सी को इसकी जाँच करनी चाहिए।
इस पेज के मुख्य शब्द
WebSocket- HTTP Upgrade अनुरोध से शुरू होने वाला लगातार द्विदिश कनेक्शन, जिसमें दोनों ओर संदेश भेजे जा सकते हैं।
Origin हेडर- ब्राउज़र द्वारा भेजा गया स्कीम, होस्ट और पोर्ट, जो अनुरोध शुरू करने वाले पेज की पहचान करता है। WebSocket हैंडशेक पर सर्वर को अपनी भरोसा-नीति लागू करनी होती है; CORS हेडर इस जाँच का विकल्प नहीं हैं।
CSWSH- Cross-Site WebSocket Hijacking: अविश्वसनीय साइट किसी पहुँच योग्य सेवा से WebSocket खोलती है और सेवा शुरू करने वाले Origin की जाँच नहीं करती।
परिवेश में उपलब्ध क्रेडेंशियल- प्रोसेस को पहले से उपलब्ध रहस्य, जैसे पर्यावरण चर में API कुंजी, जिसे क्लाइंट की अपनी कुंजी के बिना अनुरोध में इस्तेमाल किया जा सकता है।
CWE-1385- WebSocket में Origin सत्यापन का अभाव: एंडपॉइंट यह नहीं जाँचता कि संचार का स्रोत अनुमत है या नहीं।
फ्रेमवर्क मैपिंग
- इस गाइड में बताई गई कमजोरी के लिए CWE संदर्भ: CWE-1385
- OWASP GenAI 2025 — LLM06:2025 अत्यधिक एजेंसी
मूल कारण विश्लेषण (Root Cause)
Headroom का /v1/responses WebSocket हैंडलर हैंडशेक के Origin की जाँच से पहले ब्राउज़र कनेक्शन स्वीकार करता था। इसके बाद प्रॉक्सी अपने पर्यावरण से OPENAI_API_KEY लेकर upstream अनुरोध में जोड़ सकता था। ब्राउज़र की same-origin नीति अपने आप JavaScript को किसी अन्य पहुँच योग्य होस्ट पर WebSocket शुरू करने से नहीं रोकती; ब्राउज़र सामान्यतः Origin भेजता है और सर्वर को अपनी नीति से बाहर के Origin अस्वीकार करने चाहिए। इसलिए शोषण के लिए पीड़ित ब्राउज़र से असुरक्षित Headroom प्रॉक्सी तक पहुँच और प्रॉक्सी में उपयोगी क्रेडेंशियल या एकीकरण होना आवश्यक है। सलाह के अनुसार स्वीकार किया गया कनेक्शन मनमाने LLM अनुरोध भेज सकता है। होस्ट पर कमांड चलना इस बात पर निर्भर है कि अनुरोध कॉन्फ़िगर किए गए कमांड चलाने वाले टूल का उपयोग कर सकता है; केवल हेडर-जाँच की कमी से यह अपने आप नहीं होता। CNA 0.35.0 से पुराने संस्करणों को प्रभावित बताता है, जबकि GitHub सलाह के पैकेज मेटाडेटा में 0.23.0 है। 0.35.0 या नए संस्करण पर जाएँ और स्थापित संस्करण सत्यापित करें।
हमले का चरण-दर-चरण प्रवाह
प्रॉक्सी के पास upstream अधिकार हैं
Headroom प्रोसेस में OPENAI_API_KEY के रूप में OpenAI कुंजी हो सकती है; ब्राउज़र क्लाइंट को कुंजी भेजने की आवश्यकता नहीं है।
ब्राउज़र अविश्वसनीय पेज खोलता है
यदि ब्राउज़र Headroom WebSocket एंडपॉइंट तक पहुँच सकता है, तो पेज का स्क्रिप्ट कनेक्शन का प्रयास कर सकता है। ब्राउज़र हैंडशेक में पेज का Origin शामिल करता है।
कमज़ोर हैंडलर Origin नीति के बिना कनेक्शन स्वीकार करता है
प्रभावित हैंडलर अविश्वसनीय Origin अस्वीकार किए बिना websocket.accept() तक पहुँचता है। same-origin नीति सर्वर-साइड WebSocket प्राधिकरण नहीं है।
प्रॉक्सी प्रमाणीकृत अनुरोध आगे भेजता है
Headroom अनुपस्थित upstream Authorization हेडर को पर्यावरण से भर सकता है। हमलावर-नियंत्रित पेज प्रॉक्सी के अधिकार से अनुरोध करा सकता है; प्रभाव टूल, क्रेडेंशियल, नेटवर्क पहुँच और उपयोगकर्ता क्रिया पर निर्भर है।
फिक्स रूटिंग से पहले निषिद्ध Origin रोकता है
अपस्ट्रीम पैच सत्र स्वीकारने और आगे भेजने से पहले Origin जाँचता है। ब्राउज़र Origin डिफ़ॉल्ट रूप से loopback तक सीमित हैं, स्पष्ट Origin कॉन्फ़िगर किए जा सकते हैं और निषिद्ध कनेक्शन 1008 कोड से बंद होता है।
सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन
सलाह में handle_openai_responses_ws() और websocket.accept() से पहले जाँच न होने की बात है। अपस्ट्रीम commit c632023 _is_allowed_websocket_origin() जोड़ता है और routing से पहले निषिद्ध Origin रोकता है। बिना Origin वाले native clients चलते रहते हैं, ब्राउज़र Origin डिफ़ॉल्ट रूप से loopback तक सीमित हैं, और HEADROOM_WS_ORIGINS या HEADROOM_CORS_ORIGINS से स्पष्ट Origin दिए जा सकते हैं। यह संक्षिप्त उदाहरण बदली हुई भरोसा-सीमा दिखाता है; सहायक फ़ंक्शन पूरे शामिल नहीं हैं। अपस्ट्रीम regression tests अनुपस्थित, loopback, remote, malformed और स्पष्ट रूप से कॉन्फ़िगर किए Origin जाँचते हैं।
सोर्स अंश: headroom/proxy/handlers/openai.py
async def handle_openai_responses_ws(self, websocket: WebSocket) -> None:
# कमज़ोर रूप: origin सत्यापन से पहले ब्राउज़र सत्र स्वीकार करना।
await websocket.accept()
await self._relay_responses_session(websocket)
async def handle_openai_responses_ws(self, websocket: WebSocket) -> None:
ws_headers = dict(websocket.headers)
if not _is_allowed_websocket_origin(ws_headers):
logger.warning(
"event=websocket_origin_not_allowed origin=%r",
_header_get(ws_headers, "origin"),
)
await websocket.close(code=1008, reason="origin not allowed")
return
# केवल नीति-अनुमोदित ब्राउज़र सत्र ही upstream रूटिंग तक पहुँचता है।
await websocket.accept()
await self._relay_responses_session(websocket)
इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट
- ✓Headroom को 0.35.0 या नए संस्करण पर अपडेट करें; केवल dependency फ़ाइल नहीं, स्थापित पैकेज और deployment image का संस्करण भी जाँचें।
- ✓
accept()या upstream संदेश भेजने से पहले WebSocketOriginसत्यापित करें; स्पष्ट अनुमति न हो तो non-loopback Origin अस्वीकार करें। - ✓Origin-विहीन native clients को तभी संगत रखें जब उनका प्रकार अलग से भरोसेमंद हो; ब्राउज़र Origin का न होना प्राधिकरण नहीं है।
- ✓क्रेडेंशियल वाले proxy की अनुमत Origin सूची में
*न रखें; सटीक भरोसेमंद Origin दर्ज करें और default-port normalization का परीक्षण करें। - ✓जहाँ संभव हो, स्थानीय विकास proxy को loopback पर बाँधें; अन्य होस्ट पहुँच सकते हों तो authentication या network controls लागू करें।
- ✓जहाँ उपलब्ध हो, सीमित और अल्पकालिक upstream कुंजियाँ उपयोग करें; ब्राउज़र सीमा पार करने वाले अनुरोधों को shell जैसे उच्च-प्रभाव वाले टूल न दें।
- ✓ऐसे regression tests जोड़ें जो remote Origin को upstream routing से पहले policy violation के साथ बंद करें और loopback, configured Origin तथा स्वीकृत native client व्यवहार भी जाँचें।
- ✓कमांड चलना configured tools पर निर्भर है; Origin की कमी को अपने आप host RCE न कहें।