ksmbd Surface d'attaque & SMB2/SMB3 Protocol Fuzzing (syzkaller)
Reading time: 9 minutes
tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
Aperçu
Cette page synthétise des techniques pratiques pour exercer et fuzz le serveur SMB en-kernel Linux (ksmbd) en utilisant syzkaller. Elle se concentre sur l'expansion de la surface d'attaque du protocole via la configuration, la construction d'un harnais stateful capable d'enchaßner des opérations SMB2, la génération de PDUs valides grammaticalement, le biaisage des mutations vers des chemins de code faiblement couverts, et l'exploitation des fonctionnalités de syzkaller telles que focus_areas et ANYBLOB. Alors que la recherche originale énumÚre des CVE spécifiques, ici nous mettons l'accent sur la méthodologie réutilisable et des extraits concrets que vous pouvez adapter à vos propres environnements.
Portée cible : SMB2/SMB3 over TCP. Kerberos et RDMA sont volontairement hors-scope pour garder le harnais simple.
Ătendre la surface d'attaque de ksmbd via la configuration
Par défaut, une configuration ksmbd minimale laisse de larges parties du serveur non testées. Activez les fonctionnalités suivantes pour pousser le serveur à travers des parseurs/handlers supplémentaires et atteindre des chemins de code plus profonds :
- Global-level
- Durable handles
- Server multi-channel
- SMB2 leases
- Per-share-level
- Oplocks (activés par défaut)
- VFS objects
L'activation de ces éléments augmente l'exécution dans des modules tels que :
- smb2pdu.c (parsing/dispatch des commandes)
- ndr.c (encodage/décodage NDR)
- oplock.c (demande/rupture d'oplock)
- smbacl.c (parsing/renforcement des ACL)
- vfs.c (opérations VFS)
- vfs_cache.c (cache de lookup)
Notes
- Les options exactes dépendent des userspace ksmbd de votre distro (ksmbd-tools). Consultez /etc/ksmbd/ksmbd.conf et les sections par-partage pour activer durable handles, leases, oplocks et VFS objects.
- Multi-channel et durable handles modifient les machines d'état et les durées de vie, révélant souvent des bugs UAF/refcount/OOB sous concurrence.
Authentification et ajustements de rate-limiting pour le Fuzzing
SMB3 nécessite une session valide. Implémenter Kerberos dans les harnais ajoute de la complexité, donc préférez NTLM/guest pour le fuzzing :
- Autorisez l'accÚs guest et définissez map to guest = bad user afin que les utilisateurs inconnus retombent sur GUEST.
- Acceptez NTLMv2 (patcher la policy si désactivée). Cela maintient la poignée de main simple tout en exerçant les chemins de code SMB3.
- Patcherez les contrÎles stricts de credits lors des expérimentations (le durcissement postérieur pour CVE-2024-50285 a rendu le crédit pour opérations simultanées plus strict). Sinon, les rate-limits peuvent rejeter des séquences fuzzées trop tÎt.
- Augmentez le max connections (p. ex. à 65536) pour éviter des rejets précoces lors d'un fuzzing à haut débit.
Attention : Ces relaxations servent uniquement à faciliter le fuzzing. Ne pas déployer ces réglages en production.
Harnais Ă Ă©tats : Extraire des ressources et enchaĂźner des requĂȘtes
SMB est stateful : beaucoup de requĂȘtes dĂ©pendent d'identifiants retournĂ©s par des rĂ©ponses prĂ©cĂ©dentes (SessionId, TreeID, paires FileID). Votre harnais doit parser les rĂ©ponses et rĂ©utiliser les IDs dans le mĂȘme programme pour atteindre des handlers profonds (p. ex., smb2_create â smb2_ioctl â smb2_close).
Exemple d'extrait pour traiter un buffer de réponse (en sautant les +4B de longueur NetBIOS PDU) et mettre en cache les 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;
}
}
Conseils
- Gardez un seul processus fuzzer partageant l'authentification/état : meilleure stabilité et couverture avec les tables globales/session de ksmbd. syzkaller injecte néanmoins de la concurrence en marquant les ops comme async, réexécution en interne.
- L'option expérimentale reset_acc_state de syzkaller peut réinitialiser l'état global mais introduit un ralentissement important. Privilégiez la stabilité et concentrez-vous sur le fuzzing.
Génération SMB2 pilotée par une grammaire (PDUs valides)
Traduisez les structures SMB2 des Microsoft Open Specifications en une grammaire pour fuzzer afin que votre générateur produise des PDUs structurellement valides, qui atteignent systématiquement les dispatchers et les IOCTL handlers.
Exemple (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]
Ce style force des tailles/décalages de structure corrects et améliore considérablement la couverture par rapport à la mutation aveugle.
Fuzzing dirigé avec focus_areas
Utilisez syzkallerâs experimental focus_areas pour surpondĂ©rer des fonctions/fichiers spĂ©cifiques qui ont actuellement une faible couverture. Exemple JSON:
{
"focus_areas": [
{"filter": {"functions": ["smb_check_perm_dacl"]}, "weight": 20.0},
{"filter": {"files": ["^fs/smb/server/"]}, "weight": 2.0},
{"weight": 1.0}
]
}
Ceci aide à construire des ACLs valides qui atteignent les chemins arithmetic/overflow dans smbacl.c. Par exemple, un Security Descriptor malveillant avec un dacloffset surdimensionné reproduit un integer-overflow.
Script de reproduction (Python minimal):
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)
Briser les plateaux de coverage avec ANYBLOB
Les anyTypes de syzkaller (ANYBLOB/ANYRES) permettent de réduire des structures complexes en blobs qui mutent de façon générique. Générez un nouveau corpus à partir de pcaps SMB publics et convertissez les payloads en programmes syzkaller appelant votre pseudo-syscall (e.g., 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)"
)
Cela lance l'exploration et peut immédiatement déclencher des UAFs (p. ex., dans ksmbd_sessions_deregister) tout en augmentant la couverture de quelques pourcents.
Sanitizers : Au-delĂ de KASAN
- KASAN reste le principal détecteur pour les bogues de heap (UAF/OOB).
- KCSAN produit souvent des faux positifs ou des data races de faible gravité sur cette cible.
- UBSAN/KUBSAN peut détecter des erreurs de bornes déclarées que KASAN manque à cause de la sémantique des indices de tableau. Exemple:
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));
Définir num_subauth = 0 déclenche une lecture in-struct OOB de sub_auth[-1], détectée par les declared-bounds checks d'UBSAN.
Notes sur le débit et le parallélisme
- Un seul processus fuzzer (auth/state partagĂ©) a tendance Ă ĂȘtre significativement plus stable pour ksmbd et met nĂ©anmoins au jour des races/UAFs grĂące Ă l'async executor interne de syzkaller.
- Avec plusieurs VM, vous pouvez toujours atteindre des centaines de commandes SMB par seconde au total. Une couverture au niveau fonction d'environ ~60% de fs/smb/server et ~70% de smb2pdu.c est atteignable, bien que la couverture des transitions d'état soit sous-représentée par de tels métriques.
Checklist pratique
- Activez durable handles, leases, multi-channel, oplocks et VFS objects dans ksmbd.
- Autorisez guest et map-to-guest ; acceptez NTLMv2. Ăliminez les credit limits et augmentez le max connections pour la stabilitĂ© du fuzzer.
- Construisez un stateful harness qui met en cache SessionId/TreeID/FileIDs et enchaĂźne create â ioctl â close.
- Utilisez une grammar pour SMB2 PDUs afin de maintenir la validité structurelle.
- Utilisez focus_areas pour surpondérer les fonctions faiblement couvertes (par ex., chemins de smbacl.c comme smb_check_perm_dacl).
- Grainez avec ANYBLOB tiré de pcaps réels pour franchir les plateaux ; packez les seeds avec syz-db pour réutilisation.
- Exécutez avec KASAN + UBSAN ; triez soigneusement les rapports declared-bounds d'UBSAN.
Références
- 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
- Lecture de fond: pwning.tech âTickling ksmbd: fuzzing SMB in the Linux kernelâ; notes syzkaller de Dongliang Mu
tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :
HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
HackTricks