ksmbd Angriffsfläche & SMB2/SMB3 Protokoll Fuzzing (syzkaller)
Reading time: 8 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Übersicht
Diese Seite fasst praktische Techniken zusammen, um den Linux In‑Kernel SMB‑Server (ksmbd) mit syzkaller auszuüben und zu fuzzing. Der Fokus liegt auf der Erweiterung der Protokoll-Angriffsfläche durch Konfiguration, dem Aufbau eines zustandsbehafteten Harness, das SMB2‑Operationen ketten kann, der Erzeugung grammatik‑gültiger PDUs, dem Biasing von Mutationen in schlecht abgedeckte Codepfade und der Nutzung von syzkaller‑Features wie focus_areas und ANYBLOB. Während die ursprüngliche Forschung spezifische CVEs aufzählt, betonen wir hier die wiederverwendbare Methodik und konkrete Snippets, die Sie an Ihre Setups anpassen können.
Zielbereich: SMB2/SMB3 über TCP. Kerberos und RDMA sind bewusst ausgeklammert, um das Harness einfach zu halten.
Erweitern der ksmbd‑Angriffsfläche durch Konfiguration
Eine minimale ksmbd‑Konfiguration lässt standardmäßig große Teile des Servers ungetestet. Aktivieren Sie die folgenden Features, um den Server durch zusätzliche Parser/Handler zu treiben und tiefere Codepfade zu erreichen:
- Global-level
- Durable handles
- Server multi-channel
- SMB2 leases
- Per-share-level
- Oplocks (on by default)
- VFS objects
Das Aktivieren dieser Features erhöht die Ausführung in Modulen wie:
- 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)
Hinweise
- Exakte Optionen hängen von Ihrer Distro‑spezifischen ksmbd Userspace (ksmbd-tools) ab. Überprüfen Sie /etc/ksmbd/ksmbd.conf und die Per‑Share‑Sektionen, um durable handles, leases, oplocks und VFS objects zu aktivieren.
- Multi‑channel und durable handles verändern State‑Machines und Lifetimes und führen unter Concurrency oft zu UAF/refcount/OOB Fehlern.
Authentifizierungs‑ und Rate‑Limiting‑Anpassungen für Fuzzing
SMB3 benötigt eine gültige Session. Die Implementierung von Kerberos im Harness erhöht die Komplexität, daher ist NTLM/guest für Fuzzing vorzuziehen:
- Allow guest access und setzen Sie map to guest = bad user, sodass unbekannte Benutzer auf GUEST zurückfallen.
- Accept NTLMv2 (patchen Sie die Policy, falls deaktiviert). Das hält den Handshake einfach und treibt gleichzeitig SMB3‑Codepfade.
- Patchen Sie strikte credit checks während des Experimentierens (post‑Hardening für CVE-2024-50285 hat simultaneous‑op Crediting verschärft). Andernfalls können Rate‑Limits fuzzed Sequenzen zu früh ablehnen.
- Erhöhen Sie max connections (z. B. auf 65536), um frühe Ablehnungen bei hohem Durchsatz zu vermeiden.
Vorsicht: Diese Lockerungen dienen ausschließlich dem Fuzzing. Setzen Sie diese Einstellungen nicht in Produktion ein.
Stateful Harness: Ressourcen extrahieren und Requests ketten
SMB ist zustandsbehaftet: Viele Requests hängen von Identifiers ab, die in vorherigen Antworten zurückgegeben werden (SessionId, TreeID, FileID Paare). Ihr Harness muss Antworten parsen und IDs innerhalb desselben Programms wiederverwenden, um tiefe Handler zu erreichen (z. B. smb2_create → smb2_ioctl → smb2_close).
Beispiel‑Snippet, um einen Response‑Buffer zu verarbeiten (wobei die +4B NetBIOS PDU length übersprungen werden) und IDs zu cachen:
// 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;
}
}
Tipps
- Behalte einen einzelnen fuzzer-Prozess, der Authentifizierung/Zustand teilt: bessere Stabilität und Coverage mit ksmbd’s global/session tables. syzkaller injiziert dennoch Concurrency, indem es ops als async markiert und intern neu ausführt.
- Syzkaller’s experimentelles reset_acc_state kann den globalen Zustand zurücksetzen, bringt aber möglicherweise starke Verlangsamung. Bevorzuge Stabilität und konzentriere dich stattdessen auf fuzzing.
Grammatikgesteuerte SMB2-Generierung (gültige PDUs)
Übersetze die SMB2-Strukturen aus den Microsoft Open Specifications in eine fuzzer-Grammatik, damit dein Generator strukturell gültige PDUs erzeugt, die systematisch Dispatcher und IOCTL-Handler erreichen.
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]
Dieser Stil erzwingt korrekte Strukturgrößen/Offsets und verbessert die Abdeckung gegenüber blindem Mutieren dramatisch.
Gezieltes Fuzzing mit focus_areas
Verwenden Sie syzkaller’s experimentelle focus_areas, um bestimmte Funktionen/Dateien zu übergewichten, die derzeit eine schwache Abdeckung aufweisen. Beispiel-JSON:
{
"focus_areas": [
{"filter": {"functions": ["smb_check_perm_dacl"]}, "weight": 20.0},
{"filter": {"files": ["^fs/smb/server/"]}, "weight": 2.0},
{"weight": 1.0}
]
}
Das hilft, gültige ACLs zu konstruieren, die die arithmetische/overflow-Pfade in smbacl.c auslösen. Zum Beispiel reproduziert ein bösartiger Security Descriptor mit einem übergroßen dacloffset einen 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)
Durchbrechen von Coverage-Plateaus mit ANYBLOB
syzkaller’s anyTypes (ANYBLOB/ANYRES) ermöglichen es, komplexe Strukturen in blobs zu bündeln, die sich generisch mutieren. Lege ein neues Corpus aus öffentlichen SMB pcaps an und konvertiere Payloads in syzkaller-Programme, die deinen Pseudo-Syscall aufrufen (z. B. 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)"
)
Das beschleunigt die Exploration und kann sofort UAFs auslösen (z. B. in ksmbd_sessions_deregister) und gleichzeitig die Abdeckung um einige Prozentpunkte erhöhen.
Sanitizer: Über KASAN hinaus
- KASAN bleibt der primäre Detektor für Heap-Bugs (UAF/OOB).
- KCSAN liefert in diesem Ziel häufig Fehlalarme oder Daten-Races mit geringer Schwere.
- UBSAN/KUBSAN können deklarierte Grenzfehler erfassen, die KASAN aufgrund der Semantik von Array-Indizes übersieht. Beispiel:
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));
Das Setzen von num_subauth = 0 löst einen In-Struct-OOB-Lesezugriff auf sub_auth[-1] aus, der von UBSANs declared-bounds-Prüfungen erfasst wird.
Hinweise zu Durchsatz und Parallelität
- Ein einzelner fuzzer-Prozess (shared auth/state) ist für ksmbd in der Regel deutlich stabiler und bringt dank syzkaller’s internem async executor weiterhin races/UAFs zutage.
- Mit mehreren VMs erreicht man insgesamt immer noch hunderte SMB-Befehle/Sekunde. Eine Funktionsabdeckung von ~60% für fs/smb/server und ~70% für smb2pdu.c ist erreichbar, wobei die Coverage von Zustandsübergängen durch solche Metriken unterrepräsentiert ist.
Praktische Checkliste
- Aktiviere durable handles, leases, multi-channel, oplocks und VFS-Objekte in ksmbd.
- Erlaube guest und map-to-guest; akzeptiere NTLMv2. Entferne die credit limits und erhöhe die max connections für die Stabilität des fuzzers.
- Baue ein stateful harness, das SessionId/TreeID/FileIDs cached und create → ioctl → close verkettet.
- Verwende eine grammar für SMB2 PDUs, um strukturelle Gültigkeit zu gewährleisten.
- Nutze focus_areas, um schwach abgedeckte Funktionen zu übergewichten (z. B. smbacl.c-Pfade wie smb_check_perm_dacl).
- Seed mit ANYBLOB aus realen pcaps, um Plateaus zu durchbrechen; packe Seeds mit syz-db zur Wiederverwendung.
- Starte mit KASAN + UBSAN; triage UBSAN declared-bounds-Berichte sorgfältig.
Referenzen
- 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
- Weiterführende Lektüre: pwning.tech “Tickling ksmbd: fuzzing SMB in the Linux kernel”; Dongliang Mu’s syzkaller notes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.