Superficie d'attacco di ksmbd & Fuzzing del protocollo SMB2/SMB3 (syzkaller)
Reading time: 9 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Panoramica
Questa pagina astrarre tecniche pratiche per esercitare e fuzzare il Linux in-kernel SMB server (ksmbd) usando syzkaller. Si concentra sull'espansione della superficie d'attacco del protocollo tramite configurazione, sulla costruzione di un harness stateful capace di concatenare operazioni SMB2, sulla generazione di PDU valide rispetto alla grammatica, sull'orientamento delle mutazioni verso percorsi di codice poco coperti, e sull'uso di feature di syzkaller come focus_areas e ANYBLOB. Mentre la ricerca originale elenca CVE specifiche, qui enfatizziamo la metodologia riutilizzabile e snippet concreti che puoi adattare ai tuoi setup.
Ambito target: SMB2/SMB3 su TCP. Kerberos e RDMA sono intenzionalmente fuori-scope per mantenere l'harness semplice.
Espandere la superficie d'attacco di ksmbd tramite configurazione
Di default, una configurazione ksmbd minimale lascia grandi porzioni del server non testate. Abilita le seguenti feature per spingere il server attraverso parser/handler aggiuntivi e raggiungere percorsi di codice più profondi:
- Global-level
- Durable handles
- Server multi-channel
- SMB2 leases
- Per-share-level
- Oplocks (on by default)
- VFS objects
Abilitare queste opzioni aumenta l'esecuzione in moduli quali:
- 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)
Note
- Le opzioni esatte dipendono dall'userspace ksmbd della tua distro (ksmbd-tools). Controlla /etc/ksmbd/ksmbd.conf e le sezioni per-share per abilitare durable handles, leases, oplocks e VFS objects.
- Multi-channel e durable handles modificano state machine e lifetime, spesso facendo emergere UAF/refcount/OOB bug sotto concorrenza.
Authentication and Rate-Limiting Adjustments for Fuzzing
SMB3 richiede una sessione valida. Implementare Kerberos negli harness aggiunge complessità, quindi preferisci NTLM/guest per il fuzzing:
- Allow guest access e imposta map to guest = bad user in modo che utenti sconosciuti ricadano su GUEST.
- Accept NTLMv2 (patch policy se disabilitata). Questo mantiene l'handshake semplice mentre esercita i percorsi di codice di SMB3.
- Patchare i strict credit checks quando sperimenti (post-hardening per CVE-2024-50285 ha reso il crediting per operazioni simultanee più severo). Altrimenti, i rate-limit possono rifiutare sequenze fuzzate troppo presto.
- Aumentare max connections (per es., a 65536) per evitare rifiuti precoci durante il fuzzing ad alta velocità.
Attenzione: Queste rilassazioni sono solo per facilitare il fuzzing. Non usare queste impostazioni in produzione.
Stateful Harness: Extract Resources and Chain Requests
SMB è stateful: molte richieste dipendono da identificatori restituiti da risposte precedenti (SessionId, TreeID, coppie FileID). Il tuo harness deve parsare le risposte e riutilizzare gli ID nello stesso programma per raggiungere handler profondi (per es., smb2_create → smb2_ioctl → smb2_close).
Example snippet to process a response buffer (skipping the +4B NetBIOS PDU length) and cache IDs:
// 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;
}
}
Tips
- Mantieni un solo processo fuzzer che condivide autenticazione/stato: migliore stabilità e copertura con le tabelle globali/session di ksmbd. syzkaller comunque inietta concorrenza marcando le ops come async e rieseguendole internamente.
- La funzione sperimentale reset_acc_state di syzkaller può resettare lo stato globale ma può introdurre un forte rallentamento. Preferisci la stabilità e concentrati sul fuzzing.
Grammar-Driven SMB2 Generation (Valid PDUs)
Traduci le strutture SMB2 delle Microsoft Open Specifications in una grammatica per fuzzer in modo che il tuo generatore produca PDUs strutturalmente validi, che raggiungano sistematicamente dispatcher e IOCTL handler.
Example (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]
Questo stile impone dimensioni/offsets corretti delle strutture e migliora drasticamente la copertura rispetto alla blind mutation.
Directed Fuzzing With focus_areas
Usa le focus_areas sperimentali di syzkaller per sovrappesare funzioni/file specifici che attualmente hanno una copertura debole. Esempio JSON:
{
"focus_areas": [
{"filter": {"functions": ["smb_check_perm_dacl"]}, "weight": 20.0},
{"filter": {"files": ["^fs/smb/server/"]}, "weight": 2.0},
{"weight": 1.0}
]
}
Questo aiuta a costruire ACLs validi che colpiscono i percorsi arithmetic/overflow in smbacl.c. Per esempio, un Security Descriptor maligno con un dacloffset sovradimensionato riproduce un integer-overflow.
Reproducer builder (minimal 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)
Superare i plateau di Coverage con ANYBLOB
Gli anyTypes di syzkaller (ANYBLOB/ANYRES) permettono di ridurre strutture complesse a blob che mutano in modo generico. Popola un nuovo corpus da SMB pcaps pubblici e converti i payload in programmi syzkaller che chiamano il tuo pseudo-syscall (p.es., syz_ksmbd_send_req):
# Extract SMB payloads to JSON
# tshark -r smb2_dac_sample.pcap -Y "smb || smb2" -T json -e tcp.payload > packets.json
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)"
)
Questo accelera l'esplorazione e può immediatamente causare UAFs (p.es., in ksmbd_sessions_deregister) aumentando la copertura di qualche percento.
Sanitizers: Oltre KASAN
- KASAN rimane il rilevatore principale per heap bugs (UAF/OOB).
- KCSAN spesso genera falsi positivi o data races di bassa gravità su questo target.
- UBSAN/KUBSAN possono intercettare errori di declared-bounds che KASAN non rileva a causa della semantica degli indici di array. Esempio:
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));
Impostare num_subauth = 0 provoca una lettura in-struct OOB di sub_auth[-1], intercettata dai declared-bounds checks di UBSAN.
Note su throughput e parallelismo
- Un singolo processo fuzzer (auth/state condivisi) tende a essere significativamente più stabile per ksmbd e continua a far emergere races/UAF grazie all'executor async interno di syzkaller.
- Con più VM, si possono comunque raggiungere centinaia di comandi SMB/secondo complessivi. Una copertura a livello di funzione intorno al ~60% di fs/smb/server e ~70% di smb2pdu.c è ottenibile, sebbene la copertura delle transizioni di stato sia sottorappresentata da tali metriche.
Checklist pratica
- Abilitare durable handles, leases, multi-channel, oplocks e VFS objects in ksmbd.
- Consentire guest e map-to-guest; accettare NTLMv2. Rimuovere i credit limits e aumentare max connections per la stabilità del fuzzer.
- Costruire un harness stateful che memorizzi SessionId/TreeID/FileIDs e concateni create → ioctl → close.
- Usare una grammar per SMB2 PDUs per mantenere la validità strutturale.
- Usare focus_areas per sovrappesare funzioni poco coperte (es. percorsi in smbacl.c come smb_check_perm_dacl).
- Seminare con ANYBLOB da pcaps reali per rompere i plateau; confezionare gli seed con syz-db per il riuso.
- Eseguire con KASAN + UBSAN; triage attentamente i report UBSAN declared-bounds.
Riferimenti
- 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
- Letture di riferimento: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; Dongliang Mu’s syzkaller notes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.