ksmbd Površina napada i fuzzing SMB2/SMB3 protokola (syzkaller)

Reading time: 8 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Pregled

Ova stranica apstrahuje praktične tehnike za vežbanje i fuzzing Linux in-kernel SMB servera (ksmbd) koristeći syzkaller. Fokus je na proširenju attack surface protokola kroz konfiguraciju, izgradnji stateful harness-a sposobnog da lančano izvodi SMB2 operacije, generisanju PDUs validnih prema gramatici, usmeravanju mutacija ka slabo pokrivenim kodnim putevima i iskorišćavanju syzkaller funkcija kao što su focus_areas i ANYBLOB. Dok originalno istraživanje navodi specifične CVE-ove, ovde naglašavamo ponovljivo metodološko pristupanje i konkretne snippete koje možete prilagoditi sopstvenim setup-ovima.

Ciljni obuhvat: SMB2/SMB3 preko TCP-a. Kerberos i RDMA su namerno van obuhvata da bi harness ostao jednostavan.


Proširenje ksmbd površine napada kroz konfiguraciju

Po defaultu, minimalan ksmbd setup ostavlja velike delove servera netestiranim. Omogućite sledeće funkcije da biste naterali server kroz dodatne parsere/handlere i dohvatili dublje kodne puteve:

  • Global-level
  • Durable handles
  • Server multi-channel
  • SMB2 leases
  • Per-share-level
  • Oplocks (uključen po defaultu)
  • VFS objects

Omogućavanje ovih opcija povećava izvršavanje u modulima kao što su:

  • smb2pdu.c (command parsing/dispatch)
  • ndr.c (NDR encode/decode)
  • oplock.c (oplock request/break)
  • smbacl.c (ACL parsing/enforcement)
  • vfs.c (VFS ops)
  • vfs_cache.c (lookup cache)

Napomene

  • Tačne opcije zavise od vašeg distro-ovog ksmbd userspace-a (ksmbd-tools). Pregledajte /etc/ksmbd/ksmbd.conf i per-share sekcije da omogućite durable handles, leases, oplocks i VFS objects.
  • Multi-channel i durable handles menjaju state machine i lifetime, često eksponirajući UAF/refcount/OOB bagove pod konkurentnošću.

Podešavanja autentifikacije i rate-limiting za fuzzing

SMB3 zahteva validnu sesiju. Implementacija Kerberos-a u harness-evima dodaje kompleksnost, pa se za fuzzing radije koristi NTLM/guest:

  • Dozvolite guest pristup i podesite map to guest = bad user tako da nepoznati korisnici padaju na GUEST.
  • Prihvatite NTLMv2 (patch-ujte politiku ako je onemogućen). Ovo pojednostavljuje handshake dok i dalje aktivira SMB3 kodne puteve.
  • Patch-ujte stroge credit checks tokom eksperimentisanja (post-hardening za CVE-2024-50285 je strožije regulisao simultaneous-op crediting). Inače, rate-limiti mogu odbacivati fuzzovane sekvence prerano.
  • Povećajte max connections (npr. na 65536) da izbegnete rane odbacivanja pri visokoprotočnom fuzzingu.

Upozorenje: Ova opuštanja služe isključivo za potrebe fuzzinga. Ne deploy-ujte sa ovim podešavanjima u produkciji.


Stateful harness: Ekstrakcija resursa i lančanje zahteva

SMB je stateful: mnogi zahtevi zavise od identifikatora vraćenih prethodnim odgovorima (SessionId, TreeID, FileID parovi). Vaš harness mora parsirati odgovore i ponovo koristiti ID-ove unutar istog programa da bi dosegao dublje handlere (npr. smb2_create → smb2_ioctl → smb2_close).

Primer snippeta za obradu response buffera (preskačući +4B NetBIOS PDU length) i keširanje ID-ova:

c
// process response. does not contain +4B PDU length
void process_buffer(int msg_no, const char *buffer, size_t received) {
uint16_t cmd_rsp = u16((const uint8_t *)(buffer + CMD_OFFSET));
switch (cmd_rsp) {
case SMB2_TREE_CONNECT:
if (received >= TREE_ID_OFFSET + sizeof(uint32_t))
tree_id = u32((const uint8_t *)(buffer + TREE_ID_OFFSET));
break;
case SMB2_SESS_SETUP:
// first session setup response carries session_id
if (msg_no == 0x01 && received >= SESSION_ID_OFFSET + sizeof(uint64_t))
session_id = u64((const uint8_t *)(buffer + SESSION_ID_OFFSET));
break;
case SMB2_CREATE:
if (received >= CREATE_VFID_OFFSET + sizeof(uint64_t)) {
persistent_file_id = u64((const uint8_t *)(buffer + CREATE_PFID_OFFSET));
volatile_file_id   = u64((const uint8_t *)(buffer + CREATE_VFID_OFFSET));
}
break;
default:
break;
}
}

Saveti

  • Zadržite jedan fuzzer process koji deli authentication/state: pruža bolju stabilnost i pokrivenost sa ksmbd’s global/session tables. syzkaller i dalje uvodi concurrency tako što označava ops kao async i interno ih ponovo pokreće.
  • Syzkaller’s experimental reset_acc_state može resetovati global state, ali može uvesti značajno usporenje. Prioritet dajte stabilnosti i fokusirajte se na fuzzing umesto toga.

Generisanje SMB2 vođeno gramatikom (validni PDUs)

Prevedite Microsoft Open Specifications SMB2 strukture u fuzzer grammar tako da vaš generator proizvodi strukturno validne PDUs koje sistematski dopiru do dispatchers i IOCTL handlers.

Primer (SMB2 IOCTL request):

smb2_ioctl_req {
Header_Prefix           SMB2Header_Prefix
Command                 const[0xb, int16]
Header_Suffix           SMB2Header_Suffix
StructureSize           const[57, int16]
Reserved                const[0, int16]
CtlCode                 union_control_codes
PersistentFileId        const[0x4, int64]
VolatileFileId          const[0x0, int64]
InputOffset             offsetof[Input, int32]
InputCount              bytesize[Input, int32]
MaxInputResponse        const[65536, int32]
OutputOffset            offsetof[Output, int32]
OutputCount             len[Output, int32]
MaxOutputResponse       const[65536, int32]
Flags                   int32[0:1]
Reserved2               const[0, int32]
Input                   array[int8]
Output                  array[int8]
} [packed]

Ovaj stil prisiljava na ispravne structure sizes/offsets i drastično poboljšava coverage u odnosu na blind mutation.


Directed Fuzzing With focus_areas

Koristite syzkaller’s experimental focus_areas da date veću težinu određenim functions/files koje trenutno imaju slab coverage. Example JSON:

json
{
"focus_areas": [
{"filter": {"functions": ["smb_check_perm_dacl"]}, "weight": 20.0},
{"filter": {"files": ["^fs/smb/server/"]}, "weight": 2.0},
{"weight": 1.0}
]
}

Ovo pomaže da se konstruišu validni ACLs koji pogađaju arithmetic/overflow puteve u smbacl.c. Na primer, zlonamerni Security Descriptor sa prevelikim dacloffset reprodukuje integer-overflow.

Generator reprodukcije (minimalni Python):

python
def build_sd():
import struct
sd = bytearray(0x14)
sd[0x00] = 0x00; sd[0x01] = 0x00
struct.pack_into('<H', sd, 0x02, 0x0001)
struct.pack_into('<I', sd, 0x04, 0x78)
struct.pack_into('<I', sd, 0x08, 0x00)
struct.pack_into('<I', sd, 0x0C, 0x10000)
struct.pack_into('<I', sd, 0x10, 0xFFFFFFFF)  # dacloffset
while len(sd) < 0x78:
sd += b'A'
sd += b"\x01\x01\x00\x00\x00\x00\x00\x00"  # minimal DACL
sd += b"\xCC" * 64
return bytes(sd)

Prevazilaženje platoa pokrivenosti uz ANYBLOB

syzkaller’s anyTypes (ANYBLOB/ANYRES) omogućavaju sabijanje složenih struktura u blobs koji se generički mutiraju. Napunite novi korpus iz javnih SMB pcaps i konvertujte payloads u syzkaller programe koji pozivaju vaš pseudo-syscall (npr. syz_ksmbd_send_req):

bash
# Extract SMB payloads to JSON
# tshark -r smb2_dac_sample.pcap -Y "smb || smb2" -T json -e tcp.payload > packets.json
python
import json, os
os.makedirs("corpus", exist_ok=True)

with open("packets.json") as f:
data = json.load(f)
# adjust indexing to your tshark JSON structure
packets = [e["_source"]["layers"]["tcp.payload"] for e in data]

for i, pkt in enumerate(packets):
pdu = pkt[0]
pdu_size = len(pdu) // 2  # hex string length → bytes
with open(f"corpus/packet_{i:03d}.txt", "w") as f:
f.write(
f"syz_ksmbd_send_req(&(&(0x7f0000000340))=ANY=[@ANYBLOB=\"{pdu}\"], {hex(pdu_size)}, 0x0, 0x0)"
)

Ovo ubrzava istraživanje i može odmah izazvati UAFs (npr. u ksmbd_sessions_deregister) dok podiže coverage za nekoliko procenata.


Sanitizers: Više od KASAN

  • KASAN ostaje primarni detektor za heap bugs (UAF/OOB).
  • KCSAN često daje false positives ili low-severity data races na ovom targetu.
  • UBSAN/KUBSAN može uhvatiti declared-bounds greške koje KASAN promaši zbog array-index semantics. Primer:
c
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
struct smb_sid {
__u8 revision; __u8 num_subauth; __u8 authority[NUM_AUTHS];
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
} __attribute__((packed));

Postavljanje num_subauth = 0 izaziva in-struct OOB čitanje sub_auth[-1], koje detektuju UBSAN-ove provere deklarisanih granica.


Napomene o propusnosti i paralelizmu

  • Jedan fuzzer proces (shared auth/state) obično je znatno stabilniji za ksmbd i i dalje otkriva races/UAFs zahvaljujući syzkaller’s internal async executor.
  • Sa višestrukim VM-ovima, i dalje možete dostići stotine SMB komandi/sekundi ukupno. Pokrivenost na nivou funkcija oko ~60% za fs/smb/server i ~70% za smb2pdu.c je ostvariva, mada je pokrivenost prelaza stanja potcenjena ovakvim metrikama.

Praktični kontrolni spisak

  • Omogućite durable handles, leases, multi-channel, oplocks i VFS objects u ksmbd.
  • Allow guest i map-to-guest; accept NTLMv2. Patch out credit limits i povećajte max connections radi stabilnosti fuzzera.
  • Napravite stateful harness koji kešira SessionId/TreeID/FileIDs i povezuje create → ioctl → close.
  • Koristite grammar za SMB2 PDUs da održite strukturnu validnost.
  • Koristite focus_areas da preterano opteretite slabo pokrivene funkcije (npr. smbacl.c putanje kao smb_check_perm_dacl).
  • Seedujte sa ANYBLOB iz stvarnih pcaps da probijete platea; pakujte seed-ove sa syz-db za ponovnu upotrebu.
  • Pokrenite sa KASAN + UBSAN; pažljivo razvrstajte UBSAN izveštaje o declared-bounds.

Reference

  • Doyensec – ksmbd Fuzzing (Part 2): https://blog.doyensec.com/2025/09/02/ksmbd-2.html
  • syzkaller: https://github.com/google/syzkaller
  • ANYBLOB/anyTypes (commit 9fe8aa4): https://github.com/google/syzkaller/commit/9fe8aa4
  • Async executor change (commit fd8caa5): https://github.com/google/syzkaller/commit/fd8caa5
  • syz-db: https://github.com/google/syzkaller/tree/master/tools/syz-db
  • KASAN: https://docs.kernel.org/dev-tools/kasan.html
  • UBSAN/KUBSAN: https://docs.kernel.org/dev-tools/ubsan.html
  • KCSAN: https://docs.kernel.org/dev-tools/kcsan.html
  • Microsoft Open Specifications (SMB): https://learn.microsoft.com/openspecs/
  • Wireshark Sample Captures: https://wiki.wireshark.org/SampleCaptures
  • Background reading: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; Dongliang Mu’s syzkaller notes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks