ksmbd 공격 표면 및 SMB2/SMB3 프로토콜 퍼징 (syzkaller)
Reading time: 8 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
개요
이 문서는 syzkaller를 사용해 Linux in-kernel SMB 서버(ksmbd)를 테스트하고 퍼징하는 실용 기술들을 추상화해서 설명합니다. 구성 변경을 통해 프로토콜 공격 표면을 확장하고, SMB2 연산을 체이닝할 수 있는 상태 유지형 하니스(stateful harness)를 구축하며, 문법적으로 유효한 PDU를 생성하고, 약하게 커버되는 코드 경로에 변형(mutation)을 편향시켜 유효한 버그를 찾는 방법, 그리고 focus_areas와 ANYBLOB 같은 syzkaller 기능을 활용하는 방법에 중점을 둡니다. 원래 연구는 특정 CVE들을 열거하지만, 여기서는 재사용 가능한 방법론과 자신 환경에 맞게 적용할 수 있는 구체적 스니펫에 중점을 둡니다.
대상 범위: SMB2/SMB3 over TCP. Kerberos and RDMA는 하니스 단순화를 위해 의도적으로 범위에서 제외합니다.
구성으로 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는 상태 머신과 수명을 변경하여, 동시성 상황에서 UAF/refcount/OOB 버그를 자주 드러냅니다.
퍼징을 위한 인증 및 속도 제한 조정
SMB3는 유효한 세션이 필요합니다. 하니스에 Kerberos를 구현하면 복잡성이 증가하므로 퍼징에는 NTLM/guest를 선호하세요:
- guest 접근을 허용하고 map to guest = bad user로 설정하여 알려지지 않은 사용자가 GUEST로 폴백되도록 하세요.
- NTLMv2를 허용하세요(비활성화되어 있다면 정책을 패치). 이렇게 하면 핸드셰이크를 단순하게 유지하면서 SMB3 코드 경로를 실행할 수 있습니다.
- 실험 시 엄격한 credit 검사를 패치하세요(post-hardening for CVE-2024-50285로 인해 동시-op 크레디팅이 더 엄격해졌습니다). 그렇지 않으면 속도 제한으로 인해 퍼징 중인 시퀀스가 너무 일찍 거부될 수 있습니다.
- 고처리량 퍼징 중 조기 거부를 피하기 위해 최대 연결 수를 늘리세요(예: 65536).
주의: 이러한 완화는 퍼징을 용이하게 하기 위한 것뿐입니다. 프로덕션 환경에 이러한 설정을 적용하지 마세요.
상태 유지 하니스: 리소스 추출 및 요청 체이닝
SMB는 상태 기반입니다: 많은 요청이 이전 응답에서 반환된 식별자(SessionId, TreeID, FileID 쌍 등)에 의존합니다. 하니스는 응답을 파싱하여 동일한 프로그램 내에서 ID를 재사용해야 심층 핸들러에 도달할 수 있습니다(예: smb2_create → smb2_ioctl → smb2_close).
응답 버퍼를 처리하고(+4B NetBIOS PDU 길이는 건너뜀) ID를 캐시하는 예시 스니펫:
// 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의 전역/세션 테이블과 함께 더 나은 안정성 및 커버리지를 제공합니다. syzkaller는 ops를 async로 표시해 동시성을 주입하고 내부적으로 재실행합니다.
- Syzkaller의 실험적 기능 reset_acc_state는 전역 상태를 리셋할 수 있지만 심한 성능 저하를 초래할 수 있습니다. 대신 안정성을 우선하고 fuzzing에 집중하세요.
문법 기반 SMB2 생성 (유효한 PDUs)
Microsoft Open Specifications의 SMB2 구조를 fuzzer grammar로 변환해 generator가 구조적으로 유효한 PDU를 생성하도록 하세요. 이렇게 하면 PDUs가 체계적으로 디스패처와 IOCTL 핸들러에 도달합니다.
예시 (SMB2 IOCTL 요청):
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]
이 스타일은 올바른 structure sizes/offsets를 강제하며 blind mutation에 비해 커버리지를 획기적으로 향상시킵니다.
Directed Fuzzing With focus_areas
현재 커버리지가 약한 특정 함수/파일에 가중치를 두기 위해 syzkaller의 실험적 focus_areas를 사용하세요. 예시 JSON:
{
"focus_areas": [
{"filter": {"functions": ["smb_check_perm_dacl"]}, "weight": 20.0},
{"filter": {"files": ["^fs/smb/server/"]}, "weight": 2.0},
{"weight": 1.0}
]
}
이는 smbacl.c의 산술/overflow 경로를 유발하는 유효한 ACLs를 구성하는 데 도움이 됩니다. 예를 들어, 과도한 dacloffset을 가진 악의적인 Security Descriptor가 integer-overflow를 재현합니다.
재현기 빌더 (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)
ANYBLOB으로 커버리지 정체 돌파
syzkaller의 anyTypes (ANYBLOB/ANYRES)는 복잡한 구조체를 형식에 구애받지 않고 변형 가능한 blob으로 합칠 수 있다. 공개된 SMB pcaps에서 새로운 corpus를 생성하고 페이로드를 syzkaller 프로그램으로 변환해 당신의 pseudo-syscall(예: 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)"
)
이것은 탐색을 빠르게 시작시키며 UAFs(예: ksmbd_sessions_deregister) 를 즉시 유발할 수 있고 커버리지를 몇 퍼센트 정도 끌어올린다.
Sanitizers: KASAN을 넘어서
- KASAN은 힙 버그(UAF/OOB)를 탐지하는 주요 도구로 여전히 남아 있다.
- KCSAN은 이 타겟에서 종종 오탐이나 낮은 심각도의 데이터 레이스를 보고한다.
- UBSAN/KUBSAN은 배열 인덱스 의미론 때문에 KASAN이 놓치는 선언된 경계 오류를 잡아낼 수 있다. 예:
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을 설정하면 sub_auth[-1]에 대한 in-struct OOB read가 발생하며, UBSAN의 declared-bounds 검사에 의해 포착됩니다.
처리량 및 병렬성 관련 메모
- 단일 fuzzer 프로세스(인증/상태 공유)는 ksmbd에서 훨씬 더 안정적이며, syzkaller의 internal async executor 덕분에 여전히 races/UAFs를 드러냅니다.
- 여러 VM을 사용하면 전체적으로 초당 수백 건의 SMB 명령을 여전히 처리할 수 있습니다. 함수 수준 커버리지는 fs/smb/server의 약 60%와 smb2pdu.c의 약 70% 정도 달성이 가능하지만, 이러한 지표는 상태 전환 커버리지를 충분히 반영하지 못합니다.
실용 체크리스트
- ksmbd에서 durable handles, leases, multi-channel, oplocks 및 VFS objects를 활성화하세요.
- guest 및 map-to-guest를 허용하고 NTLMv2를 수용하세요. fuzzer 안정성을 위해 credit limits를 제거하고 max connections를 늘리세요.
- SessionId/TreeID/FileIDs를 캐시하고 create → ioctl → close를 연쇄하는 stateful harness를 구축하세요.
- 구조적 유효성을 유지하기 위해 SMB2 PDUs에 대한 grammar를 사용하세요.
- focus_areas를 사용해 커버리지가 낮은 함수(예: smbacl.c의 smb_check_perm_dacl 경로)에 더 높은 비중을 부여하세요.
- 정체기를 깨기 위해 실제 pcaps에서 ANYBLOB로 시드하세요; 재사용을 위해 시드를 syz-db로 패키징하세요.
- KASAN + UBSAN로 실행하세요; UBSAN declared-bounds 리포트는 신중히 분류하세요.
참고자료
- 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 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.