Skip to content

TLS context UAF (CVE-2023-0461)

Connected bir TCP socket'ine attach edilmiş bir TLS upper-layer-protocol context'i, socket bir listener olarak yeniden kullanıldığında temizlenmez; böylece accept edilen child socket'ler dangling bir icsk_ulp_data pointer'ı inherit eder — Linux'ta unprivileged bir yerel use-after-free.

Mechanism

Note

Linux, userspace'in setsockopt(TCP_ULP, "tls") ile bir TCP socket'inin üzerine bir upper-layer protocol (ULP) stack'lemesine izin verir. Bu, bir struct tls_context allocate eder ve onu socket'in inet_connection_sock'unun icsk_ulp_data'sında saklar. Kırılan invariant şudur: bir ULP context'i kurulmuş bir socket'in, accept edilen child'larının o context'i körü körüne inherit ettiği bir listening socket'i haline gelmesine izin verilmemelidir. TLS ULP yalnızca established bağlantıları destekler; bir TCP_ULP=tls socket'i disconnect edilip sonra listen() yapıldığında, stale tls_context attach edilmiş halde kalır. accept()'te yeni child socket, parent'ın icsk_ulp_data pointer'ını inherit eder, ama context'in lifetime'ı orijinal socket'e bağlıdır — bu da dangling bir pointer ve bir use-after-free verir.

Kritik olarak, setsockopt(TCP_ULP) hiçbir privilege gerektirmez, dolayısıyla CONFIG_TLS (veya CONFIG_XFRM_ESPINTCP) ile derlenmiş bir kernel'deki herhangi bir yerel kullanıcı bu açığa ulaşabilir — güçlü bir local-privilege-escalation primitive'i.

Walkthrough

Red Hat advisory'sine ve upstream fix'ine dayanan yüksek seviyeli anlatım:

  1. s = socket(AF_INET, SOCK_STREAM); onu connect et, sonra bir tls_context kurmak için setsockopt(s, SOL_TCP, TCP_ULP, "tls", 4).
  2. Disconnect et (örn. AF_UNSPEC'e connect()) ve s'i bir server olarak yeniden kullan: listen(s, ...). TLS context'i bu geçişte tear down edilmez.
  3. accept(s), parent'ın tls_context'ine işaret eden icsk_ulp_data'yı inherit eden bir child socket üretir.
  4. Child üzerindeki operasyonlar (veya orijinal context'i free etmek), backing object free edildikten/yeniden kullanıldıktan sonra inherit edilen pointer'ı dereference eder ve klasik UAF'yi verir: function pointer'ları corrupt etmek veya escalate etmek için slot'u attacker'ın kontrol ettiği veriyle reclaim et.

Warning

Açıklama kavramsaldır; bu giriş, dangling context'i silaha çevirmek için gereken heap-spray reclamation ve control-flow adımlarını bilinçli olarak atlar.

Detection

  • Kernel loglarında tls_context, tls_* callback'leri veya inet_connection_sock/ULP teardown path'lerine atıf yapan KASAN "use-after-free" raporları.
  • Unprivileged process'lerin aynı fd üzerinde TCP_ULP=tls → disconnect → listen()accept() şeklindeki olağandışı diziyi gerçekleştirmesi; gerçek bir TLS workload'u için anormal bir state machine.
  • Socket close veya accept()'ten kaynaklanan, ardından bir child process'in yükseltilmiş privilege kazandığı kernel panic'leri/oops'ları.
  • Expose taraması: Aralık-2022/2023 başı fix'inden önceki, CONFIG_TLS=y olan ve kısıtlanmamış yerel kullanıcılara sahip kernel'ler.

Mitigation

  • Patch: upstream commit 2c02d41d71f9 ("net/ulp: prevent ULP without clone op from entering the LISTEN status") ile düzeltildi, ~6.2-rc3'te merge edildi ve distro'lar tarafından backport edildi. Kernel'i güncelle.
  • Patch gecikiyorsa ve TLS-in-kernel (kTLS) kullanılmıyorsa, CONFIG_TLS/CONFIG_XFRM_ESPINTCP olmadan derlemek attack surface'i kaldırır.
  • Untrusted yerel kodu kısıtla; containerize et. Allocator hardening (slab-freelist-randomization, init_on_free) UAF exploitation maliyetini artırır.

References