FlawOpen

flawopen.com/AI Security/mlflow-webhook-ssrf-cve-2026-64849

● CVE-2026-64849 · CVSS 8.6 · उच्च
सुरक्षा अनुसंधान · FlawOpen

CVE-2026-64849: MLflow Webhook में SSRF

CVE-2026-64849 MLflow की webhook भेजने की प्रक्रिया में बिना प्रमाणीकरण का सर्वर-पक्षीय अनुरोध जालसाजी (SSRF) दोष है (उच्च, CVSS 3.1: 8.6)। आरंभिक वेब-पता जाँच आगे होने वाले पुनर्निर्देशन और वास्तविक संपर्क-गंतव्य को सीमित नहीं करती थी; परीक्षण सुविधा दूरस्थ सर्वर के उत्तर का पाठ वापस भेज सकती थी।[1]

💡 आसान भाषा में (ELI5)

डाकघर का कर्मचारी पार्सल पर लिखा पहला पता जाँचता है, फिर डाकिए को रास्ते में मिली नई अग्रेषण-पर्ची पर बिना जाँच आगे बढ़ने देता है। MLflow में भी webhook का शुरूआती वेब-पता जाँचा जाता था, लेकिन पुनर्निर्देशन या DNS की दूसरी खोज से मिले पते की नहीं। सुधार वास्तविक सॉकेट के दूसरे छोर का IP पता जाँचकर HTTP संदेश भेजने से पहले गैर-सार्वजनिक गंतव्य रोकता है।[1], [2]

इस पेज के मुख्य शब्द

SSRF
सर्वर उपयोगकर्ता के चुने वेब-पते पर अनुरोध भेजकर ऐसे आंतरिक संजाल तक पहुँच सकता है जहाँ अनुरोधकर्ता नहीं पहुँच सकता; इसे SSRF कहते हैं।[1]
Webhook परीक्षण सुविधा
MLflow का API, जो तय किए गए webhook पर परीक्षण घटना भेजता है; प्रभावित सामान्य व्यवस्था में इसका उत्तर-पाठ अनुरोधकर्ता को लौटाया जाता था।[1]
DNS rebinding / जाँच-उपयोग समयांतर (TOCTOU)
DNS rebinding में एक ही मेज़बान नाम जाँच के समय सार्वजनिक IP पते पर मिलता है, लेकिन संपर्क बनाते समय अलग, गैर-सार्वजनिक पते पर। यही जाँच और उपयोग के बीच का समयांतर (TOCTOU) है।[1], [2]

फ्रेमवर्क मैपिंग

हमले का चरण-दर-चरण प्रवाह

चरण 1

MLflow सर्वर webhook परीक्षण स्वीकार करता है

MLflow की सुरक्षा सूचना बताती है कि सामान्य Tracking Server स्थापना में प्रमाणीकरण नहीं होता। वैकल्पिक प्रमाणीकरण plug-in और deployment सुरक्षा नियंत्रण पहुँच की स्थिति बदल सकते हैं; अपनी व्यवस्था जाँचें। 19 अगस्त 2026 को CISA ने इस CVE को Known Exploited Vulnerabilities सूची में जोड़ा। यह ज्ञात शोषण का संकेत है, किसी खास स्थापना के भीतर घुसपैठ का प्रमाण नहीं।[1], [4], [5]

चरण 2

आरंभिक वेब-पता जाँच में पास हो जाता है

_validate_webhook_url मूल hostname का IP पता खोजकर जाँचता है, लेकिन मिले हुए पते को बाद में बनाए गए socket से नहीं बाँधता।[1]

चरण 3

पुनर्निर्देशन या DNS की दूसरी खोज गंतव्य बदल सकती है

HTTP client आगे दिए गए पुनर्निर्देशनों पर चलता है और संपर्क बनाते समय मेज़बान नाम फिर खोज सकता है। परीक्षण सुविधा दूरस्थ सर्वर के उत्तर का पाठ लौटाती है, इसलिए पूरी प्रतिक्रिया पढ़ सकने वाली SSRF संभव है।[1]

चरण 4

सुधार वास्तविक जुड़ाव के दूसरे छोर का IP जाँचता है

PR #24258 जुड़ाव बनते ही, TLS आदान-प्रदान या HTTP संदेश भेजने से पहले socket के peer का IP जाँचता है; इस सत्र में पर्यावरण से proxy लेने की सुविधा भी बंद रहती है। CVE MLflow 3.15.0 में ठीक हुआ; IPv6 पते बदलने के तरीकों से जुड़े अलग bypass 3.16.0 में ठीक किए गए। Advisory में freeman-bb को मूल गोपनीय रिपोर्टकर्ता और AUTHENSOR को स्वतंत्र खोजकर्ता का श्रेय दिया गया है।[1], [2], [3], [6]

सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन

ये चुने हुए अंश आरंभिक वेब-पता जाँच और अनुरोध की सीमा, तथा संपर्क बनते समय peer की जाँच दिखाते हैं। _assert_public_peer helper वास्तविक socket पता जाँचता है और पता जाँचा न जा सके या वह सार्वजनिक न हो तो connection बंद कर देता है। उदाहरण में exploit अनुरोध या आंतरिक गंतव्य शामिल नहीं हैं। 3.16.0 का IPv6 normalization बाद का अलग सुधार है।[2]

कमज़ोर कार्यान्वयन
# PR #24258 से पहले mlflow/webhooks/delivery.py का अंश।
_validate_webhook_url(webhook.url)  # केवल शुरुआती URL जाँचता है
return session.post(
    webhook.url, data=payload_bytes, headers=headers, timeout=timeout
)  # redirect अपने-आप चलते हैं; जाँचा हुआ IP connection से नहीं बाँधा जाता
सुरक्षित और सुदृढ़ फ़िक्स
# कनेक्शन के समय peer की जाँच करने वाले upstream सुधार का अंश।
def _assert_public_peer(sock):
    if _MLFLOW_WEBHOOK_ALLOW_PRIVATE_IPS.get():
        return
    try:
        peer_ip = sock.getpeername()[0]
    except OSError as exc:
        sock.close()
        raise SSRFProtectionError(
            f"Could not determine webhook connection peer address: {exc}"
        ) from exc
    try:
        ip = ipaddress.ip_address(peer_ip)
    except ValueError as exc:
        sock.close()
        raise SSRFProtectionError(
            f"Webhook connection resolved to an invalid IP address: {peer_ip!r}"
        ) from exc
    if not ip.is_global:
        sock.close()
        raise SSRFProtectionError(
            f"Webhook connection blocked: {ip} is not a public IP address. "
            "This may indicate a DNS rebinding attempt."
        )


class _SSRFProtectedHTTPConnection(HTTPConnection):
    def _new_conn(self):
        sock = super()._new_conn()
        _assert_public_peer(sock)
        return sock


class _SSRFProtectedHTTPSConnection(HTTPSConnection):
    def _new_conn(self):
        sock = super()._new_conn()
        _assert_public_peer(sock)
        return sock

adapter = SSRFProtectedHTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.trust_env = False
session.mount("http://", adapter)
session.mount("https://", adapter)

इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट

स्रोत

← AI Security Directory →