ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)

Tip

Nauči i vežbaj AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Nauči i vežbaj GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Nauči i vežbaj Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Pregledaj kompletan HackTricks Training katalog za assessment tracks (ARTA/GRTA/AzRTA) i Linux Hacking Expert (LHE).

Podrži HackTricks

Ova stranica dokumentuje deterministički out-of-bounds write u ksmbd streams obradi koji omogućava pouzdanu Linux kernel privilege escalation na Ubuntu 22.04 LTS (5.15.0-153-generic), zaobilaženjem KASLR, SMEP i SMAP koristeći standardne kernel heap primitive (msg_msg + pipe_buffer).

  • Affected component: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
  • Primitive: page-overflow OOB write past a 0x10000-byte kvmalloc() buffer
  • Preconditions: ksmbd running with an authenticated, writable share using vfs streams_xattr

Example smb.conf

[share]
path = /share
vfs objects = streams_xattr
writeable = yes

Root cause (allocation clamped, memcpy at unclamped offset)

  • Funkcija računa size = *pos + count, ograničava size na XATTR_SIZE_MAX (0x10000) kada se prekorači, i ponovo računa count = (*pos + count) - 0x10000, ali i dalje izvršava memcpy(&stream_buf[*pos], buf, count) u buffer od 0x10000 bajtova. Ako je *pos ≥ 0x10000, odredišni pokazivač je već van alokacije, što proizvodi OOB write od count bajtova.
  • streams_xattr čuva SMB alternate data streams unutar POSIX extended attributes, pa 0x10000 granica dolazi iz Linux single-xattr size limita, a ne iz SMB protocol polja. To čini bug praktičnim samo kada share eksplicitno omogućava vfs objects = streams_xattr i filesystem podržava xattrs.

Why the write offset matters

  • Vulnerable path nije samo “write više od 64KiB”. Nedostajala je provera da *pos nije validiran u odnosu na trenutnu stream dužinu (v_len) pre nego što su pokrenuti append/copy logic.
  • Upstream je ovo popravio tako što odbija writes gde je *pos >= v_len sa -EINVAL. Pre fix-a, attacker je mogao da ponovo iskoristi validan authenticated handle na named stream i pošalje raw SMB2 WRITE čiji file_offset već pokazuje na ili iza kraja postojećeg stream-a, što post-clamp memcpy() pretvara u deterministički page overflow.
  • Public PoC ovo demonstrira tako što se autentifikuje sa libsmb2, otvori stream path kao što je 1337:, izdvoji SessionId/TreeId/FileId, i zatim pošalje handcrafted SMB2 WRITE sa file_offset = 0x10018 i malim Length.
Vulnerable function snippet (ksmbd_vfs_stream_write) ```c // https://elixir.bootlin.com/linux/v5.15/source/fs/ksmbd/vfs.c#L411 static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, size_t count) { char *stream_buf = NULL, *wbuf; size_t size; ... size = *pos + count; if (size > XATTR_SIZE_MAX) { // [1] clamp allocation, but... size = XATTR_SIZE_MAX; count = (*pos + count) - XATTR_SIZE_MAX; // [1.1] ...recompute count } wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO); // [2] alloc 0x10000 stream_buf = wbuf; memcpy(&stream_buf[*pos], buf, count); // [3] OOB when *pos >= 0x10000 ... kvfree(stream_buf); return err; } ```

Offset steering and OOB length

  • Primer: postavi file offset (pos) na 0x10018 i originalnu dužinu (count) na 8. Nakon clamping-a, count’ = (0x10018 + 8) - 0x10000 = 0x20, ali memcpy upisuje 32 bajta počev od stream_buf[0x10018], tj. 0x18 bajtova iza 16-page allocation.

Triggering the bug via SMB streams write

  • Koristi istu authenticated SMB connection da otvoriš fajl na share-u i izvršiš write u named stream (streams_xattr). Postavi file_offset ≥ 0x10000 sa malom dužinom da bi generisao deterministic OOB write kontrolisane veličine.
  • libsmb2 može da se koristi za authenticate i craftovanje takvih write-ova preko SMB2/3.
  • U praksi, ponovno korišćenje negotiated SMB session-a je zgodno jer exploit treba samo da patch-uje nekoliko dynamic polja u WRITE request-u (TreeId, SessionId, FileId) i zatim može direktno da pošalje malformed packet na istom socket-u.

Minimal reachability (concept)

// Pseudocode: send SMB streams write with pos=0x0000010018ULL, len=8
smb2_session_login(...);
smb2_open("\\\\host\\share\\file:stream", ...);
smb2_pwrite(fd, payload, 8, 0x0000010018ULL); // yields 32-byte OOB

Ponašanje alokatora i zašto je potrebno page shaping

  • kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) traži alokaciju order-4 (16 uzastopnih stranica) od buddy allocator-a kada je size > KMALLOC_MAX_CACHE_SIZE. Ovo nije SLUB cache object.
  • memcpy se dešava odmah nakon alokacije; spraying nakon alokacije je neefikasan. Morate unapred groomovati fizičku memoriju tako da se izabrani target nalazi odmah nakon dodeljenog 16-page bloka.
  • Na Ubuntu-u, GFP_KERNEL često uzima iz Unmovable migrate type u zone Normal. Ispraznite order-3 i order-4 freelists da naterate alokator da podeli order-5 block u susedni order-4 + order-3 par, zatim parkirajte order-3 slab (kmalloc-cg-4k) direktno iza stream buffer-a.

Praktična strategija page shaping

  • Spray-ujte ~1000–2000 msg_msg objects od ~4096 bytes (odgovara kmalloc-cg-4k) da popunite order-3 slabs.
  • Primite neke poruke da napravite rupe i podstaknete adjacency.
  • Pokrenite ksmbd OOB više puta dok order-4 stream buffer ne padne odmah pre msg_msg slab-a. Koristite eBPF tracing da potvrdite adrese i alignment ako je dostupno.

Korisna observability

# Check per-order freelists and migrate types
sudo cat /proc/pagetypeinfo | sed -n '/Node 0, zone  Normal/,/Node/p'
# Example tracer (see reference repo) to log kvmalloc addresses/sizes
sudo ./bpf-tracer.sh

Šta pratiti tokom tuniranja

  • kvmalloc_node(0x10000) potvrđuje kada ranjivi stream write zaista troši order-4 alokaciju.
  • load_msg/kretprobe:load_msg omogućava procenu koliko je msg_msgseg alokacija nakačeno na svaku raspršenu poruku, što je korisno pri tuniranju primary/secondary veličina poruka za određeni kernel build.
  • Ako se exploit portuje na drugi distro/kernel, ponovo proveri cache imena, inline msg_msg payload veličine, anon_pipe_buf_ops offsete i gadget adrese, umesto da pretpostaviš da Ubuntu 22.04 LTS 5.15.0-153-generic konstante i dalje odgovaraju.

Plan eksploatacije (msg_msg + pipe_buffer), prilagođen iz CVE-2021-22555

  1. Rasprši mnogo System V msg_msg primary/secondary poruka (veličine 4KiB da stanu u kmalloc-cg-4k).
  2. Okini ksmbd OOB da ošteti next pointer primary poruke tako da dve primarne dele jednu sekundarnu.
  3. Detektuj oštećeni par tagovanjem queue-ova i skeniranjem sa msgrcv(MSG_COPY) da pronađeš neusklađene tagove.
  4. Oslobodi stvarnu sekundarnu da bi napravio UAF; preuzmi je kontrolisanim podacima preko UNIX sockets (napravi lažnu msg_msg).
  5. Leak-uj kernel heap pointere zloupotrebom m_ts over-read u copy_msg da dobiješ mlist.next/mlist.prev (SMAP bypass).
  6. Uz sk_buff spray, rekonstruiši konzistentnu lažnu msg_msg sa validnim linkovima i oslobodi je normalno da stabilizuješ stanje.
  7. Ponovo preuzmi UAF sa struct pipe_buffer objektima; leak-uj anon_pipe_buf_ops da izračunaš kernel base (defeat KASLR).
  8. Rasprši lažni pipe_buf_operations sa release koji pokazuje na stack pivot/ROP gadget; zatvori pipe-ove da izvršiš i dobiješ root.

Bypasses and notes

  • KASLR: leak-uj anon_pipe_buf_ops, izračunaj base (kbase_addr) i adrese gadgeta.
  • SMEP/SMAP: izvrši ROP u kernel kontekstu preko pipe_buf_operations->release toka; izbegavaj userspace deref-ove dok chain ne uradi disable/prepare_kernel_cred/commit_creds.
  • Hardened usercopy: nije primenljivo na ovaj page overflow primitive; mete korupcije su polja koja nisu usercopy.

Pouzdanost

  • Visoka kada se postigne susednost; povremeni promašaji ili panici (<10%). Tuniranje broja spray/free operacija poboljšava stabilnost. Prepisivanje dva LSB bita pointera da bi se izazvali specifični kolizije prijavljeno je kao efikasno (npr. upiši 0x0000_0000_0000_0500 pattern u overlap).

Ključni parametri za tuniranje

  • Broj msg_msg spray-ova i hole pattern
  • OOB offset (pos) i rezultujuća OOB dužina (count’)
  • Broj UNIX socket, sk_buff i pipe_buffer spray-ova tokom svake faze

Mitigations and reachability

  • Ispravka: ograniči i alokaciju i destination/length ili ograniči memcpy prema veličini alokacije; upstream zakrpe su vođene kao CVE-2025-37947.
  • Remote exploitation bi dodatno zahtevao pouzdan infoleak i remote heap grooming; ovaj write-up je fokusiran na lokalni LPE.

Vidi i

Ksmbd Attack Surface And Fuzzing Syzkaller

References PoC and tooling

  • libsmb2 za SMB auth i streams writes
  • eBPF tracer script za logovanje kvmalloc adresa i histogram alokacija (npr. grep 4048 out-4096.txt)
  • Minimal reachability PoC i full local exploit su javno dostupni (vidi References)

References

Tip

Nauči i vežbaj AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Nauči i vežbaj GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Nauči i vežbaj Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Pregledaj kompletan HackTricks Training katalog za assessment tracks (ARTA/GRTA/AzRTA) i Linux Hacking Expert (LHE).

Podrži HackTricks