ksmbd Attack Surface & SMB2/SMB3 Protocol Fuzzing (syzkaller)

Reading time: 8 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Огляд

Ця сторінка узагальнює практичні техніки для опрацювання та fuzzing Linux in-kernel SMB server (ksmbd) за допомогою syzkaller. Вона зосереджена на розширенні поверхні атаки протоколу через конфігурацію, побудові stateful harness, здатного ланцюжити SMB2 операції, генерації граматично валідних PDU, спрямуванні мутацій у слабко покриті ділянки коду та використанні можливостей syzkaller, таких як focus_areas та ANYBLOB. Хоча оригінальне дослідження перераховує конкретні CVE, тут ми підкреслюємо повторно використовувану методологію та конкретні фрагменти, які ви можете адаптувати до власного середовища.

Target scope: SMB2/SMB3 over TCP. Kerberos and RDMA are intentionally out-of-scope to keep the harness simple.


Розширення поверхні атаки ksmbd через конфігурацію

За замовчуванням мінімальна конфігурація ksmbd залишає великі ділянки сервера неперевіреними. Увімкніть наступні можливості, щоб привести сервер через додаткові парсери/обробники і досягти глибших шляхів виконання коду:

  • Global-level
  • Durable handles
  • Server multi-channel
  • SMB2 leases
  • Per-share-level
  • Oplocks (on by default)
  • VFS objects

Увімкнення цього збільшує виконання в модулях, таких як:

  • 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)

Примітки

  • Точні опції залежать від ksmbd userspace у вашому дистрибутиві (ksmbd-tools). Перегляньте /etc/ksmbd/ksmbd.conf та per-share секції, щоб увімкнути durable handles, leases, oplocks та VFS objects.
  • Multi-channel і durable handles змінюють state machines і час життя ресурсів, часто виявляючи UAF/refcount/OOB баги під конкуренцією.

Налаштування аутентифікації та обмеження швидкості для fuzzing

SMB3 потребує валідної сесії. Реалізація Kerberos у harness ускладнює процес, тому для fuzzing віддавайте перевагу NTLM/guest:

  • Дозвольте guest доступ і встановіть map to guest = bad user, щоб невідомі користувачі падали на GUEST.
  • Приймайте NTLMv2 (запатчте політику, якщо вимкнено). Це зберігає простий handshake, водночас задіюючи SMB3 code paths.
  • Вимкніть жорсткі credit checks під час експериментів (post-hardening for CVE-2024-50285 зробив simultaneous-op crediting суворішим). Інакше rate-limits можуть відхиляти fuzzed послідовності занадто рано.
  • Збільшіть max connections (наприклад, до 65536), щоб уникнути ранніх відхилень під час high-throughput fuzzing.

Увага: ці послаблення призначені тільки для полегшення fuzzing. Не використовуйте такі налаштування в production.


Stateful Harness: Extract Resources and Chain Requests

SMB є stateful: багато запитів залежать від ідентифікаторів, що повертаються у попередніх відповідях (SessionId, TreeID, FileID pairs). Ваш harness має парсити відповіді і повторно використовувати ID в межах однієї програми, щоб досягти глибоких обробників (наприклад, smb2_create → smb2_ioctl → smb2_close).

Приклад фрагмента для обробки буфера відповіді (пропускаючи +4B NetBIOS PDU length) та кешування ID:

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;
}
}

Поради

  • Підтримуйте один процес fuzzer, що спільно використовує автентифікацію/стан: краща стабільність і покриття з ksmbd’s global/session tables. syzkaller все ще вводить конкурентність, позначаючи операції як async, і повторно запускає їх внутрішньо.
  • Експериментальна функція Syzkaller’s reset_acc_state може скинути глобальний стан, але може спричинити значне уповільнення. Надавайте перевагу стабільності та зосередьтеся на fuzzing замість цього.

Граматично керована генерація SMB2 (Valid PDUs)

Перетворіть структури Microsoft Open Specifications SMB2 у fuzzer grammar, щоб ваш генератор створював структурно валідні PDUs, які систематично досягають dispatchers та IOCTL handlers.

Приклад (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]

This style forces correct structure sizes/offsets and dramatically improves coverage versus blind mutation.


Directed Fuzzing With focus_areas

Використовуйте експериментальну опцію focus_areas у syzkaller, щоб надати більшої ваги конкретним функціям/файлам, які наразі мають слабке покриття. Приклад JSON:

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

Це допомагає сконструювати валідні ACLs, які зачіпають арифметичні/overflow шляхи в smbacl.c. Наприклад, шкідливий Security Descriptor з надмірно великим dacloffset відтворює integer-overflow.

Генератор репродуцера (мінімальний 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)

Подолання плато покриття з ANYBLOB

syzkaller’s anyTypes (ANYBLOB/ANYRES) дозволяють згорнути складні структури в blobs, що мутують загально. Створіть новий corpus із публічних SMB pcaps і перетворіть payloads у syzkaller програми, що викликають ваш pseudo-syscall (наприклад, 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)"
)

Це прискорює початок дослідження і може одразу викликати UAFs (наприклад, у ksmbd_sessions_deregister), одночасно підвищуючи покриття на кілька відсотків.


Санітизери: поза KASAN

  • KASAN залишається основним детектором помилок в heap (UAF/OOB).
  • KCSAN часто дає false positives або data races низької серйозності в цьому таргеті.
  • UBSAN/KUBSAN може виявляти declared-bounds помилки, які KASAN пропускає через array-index semantics. Приклад:
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));

Setting num_subauth = 0 triggers an in-struct OOB read of sub_auth[-1], caught by UBSAN’s declared-bounds checks.


Примітки щодо пропускної здатності та паралелізму

  • A single fuzzer process (shared auth/state) tends to be significantly more stable for ksmbd and still surfaces races/UAFs thanks to syzkaller’s internal async executor.
  • With multiple VMs, you can still hit hundreds of SMB commands/second overall. Function-level coverage around ~60% of fs/smb/server and ~70% of smb2pdu.c is attainable, though state-transition coverage is under-represented by such metrics.

Практичний чеклист

  • Увімкніть durable handles, leases, multi-channel, oplocks та VFS objects у ksmbd.
  • Allow guest and map-to-guest; accept NTLMv2. Patch out credit limits and raise max connections for fuzzer stability.
  • Build a stateful harness that caches SessionId/TreeID/FileIDs and chains create → ioctl → close.
  • Use a grammar for SMB2 PDUs to maintain structural validity.
  • Use focus_areas to overweight weakly-covered functions (e.g., smbacl.c paths like smb_check_perm_dacl).
  • Seed with ANYBLOB from real pcaps to break plateaus; pack seeds with syz-db for reuse.
  • Run with KASAN + UBSAN; triage UBSAN declared-bounds reports carefully.

Джерела

  • 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

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks