Directorio .git expuesto: git-dumper y secretos en el historial
Cómo detectar un .git expuesto en una web, reconstruir el repositorio con git-dumper y encontrar contraseñas y claves en el historial de commits.
Si el desarrollador desplegó la web copiando la carpeta del proyecto tal cual, el directorio .git viaja con ella. Desde fuera puedes descargarlo y reconstruir todo el código fuente y, lo que es mejor, todo su historial: cada contraseña que alguien subió por error y luego "borró" sigue en un commit antiguo.
Es de los hallazgos más rentables en una máquina: pasas de caja negra a tener el código, y a menudo credenciales directas.
Detectarlo
curl -s http://objetivo.htb/.git/HEAD
# ref: refs/heads/master ← expuesto
Otras señales:
nmap -sClo avisa solo: el scripthttp-gitsaca la líneaGit repository found!.- Un fuzzing de directorios con cualquier lista común encuentra
.git/(más en la guía de fuzzing web). - Prueba también en cada vhost y subdominio: en LinkVortex solo está en
dev..
Si /.git/ devuelve 403 pero /.git/HEAD o /.git/config devuelven 200, está expuesto igual: solo está prohibido listar el directorio.
Descargarlo con git-dumper
pipx install git-dumper
git-dumper http://objetivo.htb/.git/ ./repo
cd repo && git status && git log --oneline --all
git-dumper sigue las referencias desde HEAD, descarga los objetos uno a uno y reconstruye el árbol de trabajo, aunque el listado de directorios esté desactivado.
Nota
Si falla, GitTools (gitdumper.sh + extractor.sh) es la alternativa clásica. El extractor saca cada commit en una carpeta distinta, útil si el repositorio está roto.
Buscar secretos en el historial
Lo primero, el código actual: ficheros de configuración, .env, cadenas de conexión a la base de datos y rutas ocultas. Después, el historial:
git log -p --all | grep -iE "pass|secret|token|key|pwd" | head -50 # cambios con palabras clave
git log --all --stat # qué ficheros tocó cada commit
git show <commit> # ver un commit entero
git log --all --diff-filter=D --name-only # ficheros que se borraron
git stash list; git branch -a; git tag # ramas y stash olvidados
Para no buscar a mano, deja que lo haga una herramienta de detección de secretos:
trufflehog git file://$(pwd) --no-update
gitleaks detect -s . -v
| Qué buscar | Por qué |
|---|---|
| Commits con mensajes como "quitar credenciales" o "limpieza" | Justo el anterior tiene la contraseña (OpenSource, Seal) |
La clave para firmar tokens (SECRET_KEY, JWT_SECRET) |
Te permite falsificar sesiones de administrador (Secret; ver ataques a JWT) |
.git/config |
A veces la URL del remoto lleva usuario y contraseña: https://usuario:pass@gitea... |
Hooks y CI (.git/hooks, .gitlab-ci.yml) |
Revelan cómo se despliega y qué se ejecuta tras un push (Bitlab) |
Leer el código para encontrar el fallo
Con el código, la búsqueda deja de ser a ciegas. Busca las funciones peligrosas del lenguaje y sigue de dónde vienen sus datos:
grep -rnE "system\(|exec\(|eval\(|popen|shell_exec|unserialize|pickle.loads|render_template_string" .
grep -rnE "SELECT .*\+|query\(.*\\\$" . # consultas construidas concatenando
Esto lleva a las guías de cada fallo: inyección de comandos, SSTI, deserialización o inyección SQL.
El mismo truco en otros sitios
- SVN:
/.svn/wc.dbes una base SQLite con los ficheros;svnosvn-extractorla reconstruyen. Hay credenciales en una revisión antigua de Worker. - Mercurial y Bazaar:
/.hg/y/.bzr/, con herramientas equivalentes. - Imágenes Docker: cada capa es como un commit.
docker save+ descomprimir las capas muestra ficheros que se borraron después (Bolt). - Servidores Gitea o GitLab dentro de la red: explora repositorios públicos y el historial de cada uno.