
CVE-2026-19445 के लिए प्रूफ-ऑफ-कॉन्सेप्ट लैब, एक CPython ssl SNI SSLContext use-after-free जहाँ एक रिमोट TLS क्लाइंट हैंडशेक के दौरान सर्वर का dispatch context फ्री कर देता है।
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cve-2026-19445-sni-uaf
CPython ssl - Python Software Foundation
एक TLS सर्वर जो प्रत्येक कनेक्शन के लिए एक SSLContext बनाता है, sni_callback सेट करता है, और sslobj.context = other_ctx असाइन करता है, मूल context के अंतिम Python संदर्भ को हटा सकता है, जबकि OpenSSL अभी भी उसके लिए एक उधार लिया गया pointer रखता है। अगला ClientHello (TLS 1.3 HelloRetryRequest पर्याप्त है) उस pointer से परामर्श करता है। Handshake जारी रहता है। प्रक्रिया बाद में crash हो सकती है। Clients प्रभावित नहीं होते। Listening socket के लंबे समय तक चलने वाले wrap पर कोई प्रभाव नहीं पड़ता।
एक दूरस्थ TLS client सर्वर के dispatch SSLContext को मुक्त कर सकता है, जबकि C SNI callback अभी भी उसकी ओर इंगित करता है। Handshake फिर भी पूरा होता है। Crash और memory-corruption विंडो। इस lab में कोई RCE नहीं।
| ID | CVE-2026-19445 |
| CWE | CWE-416 |
| CVSS | Critical: 9.2 CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L |
| Product | CPython ssl |
| Affected | < 3.12.15, 3.13.0-3.13.15, 3.14.0-3.14.7, 3.15.0a1 3.15.0 से पहले |
| Auth | unauthenticated TLS client, सर्वर को SNI-switch करना और मूल context को हटाना होगा |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1 |
एक Python सर्वर से TLS बात करें जो कनेक्शन के लिए एक नया SSLContext बनाता है, sni_callback इंस्टॉल करता है, और उस callback में एक अलग context असाइन करता है और फिर मूल को मरने देता है। SNI भेजें। दूसरा ClientHello बाध्य करें (सर्वर curve को P-384 तक सीमित करें ताकि एक डिफ़ॉल्ट X25519 client को HelloRetryRequest मिले)। GC के बाद, Python ऑब्जेक्ट चला जाता है। C tlsext_servername callback के पास अभी भी SSL_CTX_set_tlsext_servername_arg से उधार लिया गया args pointer है। Handshake इस pin पर पूरा होता है। ASan के तहत यह एक use-after-free है। उत्पादन में यह एक crash / corruption विंडो है जो अगली बार उस memory के पुनः उपयोग होने पर होती है।
जो सर्वर listening socket को एक बार process-lifetime context के साथ wrap करते हैं, वे संदर्भ बनाए रखते हैं। वे इस bug से बाहर हैं। wrap_socket clients इस bug से बाहर हैं।
एक ही उत्पाद, सहोदर अवशेष: wrap_bio hostname verification छोड़ देता है। विपरीत TLS पक्ष। वे एक साथ नहीं चलते।
PSF ने CVE-2026-19445 पोस्ट किया। आरक्षण issue python/cpython#156293 है। वास्तविक map PR 158504 / commit 0f63c2aa है। _servername_callback ने उधार लिए गए OpenSSL arg का उपयोग किया। SNI द्वारा sslobj.context स्विच करने और मूल SSLContext के GC होने के बाद, दूसरा ClientHello अभी भी उसमें कॉल करता है। Patch SSL_get_app_data -> ssl->ctx से context को देखता है और context_dealloc में callback को साफ़ करता है।
मैंने CPython के अपने tests को python:3.14.7-slim-bookworm (3.14.7 प्रभावित सीमा में है; 3.14.8 fix है) के विरुद्ध एक lab के रूप में चलाया। MemoryBIO, UAF पथ के लिए कोई TCP नहीं।
dispatch_ctx.set_ecdh_curve("secp384r1"), क्लाइंट डिफ़ॉल्ट X25519। sni_callback sslobj.context = leaf_ctx असाइन करता है। पहले SNI के बाद, तीन gc.collect() कॉल, weakref.ref(dispatch_ctx) None है। हैंडशेक फिर भी पूरा होता है (TLS_AES_256_GCM_SHA384)। HRR _msg_callback में है (ServerHello random offset 6 पर)। sni_calls=1: दूसरा ClientHello कभी किसी लाइव Python कॉलबैक तक नहीं पहुँचा।
द्वितीयक पथ (कॉलबैक स्विच करता है, del ctx, LookupError उठाता है) ने 3.14.7 को निरस्त नहीं किया। SSLError: CALLBACK_FAILED, unraisable LookupError। नकारात्मक: प्रोसेस-लाइफ़टाइम कॉन्टेक्स्ट जो 127.0.0.1:18500 पर लिसन सॉकेट को रैप करता है। हैंडशेक काम करता है। Weakref जीवित रहता है।
पहले से दर्ज गलत मोड़: dispatch के साथ-साथ leaf पर भी P-384 पिन करना, और क्लाइंट को केवल X25519 तक लॉक करना, HRR के बजाय NO_SUITABLE_KEY_SHARE उत्पन्न करता है। CPython केवल dispatch कॉन्टेक्स्ट को पिन करता है। HRR मैजिक ServerHello offset 6 पर है, 2 पर नहीं। पहली जाँच ने HRR को चूक दिया, भले ही वह सक्रिय हुआ। dispatch_ctx wrap_bio के ठीक बाद भी जीवित है क्योंकि server.context इसे थामे रखता है। यह केवल SNI स्विच के बाद ही संग्रहणीय होता है। नाटक: एक रिवर्स शेल। Oracle dispatch_ref is None के साथ-साथ एक पूर्ण हैंडशेक है।
cd lab
./run.sh
Image python:3.14.7-slim-bookworm. Compose प्रोजेक्ट cve-2026-19445. Loopback 127.0.0.1:18500 नकारात्मक लिसन रैप है। प्राथमिक/द्वितीयक ओरेकल इन-मेमोरी MemoryBIO में हैं।
primary_dispatch_ref_after_sni_gc='none'
primary_hrr='yes'
primary_handshake='complete'
SUCCESS CVE-2026-19445 dispatch_ctx_gc=yes handshake=complete hrr=yes secondary_crash=no CVE-2026-19445-SNI-UAF-WITNESS
सर्वर के जीवनकाल तक sni_callback सेट करने वाले प्रत्येक SSLContext का संदर्भ बनाए रखें। 3.12.15 / 3.13.16 / 3.14.8 / 3.15.0 में अपग्रेड करें। C पैच उधार लिए गए OpenSSL arg का उपयोग करना बंद कर देता है।