the_open_door
café
ESEN
← Volver al índice

Secrets in git history

ATT&CKT1552.001

Un repositorio git no guarda solo el estado actual del código, sino toda su historia: cada commit es una instantánea completa. Por eso, borrar una contraseña o un token del código y commitear el cambio no lo elimina: el secreto sigue accesible en el commit donde se introdujo. Es uno de los errores más comunes y rentables que encontrar tras conseguir acceso (o incluso desde fuera, si el .git es accesible por web).

Cuando se encuentra un repo (típicamente en /opt, /var/www, el home de un usuario, o referenciado en un .gitignore), conviene revisar la historia entera:

git -C <repo> log --oneline --all          # listar commits
git -C <repo> show <commit>                # ver el diff de un commit concreto
git -C <repo> log -p                        # historia con diffs
git -C <repo> grep -i 'password\|token\|secret' $(git -C <repo> rev-list --all)

Lo que suele aparecer: tokens de API, claves de servicios (un CONSUL_HTTP_TOKEN, una clave AWS), URLs de conexión con credenciales, ficheros .env borrados, contraseñas en commits de "pruebas". Cada uno puede ser el siguiente eslabón de la cadena (autenticarse contra un servicio interno, escalar, etc.).

Nota sobre git moderno. Versiones recientes bloquean operar en repos de otro dueño ("dubious ownership"); se resuelve con git config --global --add safe.directory <repo>.

También conviene mirar los rincones que log no muestra de primeras:

git -C <repo> reflog                        # commits "perdidos" (rebase, reset)
git -C <repo> stash list && git -C <repo> stash show -p
git -C <repo> branch -a                     # ramas remotas olvidadas

Herramientas. Para repos grandes, gitleaks o trufflehog automatizan la búsqueda de secretos en todo el historial:

gitleaks detect --source <repo> -v
trufflehog git file://<repo> --only-verified

Cómo detectarlo. Como con las credenciales en el código, la detección eficaz es proactiva: gitleaks/trufflehog recorriendo todo el historial (no solo HEAD) en un hook de pre-commit y en CI encuentran el secreto antes de que se propague, que es la única defensa real porque un secreto commiteado ya pudo clonarse. Si el .git está expuesto por web, la fase de descubrimiento deja peticiones a /.git/ (HEAD, /.git/config, objetos) en el log de acceso, firma que un WAF marca (ver volcado de .git). Y el uso del secreto encontrado (un token de API, una clave de servicio) se detecta en el servicio destino como un acceso anómalo con esa credencial.

Defensa. No commitear secretos nunca (usar variables de entorno, gestores de secretos, .gitignore desde el principio); si se filtra uno, rotarlo (borrarlo del historial con git filter-repo no basta: ya pudo ser clonado) y revisar accesos. Relacionado con las credenciales en el código y el volcado de .git expuesto por web.

HerramientasgitgitleaksTruffleHoggit-dumper

Máquinas donde se aplica