Skip to content

Commit 21f4ebf

Browse files
authored
Merge pull request #2127 from HackTricks-wiki/research_update_src_binary-exploitation_linux-kernel-exploitation_ksmbd-streams_xattr-oob-write-cve-2025-37947_20260414_032056
Research Update Enhanced src/binary-exploitation/linux-kerne...
2 parents a3055b7 + dac7024 commit 21f4ebf

1 file changed

Lines changed: 20 additions & 4 deletions

File tree

src/binary-exploitation/linux-kernel-exploitation/ksmbd-streams_xattr-oob-write-cve-2025-37947.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ Example smb.conf
1919

2020
Root cause (allocation clamped, memcpy at unclamped offset)
2121
- The function computes size = *pos + count, clamps size to XATTR_SIZE_MAX (0x10000) when exceeded, and recomputes count = (*pos + count) - 0x10000, but still performs memcpy(&stream_buf[*pos], buf, count) into a 0x10000-byte buffer. If *pos ≥ 0x10000 the destination pointer is already outside the allocation, producing an OOB write of count bytes.
22+
- `streams_xattr` stores SMB alternate data streams inside POSIX extended attributes, so the 0x10000 ceiling comes from the Linux single-xattr size limit rather than from an SMB protocol field. That makes the bug practical only when the share explicitly enables `vfs objects = streams_xattr` and the filesystem supports xattrs.
23+
24+
Why the write offset matters
25+
- The vulnerable path is not just "write more than 64KiB". The missing check was that `*pos` was not validated against the current stream length (`v_len`) before the append/copy logic ran.
26+
- Upstream fixed this by rejecting writes where `*pos >= v_len` with `-EINVAL`. Pre-fix, an attacker could reuse a valid authenticated handle to a named stream and send a raw SMB2 WRITE whose `file_offset` already points at or past the end of the existing stream, which turns the post-clamp `memcpy()` into a deterministic page overflow.
27+
- The public PoC demonstrates this by authenticating with `libsmb2`, opening a stream path such as `1337:`, extracting `SessionId`/`TreeId`/`FileId`, and then sending a handcrafted SMB2 WRITE with `file_offset = 0x10018` and a small `Length`.
2228

2329
<details>
2430
<summary>Vulnerable function snippet (ksmbd_vfs_stream_write)</summary>
@@ -52,6 +58,7 @@ Offset steering and OOB length
5258
Triggering the bug via SMB streams write
5359
- Use the same authenticated SMB connection to open a file on the share and issue a write to a named stream (streams_xattr). Set file_offset ≥ 0x10000 with a small length to generate a deterministic OOB write of controllable size.
5460
- libsmb2 can be used to authenticate and craft such writes over SMB2/3.
61+
- In practice, reusing the negotiated SMB session is convenient because the exploit only needs to patch a few dynamic fields in the WRITE request (`TreeId`, `SessionId`, `FileId`) and can then transmit the malformed packet directly on the same socket.
5562
5663
Minimal reachability (concept)
5764
```c
@@ -79,6 +86,11 @@ sudo cat /proc/pagetypeinfo | sed -n '/Node 0, zone Normal/,/Node/p'
7986
sudo ./bpf-tracer.sh
8087
```
8188

89+
What to trace while tuning
90+
- `kvmalloc_node(0x10000)` confirms when the vulnerable stream write actually consumes an order-4 allocation.
91+
- `load_msg`/`kretprobe:load_msg` lets you estimate how many `msg_msgseg` allocations are attached to each sprayed message, which is useful when tuning primary/secondary message sizes for a specific kernel build.
92+
- If the exploit is ported to a different distro/kernel, re-check cache names, inline `msg_msg` payload sizes, `anon_pipe_buf_ops` offsets, and gadget addresses rather than assuming the Ubuntu 22.04 LTS `5.15.0-153-generic` constants still match.
93+
8294
Exploitation plan (msg_msg + pipe_buffer), adapted from CVE-2021-22555
8395
1) Spray many System V msg_msg primary/secondary messages (4KiB-sized to fit kmalloc-cg-4k).
8496
2) Trigger ksmbd OOB to corrupt a primary message’s next pointer so that two primaries share one secondary.
@@ -106,16 +118,20 @@ Mitigations and reachability
106118
- Fix: clamp both allocation and destination/length or bound memcpy against the allocated size; upstream patches track as CVE-2025-37947.
107119
- Remote exploitation would additionally require a reliable infoleak and remote heap grooming; this write-up focuses on local LPE.
108120

121+
See also
122+
123+
{{#ref}}
124+
../../network-services-pentesting/pentesting-smb/ksmbd-attack-surface-and-fuzzing-syzkaller.md
125+
{{#endref}}
126+
109127
References PoC and tooling
110128
- libsmb2 for SMB auth and streams writes
111129
- eBPF tracer script to log kvmalloc addresses and histogram allocations (e.g., grep 4048 out-4096.txt)
112130
- Minimal reachability PoC and full local exploit are publicly available (see References)
113131

114132
## References
115133
- [ksmbd - Exploiting CVE-2025-37947 (3/3) — Doyensec](https://blog.doyensec.com/2025/10/08/ksmbd-3.html)
116-
- [libsmb2](https://github.com/sahlberg/libsmb2)
117-
- [KSMBD-CVE-2025-37947: proof-of-concept.c](https://github.com/doyensec/KSMBD-CVE-2025-37947/blob/main/proof-of-concept.c)
118-
- [KSMBD-CVE-2025-37947: CVE-2025-37947.c (full exploit)](https://github.com/doyensec/KSMBD-CVE-2025-37947/blob/main/CVE-2025-37947.c)
119-
- [bpf-tracer.sh](https://github.com/doyensec/KSMBD-CVE-2025-37947/blob/main/bpf-tracer.sh)
134+
- [Linux upstream fix: `ksmbd: prevent out-of-bounds stream writes by validating *pos`](https://github.com/torvalds/linux/commit/0ca6df4f40cf4c32487944aaf48319cb6c25accc)
135+
- [KSMBD-CVE-2025-37947 PoC repository](https://github.com/doyensec/KSMBD-CVE-2025-37947)
120136

121137
{{#include ../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)