
مختبر إثبات مفهوم لـ CVE-2026-19445، وهو ثغرة use-after-free في CPython ssl SNI SSLContext حيث يقوم عميل TLS بعيد بتحرير سياق الإرسال الخاص بالخادم أثناء المصافحة.
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 يمكن أن يُسقط آخر مرجع Python للسياق الأصلي بينما لا يزال OpenSSL يحتفظ بمؤشر مستعار إليه. الـ ClientHello التالي (يكفي TLS 1.3 HelloRetryRequest) يستشير ذلك المؤشر. تستمر المصافحة. قد تنهار العملية لاحقًا. العملاء غير متأثرين. الالتفاف طويل الأمد حول مقبس الاستماع غير متأثر.
يمكن لعميل TLS بعيد تحرير SSLContext الخاص بالتوجيه في الخادم بينما لا يزال رد نداء SNI بلغة C يشير إليه. تكتمل المصافحة رغم ذلك. نافذة انهيار وتلف ذاكرة. لا RCE في هذا المختبر.
| ID | CVE-2026-19445 |
| CWE | CWE-416 |
| CVSS | حرج: 9.2 CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L |
| المنتج | CPython ssl |
| المتأثر | < 3.12.15، 3.13.0–3.13.15، 3.14.0–3.14.7، 3.15.0a1 قبل 3.15.0 |
| المصادقة | عميل TLS غير مصادق، يجب على الخادم تبديل SNI وإسقاط السياق الأصلي |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1 فقط |
التحدث بـ TLS إلى خادم Python ينشئ SSLContext جديدًا للاتصال، ويثبّت sni_callback، وفي ذلك الرد يعيّن سياقًا مختلفًا ثم يترك السياق الأصلي يموت. أرسل SNI. أجبر ClientHello ثانيًا (قيّد منحنى الخادم إلى P-384 حتى يحصل عميل X25519 الافتراضي على HelloRetryRequest). بعد GC، يختفي كائن Python. لا يزال رد نداء tlsext_servername بلغة C يحتفظ بمؤشر args المستعار من SSL_CTX_set_tlsext_servername_arg. تكتمل المصافحة على هذا التثبيت. تحت ASan هذا استخدام بعد التحرير. في الإنتاج هو نافذة انهيار / تلف في المرة التالية التي تُعاد فيها استخدام تلك الذاكرة.
الخوادم التي تلتف حول مقبس الاستماع مرة واحدة بسياق يمتد لعمر العملية تحتفظ بالمرجع. تلك خارج نطاق العلّة. عملاء wrap_socket خارج نطاق العلّة.
نفس المنتج، بقايا شقيقة: wrap_bio يتخطى التحقق من اسم المضيف. الجانب المعاكس من TLS. لا يتكاملان.
نشرت PSF CVE-2026-19445. قضية الحجز هي python/cpython#156293. الخريطة الحقيقية هي PR 158504 / الالتزام 0f63c2aa. استخدم _servername_callback وسيط OpenSSL المستعار. بعد أن يبدّل SNI قيمة sslobj.context ويُجمع SSLContext الأصلي كقمامة، لا يزال ClientHello الثاني يستدعي داخله. تُحضر الترقعة السياق من SSL_get_app_data → ssl->ctx وتمسح رد النداء في context_dealloc.
شغّلت اختبارات CPython الخاصة كمختبر ضد python:3.14.7-slim-bookworm (3.14.7 ضمن النطاق المتأثر؛ 3.14.8 هو الإصلاح). MemoryBIO، بدون TCP لمسار UAF.
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 عشوائي عند الإزاحة 6). sni_calls=1: لم يصل ClientHello الثاني أبدًا إلى رد نداء Python حي.
المسار الثانوي (رد النداء يبدّل، del ctx، يرفع LookupError) لم يُجهض 3.14.7. SSLError: CALLBACK_FAILED، LookupError غير قابل للرفع. سلبي: سياق يمتد لعمر العملية يلتف حول مقبس استماع على 127.0.0.1:18500. المصافحة تعمل. يبقى weakref حيًا.
المنعطفات الخاطئة المسجلة مسبقًا: تثبيت P-384 على leaf وكذلك dispatch، مع قفل العميل على X25519 فقط، أنتج NO_SUITABLE_KEY_SHARE بدلًا من HRR. يثبّت CPython سياق dispatch فقط. سحر HRR عند الإزاحة 6 في ServerHello، وليس 2. أخطأ المسبار الأول في HRR حتى عندما انطلق. لا يزال dispatch_ctx حيًا مباشرة بعد wrap_bio لأن server.context يحتفظ به. يصبح قابلًا للجمع فقط بعد تبديل SNI. مسرحية: reverse shell. الأوراكل هو dispatch_ref is None بالإضافة إلى مصافحة مكتملة.
cd lab
./run.sh
الصورة 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
احتفظ بمرجع لكل SSLContext يضبط sni_callback طوال عمر الخادم. قم بالترقية إلى 3.12.15 / 3.13.16 / 3.14.8 / 3.15.0. تتوقف ترقعة C عن استخدام وسيط OpenSSL المستعار.