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 지원하기

개요

이 페이지는 syzkaller를 사용해 Linux 인커널 SMB 서버(ksmbd)를 실행하고 퍼징하기 위한 실용 기법들을 추상화합니다. 구성으로 프로토콜 공격 표면을 확장하고, SMB2 연산을 체이닝할 수 있는 상태 유지 하니스(stateful harness)를 구축하며, 문법에 맞는 PDU를 생성하고, 약하게 커버되는 코드 경로로 변형을 편향시키며, focus_areas와 ANYBLOB 같은 syzkaller 기능을 활용하는 데 중점을 둡니다. 원본 연구는 특정 CVE들을 열거하지만, 여기서는 재사용 가능한 방법론과 자신의 환경에 맞게 적용할 수 있는 구체적인 스니펫을 강조합니다.

대상 범위: SMB2/SMB3 over TCP. Kerberos와 RDMA는 하니스 단순화를 위해 의도적으로 범위에서 제외합니다.


구성으로 ksmbd 공격 표면 확장

기본적인 ksmbd 설정은 서버의 많은 부분을 테스트하지 못한 채로 둡니다. 다음 기능들을 활성화하여 추가 파서/핸들러를 통과시키고 더 깊은 코드 경로에 도달하세요:

  • Global-level
  • Durable handles
  • Server multi-channel
  • SMB2 leases
  • Per-share-level
  • Oplocks (기본적으로 활성화됨)
  • VFS objects

이들을 활성화하면 다음과 같은 모듈에서 실행이 증가합니다:

  • smb2pdu.c (명령 파싱/디스패치)
  • ndr.c (NDR 인코드/디코드)
  • oplock.c (oplock 요청/중단)
  • smbacl.c (ACL 파싱/강제)
  • vfs.c (VFS 연산)
  • vfs_cache.c (조회 캐시)

참고

  • 정확한 옵션은 배포판의 ksmbd 사용자 공간(ksmbd-tools)에 따라 다릅니다. /etc/ksmbd/ksmbd.conf 및 각 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 검사(credit checks)를 패치해 제거하세요 (하드닝 이후 CVE-2024-50285로 동시 작업 크레딧 부여가 더 엄격해졌습니다). 그렇지 않으면 속도 제한이 퍼즈된 시퀀스를 너무 일찍 거부할 수 있습니다.
  • 최대 연결 수를 증가시켜(예: 65536) 고처리량 퍼징 중 조기 거부를 피하세요.

주의: 이러한 완화는 퍼징을 용이하게 하기 위한 것뿐입니다. 운영 환경에 이 설정을 배포하지 마세요.


상태 유지 하니스: 리소스 추출 및 요청 체이닝

SMB는 상태를 가집니다: 많은 요청이 이전 응답에서 반환된 식별자(SessionId, TreeID, FileID 쌍 등)에 의존합니다. 하니스는 응답을 파싱하고 동일한 프로그램 내에서 ID를 재사용하여 깊은 핸들러에 도달해야 합니다(예: smb2_create → smb2_ioctl → smb2_close).

예제 스니펫: 응답 버퍼( +4B NetBIOS PDU 길이 생략)를 처리하고 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는 ops를 async로 표시해 내부적으로 재실행하면서 여전히 동시성을 주입합니다.
  • Syzkaller의 experimental reset_acc_state는 global state를 리셋할 수 있지만 심각한 성능 저하를 초래할 수 있습니다. 안정성을 우선하고 fuzzing에 집중하세요.

문법 기반 SMB2 생성 (유효한 PDUs)

Microsoft Open Specifications의 SMB2 구조를 fuzzer grammar로 변환하여 generator가 구조적으로 유효한 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]

이 방식은 구조체 크기/오프셋을 올바르게 강제하며 블라인드 뮤테이션에 비해 커버리지를 극적으로 향상시킵니다.


Directed Fuzzing With focus_areas

syzkaller’s 실험적 focus_areas를 사용하여 현재 커버리지가 약한 특정 함수/파일에 가중치를 더하세요. 예시 JSON:

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의 arithmetic/overflow 경로를 타깃하는 유효한 ACLs를 구성하는 데 도움이 됩니다. 예를 들어, 과도한 dacloffset을 가진 악의적인 Security Descriptor는 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)는 복잡한 구조를 일반적으로 mutate하는 blob으로 축소할 수 있게 해준다. 공개 SMB pcaps에서 새로운 corpus를 seed하고 payload를 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)를 유발할 수 있습니다.


Sanitizers: Beyond KASAN

  • KASAN은 힙 버그(UAF/OOB)를 탐지하는 주요 수단으로 남아 있습니다.
  • KCSAN은 이 대상에서 종종 오탐을 내거나 심각도가 낮은 데이터 레이스를 보고합니다.
  • UBSAN/KUBSAN은 배열 인덱스 의미론 때문에 KASAN이 놓치는 선언된 경계 오류를 잡을 수 있습니다. 예:
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));

num_subauth = 0으로 설정하면 구조체 내부에서 sub_auth[-1]에 대한 OOB read가 발생하며, UBSAN의 declared-bounds 검사에 의해 포착됩니다.


처리량 및 병렬성 주의사항

  • 단일 fuzzer 프로세스 (shared auth/state)는 ksmbd에 대해 훨씬 더 안정적인 경향이 있으며, syzkaller의 내부 async executor 덕분에 여전히 races/UAFs를 드러냅니다.
  • 여러 VM을 사용하면 전반적으로 초당 수백 건의 SMB 명령을 처리할 수 있습니다. 함수 수준의 커버리지는 fs/smb/server의 약 60% 및 smb2pdu.c의 약 70% 정도 달성할 수 있으나, 상태 전이(state-transition) 커버리지는 이러한 지표로는 과소평가됩니다.

실무 체크리스트

  • 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
  • 배경 읽기: 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 지원하기