Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
cve-2026-19445-sni-uaf — Proof-of-concept lab for CVE-2026-19445, a CPython ssl SNI SSLContext use-after-free where a remote TLS client frees the server's dispatch context during handshake. | Kitploit
Tools/GitHubGitHub/abraxas/cve-2026-19445-sni-uaf
Dynamic Analysis (Sandboxing)Memory ForensicsVulnerability AnalysisExploitationCryptographyPapers & ResearchLabs & Practice
GitHubabraxas/cve-2026-19445-sni-uaf

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →

cve-2026-19445-sni-uaf

Proof-of-concept lab for CVE-2026-19445, a CPython ssl SNI SSLContext use-after-free where a remote TLS client frees the server's dispatch context during handshake.

View Repository
1 day agoNot yet reviewed
Share

Abraxas Labs - cve-2026-19445-sni-uaf

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  cve-2026-19445-sni-uaf

cve-2026-19445-sni-uaf

CPython ssl - Python Software Foundation

A TLS server that mints an SSLContext per connection, sets sni_callback, and assigns sslobj.context = other_ctx can drop the last Python reference to the original context while OpenSSL still holds a borrowed pointer to it. The next ClientHello (TLS 1.3 HelloRetryRequest is enough) consults that pointer. The handshake continues. The process may crash later. Clients are not affected. A long-lived wrap of the listening socket is not affected.

A remote TLS client can free the server's dispatch SSLContext while the C SNI callback still points at it. Handshake still completes. Crash and memory-corruption window. No RCE in this lab.

IDCVE-2026-19445
CWECWE-416
CVSSCritical: 9.2 CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:L
ProductCPython ssl
Affected< 3.12.15, 3.13.0–3.13.15, 3.14.0–3.14.7, 3.15.0a1 before 3.15.0
Authunauthenticated TLS client, server must SNI-switch and drop the original context
LicenseGNU Affero GPL v3.0
Lab127.0.0.1 only

What an attacker can do

Talk TLS to a Python server that creates a fresh SSLContext for the connection, installs sni_callback, and in that callback assigns a different context then lets the original one die. Send SNI. Force a second ClientHello (restrict the server curve to P-384 so a default X25519 client gets HelloRetryRequest). After GC, the Python object is gone. The C tlsext_servername callback still has the borrowed args pointer from SSL_CTX_set_tlsext_servername_arg. Handshake completes on this pin. Under ASan that is a use-after-free. In production it is a crash / corruption window the next time that memory is reused.

Servers that wrap the listening socket once with a process-lifetime context keep the reference. Those are outside the bug. wrap_socket clients are outside the bug.

Same product, sibling leftover: wrap_bio skips hostname verification. Opposite TLS side. They do not compose.

How I found it

PSF posted CVE-2026-19445. The reservation issue is python/cpython#156293. The real map is PR 158504 / commit 0f63c2aa. _servername_callback used the borrowed OpenSSL arg. After SNI switches sslobj.context and the original SSLContext is GC'd, the second ClientHello still calls into it. The patch looks up the context from SSL_get_app_data → ssl->ctx and clears the callback in context_dealloc.

I ran CPython's own tests as a lab against python:3.14.7-slim-bookworm (3.14.7 is in the affected range; 3.14.8 is the fix). MemoryBIO, no TCP for the UAF path.

dispatch_ctx.set_ecdh_curve("secp384r1"), client default X25519. sni_callback assigns sslobj.context = leaf_ctx. After the first SNI, three gc.collect() calls, weakref.ref(dispatch_ctx) is None. Handshake still completes (TLS_AES_256_GCM_SHA384). HRR is in _msg_callback (ServerHello random at offset 6). sni_calls=1: the second ClientHello never reached a live Python callback.

Secondary path (callback switches, del ctx, raises LookupError) did not abort 3.14.7. SSLError: CALLBACK_FAILED, unraisable LookupError. Negative: process-lifetime context wrapping a listen socket on 127.0.0.1:18500. Handshake works. Weakref stays alive.

Wrong turns already recorded: pinning P-384 on the leaf as well as dispatch, plus locking the client to X25519-only, produced NO_SUITABLE_KEY_SHARE instead of HRR. CPython only pins the dispatch context. HRR magic is at ServerHello offset 6, not 2. First probe missed HRR even when it fired. dispatch_ctx is still alive right after wrap_bio because server.context holds it. It becomes collectable only after the SNI switch. Theatre: a reverse shell. The oracle is dispatch_ref is None plus a completed handshake.

Lab

cd lab
./run.sh

Image python:3.14.7-slim-bookworm. Compose project cve-2026-19445. Loopback 127.0.0.1:18500 is the negative listen wrap. Primary/secondary oracles are in-memory 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

The fix

Keep a reference to every SSLContext that sets sni_callback for the lifetime of the server. Upgrade to 3.12.15 / 3.13.16 / 3.14.8 / 3.15.0. The C patch stops using the borrowed OpenSSL arg.

References

  • CVE-2026-19445
  • python/cpython#156293
  • PR 158504
  • commit 0f63c2aa
  • PSF security-announce
Download Tool