# ksmbd Attack Surface & SMB2/SMB3 Protocol Fuzzing (syzkaller) {{#include ../../banners/hacktricks-training.md}} ## Pregled Ova stranica sažima praktične tehnike za vežbanje i fuzzing Linux in-kernel SMB servera (ksmbd) koristeći syzkaller. Fokusira se na proširenje attack surface-a protokola kroz konfiguraciju, izgradnju stateful harness-a sposobnog da poveže SMB2 operacije, generisanje grammar-valid PDUs, usmeravanje mutacija ka slabo pokrivenim kodnim putevima i korišćenje syzkaller funkcija kao što su focus_areas i ANYBLOB. Dok originalno istraživanje nabraja specifične CVE-e, ovde naglašavamo ponovljivo metodološko pristupanje i konkretne isječke koje možete prilagoditi sopstvenim okruženjima. Target scope: SMB2/SMB3 over TCP. Kerberos i RDMA su namerno van opsega da bi harness ostao jednostavan. --- ## Proširite ksmbd Attack Surface putem konfiguracije Po defaultu, minimalna ksmbd konfiguracija ostavlja veliki deo servera netestiranim. Omogućite sledeće funkcije da biste naveli server da prolazi kroz dodatne parsere/handlere i doseže dublje kodne puteve: - Global-level - Durable handles - Server multi-channel - SMB2 leases - Per-share-level - Oplocks (on by default) - 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 ksmbd userspace-a vaše distro-e (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-e i lifetim-e, često izlažući UAF/refcount/OOB bugove pod konkurentnošću. --- ## Podešavanja autentikacije i rate-limiting za fuzzing SMB3 zahteva validnu sesiju. Implementacija Kerberos-a u harness-evima dodaje kompleksnost, pa za fuzzing preferirajte NTLM/guest: - Allow guest access i set map to guest = bad user tako da nepoznati korisnici padaju na GUEST. - Accept NTLMv2 (patch policy ako je disabled). Ovo održava handshake jednostavnim dok se i dalje vežbaju SMB3 kodni putevi. - Patch-ujte stroge kredit-provere dok eksperimentišete (post-hardening za CVE-2024-50285 je učinio simultaneous-op crediting strožijim). U suprotnom, rate-limiti mogu odbiti fuzzovane sekvence prerano. - Povećajte max connections (npr. na 65536) da izbegnete rane odbijanja tokom visokopropusnog fuzzinga. Upozorenje: Ova relaksiranja su isključivo radi olakšavanja fuzzinga. Ne koristite ovakva podešavanja u produkciji. --- ## Stateful Harness: Ekstrahovanje resursa i povezivanje zahteva SMB je stateful: mnogi zahtevi zavise od identifikatora vraćenih u prethodnim odgovorima (SessionId, TreeID, FileID parovi). Vaš harness mora parsirati odgovore i ponovo koristiti ID-e unutar istog programa da bi dostigao dublje handlere (npr. smb2_create → smb2_ioctl → smb2_close). Primer isječka za obradu response buffer-a (preskačući +4B NetBIOS PDU length) i keširanje ID-eva: ```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 - Koristite jedan fuzzer proces koji deli authentication/state: bolja stabilnost i pokrivenost sa ksmbd’s global/session tables. syzkaller i dalje ubrizgava konkurentnost označavanjem ops kao async, interno ponovo izvršava. - Syzkaller’s experimental reset_acc_state može resetovati global state ali može uvesti značajno usporenje. Preferirajte stabilnost i fokusirajte se na fuzzing umesto toga. --- ## Generisanje SMB2 vođeno gramatikom (ispravni PDU-i) Prevedite Microsoft Open Specifications SMB2 strukture u fuzzer gramatiku tako da vaš generator proizvodi strukturalno ispravne PDU-e, koji sistematski stižu 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 osigurava ispravne veličine/offsete struktura i dramatično poboljšava coverage u odnosu na blind mutation. --- ## Directed Fuzzing pomoću focus_areas Koristite syzkaller’s eksperimentalni focus_areas da date veću težinu specifičnim funkcijama/datotekama koje trenutno imaju slabu coverage. Primer 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 u konstruisanju validnih ACL-ova koji pogode aritmetičke/overflow putanje u smbacl.c. Na primer, maliciozan Security Descriptor sa prevelikim dacloffset reprodukuje integer-overflow. Reproducer builder (minimal Python): ```python def build_sd(): import struct sd = bytearray(0x14) sd[0x00] = 0x00; sd[0x01] = 0x00 struct.pack_into(' 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 početno istraživanje i može odmah da izazove UAFs (npr. u ksmbd_sessions_deregister), istovremeno povećavajući pokrivenost za nekoliko procenata. --- ## Sanitizers: Iza KASAN - KASAN ostaje primarni detektor za heap bugs (UAF/OOB). - KCSAN često daje false positives ili data races niske ozbiljnosti u ovom targetu. - UBSAN/KUBSAN može otkriti declared-bounds greške koje KASAN propušta zbog semantike array-index-a. Example: ```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 pokreće in-struct OOB čitanje sub_auth[-1], koje je otkriveno UBSAN-ovim proverama deklarisanih granica. --- ## Napomene o propusnosti i paralelizmu - Jedan fuzzer proces (shared auth/state) obično je značajno stabilniji za ksmbd i i dalje izbacuje races/UAFs zahvaljujući syzkaller-ovom internal async executor-u. - Sa više VM-ova i dalje možete pogoditi stotine SMB komandi/sekundi ukupno. Pokrivenost na nivou funkcija od oko ~60% za fs/smb/server i ~70% za smb2pdu.c je ostvariva, mada pokrivenost prelaza stanja nije adekvatno predstavljena takvim metrima. --- ## Praktična kontrolna lista - Omogućite durable handles, leases, multi-channel, oplocks i VFS objects u ksmbd. - Dozvolite guest i map-to-guest; prihvatite NTLMv2. Patch-ujte credit limits i povećajte max connections radi stabilnosti fuzzer-a. - 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 dodatno ponderišete slabo pokrivene funkcije (npr. smbacl.c putanje poput smb_check_perm_dacl). - Seed-ujte sa ANYBLOB iz realnih pcaps da probijete plateaus; pakujte seed-ove sa syz-db za ponovnu upotrebu. - Pokrenite sa KASAN + UBSAN; pažljivo triage-ujte UBSAN declared-bounds izveštaje. --- ## 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 {{#include ../../banners/hacktricks-training.md}}