ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Αυτή η σελίδα τεκμηριώνει μια ντετερμινιστική out-of-bounds write στον χειρισμό των ksmbd streams που επιτρέπει αξιόπιστο Linux kernel privilege escalation σε Ubuntu 22.04 LTS (5.15.0-153-generic), παρακάμπτοντας KASLR, SMEP και SMAP χρησιμοποιώντας τυπικά kernel heap primitives (msg_msg + pipe_buffer).
- Επηρεασμένο στοιχείο: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
- Primitive: page-overflow OOB write past a 0x10000-byte kvmalloc() buffer
- Προϋποθέσεις: ksmbd running with an authenticated, writable share using vfs streams_xattr
Παράδειγμα smb.conf
[share]
path = /share
vfs objects = streams_xattr
writeable = yes
Βασική αιτία (η κατανομή περιορίζεται, memcpy σε μη-περιορισμένη μετατόπιση)
- Η συνάρτηση υπολογίζει size = *pos + count, περιορίζει το size στο XATTR_SIZE_MAX (0x10000) όταν υπερβαίνεται, και επανυπολογίζει το count = (*pos + count) - 0x10000, αλλά εξακολουθεί να εκτελεί memcpy(&stream_buf[*pos], buf, count) σε 0x10000-byte buffer. Αν *pos ≥ 0x10000 ο δείκτης προορισμού είναι ήδη εκτός της κατανομής, παράγοντας ένα OOB write μεγέθους count bytes.
Απόσπασμα ευπαθούς συνάρτησης (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 και μήκος OOB
- Παράδειγμα: θέστε το file offset (pos) σε 0x10018 και το αρχικό μήκος (count) σε 8. Μετά τον περιορισμό (clamping), count’ = (0x10018 + 8) - 0x10000 = 0x20, αλλά η memcpy γράφει 32 bytes ξεκινώντας από stream_buf[0x10018], δηλαδή 0x18 bytes πέρα από την κατανομή των 16 σελίδων.
Triggering the bug via SMB streams write
- Χρησιμοποιήστε την ίδια authenticated SMB σύνδεση για να ανοίξετε ένα αρχείο στο share και να εκτελέσετε μια write σε ένα named stream (streams_xattr). Θέστε file_offset ≥ 0x10000 με μικρό μήκος για να παραχθεί μια deterministic OOB write ελεγχόμενου μεγέθους.
- Το libsmb2 μπορεί να χρησιμοποιηθεί για authentication και για τη δημιουργία τέτοιων writes πάνω από SMB2/3.
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
Συμπεριφορά του allocator και γιατί απαιτείται page shaping
- kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) requests an order-4 (16 contiguous pages) allocation from the buddy allocator when size > KMALLOC_MAX_CACHE_SIZE. Αυτό δεν είναι ένα SLUB cache object.
- memcpy occurs immediately after allocation; post-allocation spraying is ineffective. Πρέπει να κάνετε pre-groom της φυσικής μνήμης ώστε ένας επιλεγμένος στόχος να βρεθεί αμέσως μετά το δεσμευμένο block των 16 σελίδων.
- On Ubuntu, GFP_KERNEL often pulls from the Unmovable migrate type in zone Normal. Εξαντλήστε τα freelists των order-3 και order-4 για να αναγκάσετε τον allocator να σπάσει ένα order-5 block σε ένα παρακείμενο pair order-4 + order-3, και στη συνέχεια τοποθετήστε ένα order-3 slab (kmalloc-cg-4k) αμέσως μετά το stream buffer.
Practical page shaping strategy
- Spray ~1000–2000 msg_msg objects of ~4096 bytes (fits kmalloc-cg-4k) to populate order-3 slabs.
- Receive some messages to punch holes and encourage adjacency.
- Trigger the ksmbd OOB repeatedly until the order-4 stream buffer lands immediately before a msg_msg slab. Use eBPF tracing to confirm addresses and alignment if available.
Useful 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
Σχέδιο εκμετάλλευσης (msg_msg + pipe_buffer), προσαρμοσμένο από CVE-2021-22555
- Spray πολλά System V msg_msg primary/secondary μηνύματα (4KiB-sized για να χωράνε σε kmalloc-cg-4k).
- Προκαλέστε ksmbd OOB για να καταστραφεί ο primary message’s next pointer ώστε δύο primaries να μοιράζονται ένα secondary.
- Εντοπίστε το corrupted pair επισημαίνοντας ουρές και σαρώνοντας με msgrcv(MSG_COPY) για να βρείτε mismatched tags.
- Free το πραγματικό secondary για να δημιουργηθεί UAF; ανακτήστε το με ελεγχόμενα δεδομένα μέσω UNIX sockets (craft ένα fake msg_msg).
- Leak kernel heap pointers εκμεταλλευόμενοι το m_ts over-read στο copy_msg για να αποκτήσετε mlist.next/mlist.prev (SMAP bypass).
- Με ένα sk_buff spray, αναδομήστε ένα συνεπές fake msg_msg με έγκυρους συνδέσμους και free το κανονικά για σταθεροποίηση της κατάστασης.
- Reclaim το UAF με struct pipe_buffer objects; leak anon_pipe_buf_ops για να υπολογίσετε το kernel base (defeat KASLR).
- Spray ένα fake pipe_buf_operations με release που δείχνει σε stack pivot/ROP gadget; κλείστε τα pipes για εκτέλεση και απόκτηση root.
Παράκαμψεις και σημειώσεις
- KASLR: leak anon_pipe_buf_ops, compute base (kbase_addr) και gadget addresses.
- SMEP/SMAP: execute ROP στο kernel context μέσω pipe_buf_operations->release flow; αποφύγετε userspace derefs μέχρι μετά την αλυσίδα disable/prepare_kernel_cred/commit_creds.
- Hardened usercopy: δεν εφαρμόζεται στο συγκεκριμένο page overflow primitive; τα στοχευόμενα corruption πεδία είναι non-usercopy fields.
Αξιοπιστία
- Υψηλή μόλις επιτευχθεί adjacency; περιστασιακά misses ή panics (<10%). Η ρύθμιση των spray/free counts βελτιώνει τη σταθερότητα. Το overwrite των δύο LSBs ενός pointer για να προκληθούν συγκεκριμένες συγκρούσεις αναφέρθηκε ως αποτελεσματικό (π.χ., write 0x0000_0000_0000_0500 pattern στο overlap).
Κύριες παράμετροι για ρύθμιση
- Number of msg_msg sprays and hole pattern
- OOB offset (pos) and resulting OOB length (count’)
- Number of UNIX socket, sk_buff, and pipe_buffer sprays during each stage
Μέτρα αντιμετώπισης και προσβασιμότητα
- Fix: clamp both allocation and destination/length or bound memcpy against the allocated size; upstream patches track as CVE-2025-37947.
- Remote exploitation θα απαιτούσε επιπλέον ένα αξιόπιστο infoleak και remote heap grooming; αυτή η τεκμηρίωση εστιάζει στο local LPE.
Αναφορές PoC και εργαλεία
- libsmb2 for SMB auth and streams writes
- eBPF tracer script to log kvmalloc addresses and histogram allocations (e.g., grep 4048 out-4096.txt)
- Minimal reachability PoC and full local exploit are publicly available (see References)
Αναφορές
- ksmbd - Exploiting CVE-2025-37947 (3/3) — Doyensec
- libsmb2
- KSMBD-CVE-2025-37947: proof-of-concept.c
- KSMBD-CVE-2025-37947: CVE-2025-37947.c (full exploit)
- bpf-tracer.sh
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks

