ksmbd Powierzchnia ataku & SMB2/SMB3 Protocol Fuzzing (syzkaller)
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Overview
Ta strona podsumowuje praktyczne techniki pozwalające ćwiczyć i fuzzować Linux in-kernel SMB server (ksmbd) przy użyciu syzkaller. Skupia się na rozszerzaniu powierzchni ataku protokołu poprzez konfigurację, budowaniu stanowego harnessu zdolnego do łączenia operacji SMB2, generowaniu grammar-valid PDUs, ukierunkowywaniu mutacji w słabo pokryte ścieżki kodu oraz wykorzystaniu funkcji syzkaller takich jak focus_areas i ANYBLOB. Podczas gdy oryginalne badania wymieniały konkretne CVE, tutaj kładziemy nacisk na powtarzalną metodologię i konkretne fragmenty, które możesz zaadaptować do własnych środowisk.
Zakres docelowy: SMB2/SMB3 over TCP. Kerberos i RDMA zostały celowo wyłączone z zakresu, aby utrzymać harness prostym.
Expand ksmbd Attack Surface via Configuration
Domyślna, minimalna konfiguracja ksmbd pozostawia dużą część serwera nieprzetestowaną. Włącz następujące funkcje, aby przetestować dodatkowe parsery/handlery i dotrzeć do głębszych ścieżek kodu:
- Global-level
- Durable handles
- Server multi-channel
- SMB2 leases
- Per-share-level
- Oplocks (on by default)
- VFS objects
Włączenie tych opcji zwiększa wykonanie w modułach takich jak:
- 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)
Uwagi
- Dokładne opcje zależą od userspace ksmbd w Twojej dystrybucji (ksmbd-tools). Przejrzyj /etc/ksmbd/ksmbd.conf oraz sekcje per-share, aby włączyć durable handles, leases, oplocks i VFS objects.
- Multi-channel i durable handles zmieniają automaty stanu i czasy życia obiektów, często ujawniając UAF/refcount/OOB bugs pod obciążeniem współbieżnym.
Authentication and Rate-Limiting Adjustments for Fuzzing
SMB3 wymaga ważnej sesji. Implementacja Kerberos w harnessach dodaje złożoności, więc preferuj NTLM/guest do fuzzingu:
- Zezwól na guest access i ustaw map to guest = bad user, aby nieznani użytkownicy spadali do GUEST.
- Akceptuj NTLMv2 (zmodyfikuj politykę jeśli jest wyłączone). Utrzymuje to prostotę handshake’u przy jednoczesnym ćwiczeniu ścieżek kodu SMB3.
- Wyczyść/obejdź rygorystyczne checks na kredyty (post-hardening dla CVE-2024-50285 zaostrzył simultaneous-op crediting). W przeciwnym razie rate-limity mogą odrzucić fuzzowane sekwencje zbyt wcześnie.
- Zwiększ max connections (np. do 65536), aby uniknąć wczesnych odrzuceń podczas fuzzingu o wysokiej przepustowości.
Ostrzeżenie: Te poluzowania służą wyłącznie ułatwieniu fuzzingu. Nie stosuj tych ustawień w środowisku produkcyjnym.
Stateful Harness: Extract Resources and Chain Requests
SMB jest stanowy: wiele żądań zależy od identyfikatorów zwracanych przez wcześniejsze odpowiedzi (SessionId, TreeID, FileID pairs). Twój harness musi parsować odpowiedzi i ponownie używać ID w tym samym programie, aby dotrzeć do głębokich handlerów (np. 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;
}
}
Wskazówki
- Keep one fuzzer process sharing authentication/state: better stability and coverage with ksmbd’s global/session tables. syzkaller still injects concurrency by marking ops async, rerun internally.
- Syzkaller’s experimental reset_acc_state can reset global state but may introduce heavy slowdown. Prefer stability and focus fuzzing instead.
Generowanie SMB2 sterowane gramatyką (Prawidłowe PDUs)
Przekształć struktury SMB2 z Microsoft Open Specifications w fuzzer grammar, tak aby twój generator produkował strukturalnie prawidłowe PDUs, które systematycznie docierają do dispatcherów i IOCTL handlers.
Przykład (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]
Ten styl wymusza poprawne rozmiary/przesunięcia struktur i dramatycznie poprawia coverage w porównaniu z blind mutation.
Directed Fuzzing z focus_areas
Użyj eksperymentalnego focus_areas w syzkaller, aby przyznać większą wagę określonym funkcjom/plikom, które obecnie mają słaby coverage. Przykładowy JSON:
{
"focus_areas": [
{"filter": {"functions": ["smb_check_perm_dacl"]}, "weight": 20.0},
{"filter": {"files": ["^fs/smb/server/"]}, "weight": 2.0},
{"weight": 1.0}
]
}
To pomaga skonstruować poprawne ACLs, które wywołują ścieżki arithmetic/overflow w smbacl.c. Na przykład złośliwy Security Descriptor z nadmiernym dacloffset odtwarza integer-overflow.
Generator reproduktora (minimalny 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)
Przełamywanie stagnacji pokrycia za pomocą ANYBLOB
anyTypes syzkallera (ANYBLOB/ANYRES) pozwalają sprowadzić złożone struktury do blobów, które mutują generycznie. Utwórz nowy korpus z public SMB pcaps i skonwertuj payloady na programy syzkaller wywołujące twój pseudo-syscall (np. 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)"
)
To przyspiesza eksplorację i może natychmiast wywołać UAFs (np. w ksmbd_sessions_deregister), jednocześnie zwiększając pokrycie o kilka procent.
Sanitizery: Poza KASAN
- KASAN pozostaje głównym detektorem błędów sterty (UAF/OOB).
- KCSAN często generuje false positives lub data races o niskiej istotności dla tego celu.
- UBSAN/KUBSAN może wykryć błędy związane z deklarowanymi granicami, które KASAN pomija z powodu semantyki indeksów tablic. Przykład:
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));
Setting num_subauth = 0 triggers an in-struct OOB read of sub_auth[-1], caught by UBSAN’s declared-bounds checks.
Notatki o przepustowości i równoległości
- Pojedynczy proces fuzzer’a (wspólne auth/state) zwykle jest znacznie bardziej stabilny dla ksmbd i wciąż ujawnia race/UAF dzięki wewnętrznemu async executorowi syzkallera.
- Przy użyciu wielu VM można nadal osiągnąć setki SMB commands/sekund łącznie. Pokrycie na poziomie funkcji rzędu ~60% dla fs/smb/server i ~70% dla smb2pdu.c jest osiągalne, choć pokrycie przejść stanów jest słabo reprezentowane przez takie metryki.
Praktyczna lista kontrolna
- Włącz durable handles, leases, multi-channel, oplocks i VFS objects w ksmbd.
- Zezwól na guest i map-to-guest; akceptuj NTLMv2. Usuń ograniczenia credit i zwiększ max connections dla stabilności fuzzera.
- Zbuduj stateful harness, który cache’uje SessionId/TreeID/FileIDs i łańcuchuje create → ioctl → close.
- Użyj grammar dla SMB2 PDUs, żeby utrzymać poprawność strukturalną.
- Użyj focus_areas, aby przewagować słabiej pokryte funkcje (np. ścieżki w smbacl.c takie jak smb_check_perm_dacl).
- Seeduj ANYBLOB z prawdziwych pcaps, aby przełamać plateau; pakuj seedy za pomocą syz-db do ponownego użycia.
- Uruchamiaj z KASAN + UBSAN; triage raporty UBSAN declared-bounds ostrożnie.
Referencje
- 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
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
HackTricks

