Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-89633 — CVE-2026-89633에 대한 PoC 및 익스플로잇 체인으로, Linux cifs.ko SMB1 TRANS2 병합 경로의 힙 범위 초과 쓰기 취약점이며, cred 덮어쓰기와 PTE 앨리어싱을 통해 uid 0으로 권한 상승한다. | Kitploit
도구/GitHubGitHub/woshigenm/cve-2026-89633
Android SecurityPrivilege EscalationMemory ForensicsVulnerability AnalysisExploitationPapers & ResearchBinary Exploitation
GitHubwoshigenm/cve-2026-89633

CVE-2026-89633

CVE-2026-89633에 대한 PoC 및 익스플로잇 체인으로, Linux cifs.ko SMB1 TRANS2 병합 경로의 힙 범위 초과 쓰기 취약점이며, cred 덮어쓰기와 PTE 앨리어싱을 통해 uid 0으로 권한 상승한다.

저장소 보기
113일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-89633 — cifs SMB1 coalesce_t2 힙 범위 초과 쓰기

한국어 | 简体中文

Linux cifs.ko SMB1 클라이언트의 힙 범위 초과 쓰기에 대한 연구용 PoC/EXP입니다. 악의적인 SMB1 서버가 TRANS2 보조 응답의 DataOffset을 제어하면, coalesce_t2()가 대상 범위 검사 없이 8바이트 보조 페이로드를 &primary->Protocol + DataOffset + accumulated에 복사합니다. 복사 대상은 응답 버퍼(server->bigbuf)를 기준으로 서버가 지정하는 임의의 위치입니다.

이 저장소는 역할이 서로 다른 두 가지 시연을 유지하며, 이들은 서로를 대체하지 않습니다:

  • POC — OOB 쓰기를 트리거하고 관찰합니다: 악의적인 SMB1 서버와 런타임에 DataOffset을 패치하는 TCP 프록시.
  • EXP 1 (최소 프리미티브) — 쓰기를 실제 자격 증명 덮어쓰기로 전환하는 루트 측 참조 체인: 대상 프로세스의 cred slab 페이지를 파이프로 제어되는 물리 페이지에 배치한 다음, 4프레임 coalesce 응답으로 uid/gid/suid/sgid/euid/egid/fsuid/fsgid를 0으로 만듭니다. OOB 쓰기가 제어 가능하며 cred를 수정할 수 있음을 가장 적은 의존성으로 직접 증명합니다.
  • EXP 2 (고급 프리미티브) — 셸 전용 PTE 체인: 동일한 OOB 쓰기로 사용자 쓰기 가능한 PTE를 설치하고, 별칭이 cred 페이지와 선택적으로 selinux_state를 매핑하며, 루트 측 관찰 없이 클론이 전체 caps를 가진 uid 0이 됩니다. 이는 EXP 1의 확장이며 대체물이 아닙니다.

커널 모듈 로딩은 이 저장소의 범위에서 의도적으로 제외됩니다: 체인은 uid 0(및 선택적으로 selinux_state permissive)에서 멈추며 모듈을 설치하지 않습니다. 모듈이 로드되지 않더라도 uid 0 + permissive는 이 저장소가 주장하는 완전한 LPE 시연입니다.

EXP 2의 비용은 명시적으로 남아 있습니다: 윈도우별 복권(~25–33%, 12회 시도 시 ~97–99%), 재부팅까지 유지되는 베어 PTE, 셸 쓰기 가능한 tracefs에 대한 의존성, 그리고 빌드별 direct-map/호출 지점/SEL_PFN 가정. EXP 1은 가장 단순한 프리미티브 증명이자 셸 쓰기 가능한 tracefs를 사용할 수 없을 때의 대체 수단으로 남습니다.

상태

항목값
CVECVE-2026-89633
분류힙 범위 초과 쓰기 (CWE-787)
구성 요소cifs.ko, SMB1 TRANS2 보조 coalescing
업스트림 수정36d01415d881 ("smb: client: fix ... coalesce_t2", 6.12.113)
POC트리거 및 OOB 쓰기 검증됨 (마운트 후 및 마운트 중)
EXP 1 (최소 프리미티브)루트 측 관찰 하의 4프레임 OOB cred 쓰기; uid 0 검증됨 (마운트 후 및 마운트 시점 유지 응답)
EXP 2 (고급 프리미티브)셸 전용 PTE 체인; uid 2000 → uid 0 + 전체 caps + Permissive 검증됨 (SEL_PFN/SEL_OFF); 베어 PTE에서 멈추며 모듈 로드 없음
요구 사항공격자가 제어하는 서버에 대한 SMB1 마운트(권한 게이트); 참조 게이트는 su를 사용하며, 셸 전용 배치는 셸 쓰기 가능한 tracefs가 필요함

테스트 환경: arm64 Android 16 벤더 빌드, 커널 6.12.38, 6.12.23 KMI 베이스라인에서 빌드된 cifs.ko, SELinux enforcing.

테스트 범위

  • 검증됨: 위의 arm64 Android 16 빌드(커널 6.12.38, 6.12.23 KMI 베이스라인의 cifs.ko) — POC 트리거/OOB 쓰기(마운트 후 및 마운트 자체 중, 마운트 지점 접근 없이), EXP 1 루트 측 참조 체인(uid 0), 마운트 시점 유지 응답 변형(statfs 없음, 마운트 지점 접근 없음), EXP 2 셸 전용 배치(tracefs만 사용, 루트 측 관찰 없음), 전체 EXP 2 수용(uid 0 + 모든 cap 비트 + SEL_PFN/SEL_OFF를 사용한 Permissive), 그리고 su 기반 마운트 게이트(마운트만 루트로 실행; 배치는 uid 2000으로 실행)가 SELinux enforcing 하에서 테스트되었습니다.
  • 검증되지 않음: 다른 6.12.x 빌드, 다른 Android 버전/SoC, 순정 AOSP GKI 커널, 또는 비-arm64 플랫폼. 호출 지점 링크, 구조체 오프셋 및 direct-map 상수는 빌드별로 다르므로, EXP가 작동하기를 기대하기 전에 다른 커널에서 재검증하십시오.

버그

MAX_CIFS_SMALL_BUFFER_SIZE - 4(444바이트)보다 큰 SMB1 TRANS2 응답의 경우, 클라이언트는 기본 응답을 server->bigbuf에 유지하고 이를 mid->resp_buf에 저장합니다. 이어지는 SMB_COM_TRANSACTION2_SECONDARY 응답은 cifs_check_trans2() -> check2ndT2() -> coalesce_t2()를 거칩니다:

data_area_of_tgt = &primary->Protocol + primary->DataOffset + total_in_tgt;
memcpy(data_area_of_tgt, data_area_of_src, secondary->DataCount);

DataOffset는 서버 응답에서 그대로 가져옵니다. 카운터 검사(total_in_tgt/byte_count 오버플로, 소스 버퍼 경계)는 존재하지만, data_area_of_tgt가 응답 버퍼 내부에 머무는지 확인하는 검사는 없습니다. 각 보조 프레임은 8바이트씩 더 멀리 위치하므로(누적된 DataCount), 다중 프레임 응답은 버퍼 기준점으로부터 공격자가 선택한 오프셋(16비트)에 8*N 바이트 쓰기를 발생시킵니다.

트리거 조건:

  1. 클라이언트가 공격자가 제어하는 서버에서 SMB1 공유를 마운트함(vers=1.0);
  2. 클라이언트가 임의의 TRANS2 요청을 발행함(PoC는 statfs를 통한 QUERY_FS_INFORMATION을 사용);
  3. 서버가 TotalDataCount > DataCount이고 bigbuf 경로에 충분히 큰 프라이머리로 응답한 뒤, TotalDataCount > DataCount인 하나 이상의 보조 프레임으로 응답함.

저장소 구조

Makefile
src/poc/poc_smb1_trans2.py   malicious SMB1 server (QFS hook, runtime ctl)
src/poc/smb1_proxy.py        TCP proxy: patches DataOffset, repeats secondaries
src/exp/pipesearch.c         pipe placement/write driver (modes 3, 8, 9)
src/exp/shcred.c             shell-side drain + clone helper (uid 2000)
src/exp/shp4a2.c             trace-based drainer/observer/clone (modes 8/9)
src/exp/pte_fault.c          2 MiB fault + PTE alias writes
src/exp/bscan.c              bigbuf discovery by call site (no kprobes)
src/exp/kslide.c             KASLR slide from a raw call site
src/exp/smbd.c               device-side SMB1 server (held TRANS2)
src/exp/smbd_templates.h     SMB1 response templates for smbd
src/exp/pfn.c                linear-map VA to pfn
src/exp/kflags.c             /proc/kpageflags reader
scripts/setup_device.sh      trace instance + kprobes (root on device)
scripts/start_servers.sh     host: SMB1 server + proxy + mount helper
scripts/probe_round.sh       one probe round: bigbuf base + free target page
scripts/place.sh             placement: pipesearch mode 3 + shcred
scripts/write_cred.sh        4-frame coalesce write + /proc verification
scripts/mount_su.sh          generic su mount gate (target/decoy/abort/unmount)
scripts/chain_shell.sh       shell-only placement for an already-held TRANS2
scripts/gen_smb_templates.py regenerates smbd_templates.h from a capture
docs/analysis.md             vulnerability and chain analysis
docs/exp-protocol.md         shared-page and smbd ctl protocols

빌드

make deps        # checks impacket
make helpers     # NDK cross-build of all C helpers
make push        # adb push to /data/local/tmp

NDK, API, ARCH, ADB, DEVICE_DIR는 재정의할 수 있습니다.

POC — OOB 쓰기 트리거 및 관찰

트리거 자체는 SMB1 마운트와 실행 중인 서버/프록시만 있으면 됩니다. kprobe와 kflags는 관찰 보조 수단이며 트리거의 일부가 아닙니다 — dst/src/len 증거가 필요할 때 설치하십시오 (그리고 아래 EXP 체인에서 필수이며, bigbuf 베이스, 배치 감시, 대상 cred 주소가 필요합니다).

  1. 디바이스 (root, 선택 사항 — 관찰 전용): 프로브를 설치합니다.

    adb push scripts/setup_device.sh /data/local/tmp/
    adb shell su -c 'sh /data/local/tmp/setup_device.sh'
    adb push build/kflags /data/local/tmp/kflags
    
  2. 호스트: SMB1 서버와 프록시를 시작합니다(스크립트는 공유 디렉터리도 생성하고 마운트 명령을 출력합니다):

    scripts/start_servers.sh /tmp/cifs01-ctl
    

    1470에서 src/poc/poc_smb1_trans2.py를 실행하고, 제어 디렉터리 /tmp/cifs01-ctl과 함께 src/poc/smb1_proxy.py(1460 -> 1470)를 실행합니다.

  3. 로컬 테스트 토폴로지: 프록시 포트를 디바이스에 매핑하고 디바이스에서 root로 공유를 마운트합니다.

    adb reverse tcp:1460 tcp:1460
    adb shell su -c 'mkdir -p /mnt/cifs'
    adb shell su -c 'mount -t cifs //127.0.0.1/share /mnt/cifs \
        -o vers=1.0,port=1460,username=test,password=test,sec=ntlmssp'
    
    • vers=1.0은 취약한 SMB1 경로를 선택합니다(SMB2/3는 coalesce_t2에 도달하지 않음).
    • port=1460은 이 토폴로지에서의 프록시 포트입니다 — 서버가 기본값 445에서 수신 대기하는 실제 네트워크에서는 이를 제거하십시오.
    • username=test,password=test는 PoC 서버의 자격 증명입니다.
    • sec=ntlmssp는 PoC 서버가 허용하는 보안 모드입니다.
    • //127.0.0.1/share는 서버/공유입니다. 마운트 지점은 임의입니다.

    마운트는 권한이 필요한 관문입니다 — 아래의 도달 가능성(Reachability)을 참조하십시오.

  4. 한 라운드를 트리거합니다(훅을 무장하고, 악성 primary를 유지하며, DataOffset을 패치하고, 해제함).

    scripts/probe_round.sh 1
    

    프로브가 설치된 상태에서 인스턴스 트레이스에는 oobpri(기본 헤더 필드)와 cifs01m/cifs01mv(memcpy dst/src/len/val)가 포함됩니다. 기본 프로브 DataOffset=0x4100을 사용하면 dst - prim은 0x4104로, 16640바이트 cifs_request slab 객체(32 KiB order-3 slab의 꼬리 패딩)를 넘어서므로, 이 쓰기는 다른 할당을 손상시키지 않는 실제 객체 외부 쓰기입니다. 반면 DataOffset=0은 SMB 헤더 필드를 제자리에서 다시 씁니다.

EXP 1 — 최소 프리미티브: OOB cred 쓰기

단순 트리거와 달리 EXP 1은 관찰 보조 수단을 익스플로잇의 일부로 사용합니다. cifsget은 다음 응답의 bigbuf 베이스 B를 제공하고, 루트 도구의 /proc/kpageflags 읽기가 페이지 배치를 유도하며, credprep 트레이스는 대상 자식의 cred 주소를 제공합니다. POC 섹션의 동일한 서버/프록시가 사용됩니다.

체인을 요약하면 다음과 같습니다(자세한 내용은 docs/analysis.md 및 docs/exp-protocol.md 참조):

  1. probe — 다음 응답에서 사용될 bigbuf 베이스 B와 pfn(B)+8..pfn(B)+16 범위의 빈 물리 페이지 P를 알아냅니다(scripts/probe_round.sh).
  2. place — scripts/place.sh가 pipesearch 모드 3과 shcred를 실행합니다. 대상 페이지는 CPU의 per-CPU 페이지 리스트에 마지막으로 해제되고, 셸은 setfsuid로 memcg cred 캐시를 비우며, 루트 도구는 kpageflags(P)가 cred slab(0x80)이 될 때까지 폴링한 뒤 비우기를 중단하고, 셸은 자식 하나를 클론하는데 이 자식의 copy_creds()가 현재 slab의 빈 객체 — 즉 P — 를 차지합니다.
  3. write — scripts/write_cred.sh가 TotalDataCount=32인 primary와 8바이트 secondary 프레임 네 개를 전송합니다. DataOffset = (cred - B) + 4로 설정하면 네 개의 병합 쓰기가 uid/gid, suid/sgid, euid/egid, fsuid/fsgid를 0으로 만듭니다.
  4. verify — /proc/<child>/status에 Uid: 0 0 0 0 / Gid: 0 0 0 0이 표시됩니다.

테스트 빌드에서 검증된 내용:

도구 다운로드