¿Se te olvidó borrar la carpeta .git en producción?

freishner

Capo
Se incorporó
16 Noviembre 2021
Mensajes
303
Me imagino que debe ser archi recontra conocida esta pifea entre los colegas desarrolladores, pero no está demás darle un thread.

Introducción

Muchos TI conocemos la famosa carpeta .git, y si nó, pues ahora la van a conocer. Dicha carpeta almacena el repo de un proyecto GIT, comits, ramas, tags... todo queda dentro (todo lo que versionemos).

Si llegara a perderse la carpeta, el histórico del proyecto y la posibilidad del control de cambios basado en GIT se perdería, tendríamos que volver a clonar el repo. No obstante, si el proyecto excepto dicha carpeta se perdiera, podríamos restaurar todo como estaba en el último comit a excepción de los archvos que nunca se versionaron o ignoraron.

El repo no solo sirve para controlar versiones, tambien sirve para manejar actualizaciones.

Descargar el repo desde internet

Tal cual, vamos a reconstruir el repo desde la versión de producción, cualquiera que encontremos en internet, y a intentar accesar a lo que sea que encontremos dentro.

Para ésto basta con buscar en google.

Código:
intitle:"index of /.git"

1665498388301.png

El repo debería verse así:


Lo que estamos viendo es el directorio .git, faltaría descargarlo, para ello tenemos una herramienta llamada GitTools.
Luego nos posicionamos en alguna parte de nuestro equipo y clonamos el repo de GitTools.

Código:
clone https://github.com/internetwache/GitTools

Una vez clonado, veremos 3 herramientas al interior, Dumper, Extractor y Finder.
Como ya tenemos ubicado el repo, no hace falta que utilicemos Finder, tampoco Extractor, porque reconstruiremos todo con git y una terminal.

La sintaxis es sencilla:

Código:
gitdumper.sh URL-REPO CARPETA-DESTINO

El proceso puede demorar dependiendo del internet y de la cantidad de commits del repo... deberíamos ver algo como ésto:


Una vez "clonado" descargado el repo, dependiendo de la tecnología usada, podremos accesar directamente a mas recursos ahora vulnerables. Pero antes tenemos que reconstruir todo el repo, o al menos devolver lo versionado a donde estaba al último commit para mirar dentro.

Reconstruir el repo

Tenemos el repo en un directorio cualquiera, nos movemos con la terminal a dicho directorio y ejecutamos:

Código:
git status

Veremos muchos archivos eliminados:


Ahora con el comando git restore vamos a restaurar todos los archivos de la siguiente forma ayudándonos de nuestro terminal linux:

Código:
git status | grep deleted | awk '{print "git restore", $2}' > restore.txt

En el archivo "restore.txt" quedarán todos los archivos concatenados al comando git restore, haría falta copiar y pegar en la terminal dentro de la carpeta que contiene el directorio .git.

Nota:
No tendremos acceso a los archivos históricos hasta que usemos la herramienta "Extractor" que viene con GitTools.


Buscando recursos vulnerables

Una vez que tenemos el proyecto restaurado, podemos ejecutar "Extractor" si quisieramos encontrar archivos para analizar si en algún momento de la historia del proyecto se comprometieron credenciales o algún otro archivo de importancia. Por lo pronto, lo común a encontrar es el acceso a la base de datos, sistemas de cache y/o al correo. Tambien es posible analizar el código buscando vulnerabilidades.

En éste caso he encontrado el acceso a una instancia de MySQL.

Nota:

No todos los accesos son públicos, algunos están restringidos a localhost, para que solamente la app pueda accesarlos. Para comprobarlo podemos usar nmap de la siguiente forma:

Código:
nmap -p 3306 URL/IP


Como vemos el puerto 3306 correspondiente a MySQL está siendo filtrado y posiblemente no tengamos acceso. Si el recurso estuviera disponible, veríamos en ves de "filtered", "open" posibilitando el ingreso como vemo mas abajo.


Alertar del incidente

Supongamos que quisieramos alertar a alguien del incidente, si el repo no tuviera un dominio, por ende, no hubiera una entidad a quien reportar, simplemente nos iríamos a la siguiente ruta del directorio .git: logs/HEAD. En tal archivo (no siempre), podríamos visualizar los comits con sus respectivos nombre e email.

Conclusión

Borrar o restringir siempre el acceso a la carpeta .git o del repo de turno. Si no los indexa algún motor de búsqueda, lo hará algún bot. No es algo hipotético como hemos visto, es cuestión de tiempo.
 

Amenadiel

Ille qui nos omnes servabit
Fundador
OVERLORD
REPORTERO
Se incorporó
15 Enero 2004
Mensajes
18.398
No tiene nada de terrible dejar la carpeta .git en producción. Lo importante es que no sea públicamente visible. Mediante reglas en el webserver (nginx, apache) se define que esos archivos no son accesibles

NGINX:
location ~* (^|/)\. {
  return 403;
}

Otra estrategia que no es mala para proteger la carpeta .git es ponerla un directorio más arriba que el document root, de manera que no esté al mismo nivel que tu index, y obvio que tu webserver no permita navegar aguas arriba.

Ya, pero qué pasa si a alguien se le olvida poner esas regla en el webserver? Bueno, ahí será visible también el archivo .env y cuando eso pase el directorio .git será el menor de tus problemas, siempre y cuando no hayas cometido el autogol de tener credenciales versionadas, que es super común.

Cuáles son las credenciales que sí puedes tener versionadas, aunque sea una mala práctica?

Bueno, por ejemplo el api_key de cualquier servicio que igual será visible en el frontend (ej. Google Maps, Pusher) . Es tolerable porque igual las expondrás al visitante, pero es dispararse en el pie porque si tienes algunas credenciales en el .env y otras en el código, cuando haces un cambio tienes que andar buscando por texto adónde cambiarla en el código.

¿Y por qué hay un .git en producción?

De alguna manera hay que pasar cada release a producción. Yo he visto empresas donde el paso a producción es automático. Cuando hay código nuevo automáticamente el gerente le pega un cachuchazo a un weón que lo sube por SFTP y reinicia la máquina. En otras empresas no es necesario este procedimiento. El servidor es en realidad el notebook del gerente y no tiene nada de malo porque lo mantene enchufado, lo deja prendido el fin de semana y el protector de pantalla tiene password. Problema resuelto.

Pero, si la empresa es seria, el paso a producción debiera conllevar un deploy realmente automatizado, y uno de los enfoques posibles es programar un script que navegue hasta el directorio del deploy, pause la aplicación, actualice el repo, ejecute la actualización de librerías con la herramienta correspondiente (nuget, npm, composer, pip) opcionalmente ejecute el build (en algunos casos el build ya está versionado) y levante la aplicación.

Pros y Contra de echarse .git

Como dice @freishner sería más seguro borrar el directorio .git después de levantar la aplicación (o "el aplicativo" como dicen los viejos culiaos) pero esto igual tiene sus inconvenientes. Básicamente implica clonar el repo completo en cada paso a producción y dependiendo del tamaño del tepo eso puede ser fácil 10 minutos y no es hueveo. Versus 1 minuto de un git pull incremental. Alguno me dirá: "oye pero pueses usar un shallow clone y sólo traerte los últimos 5 commits". Ya, eso es cierto, pero resulta que levantaste el nuevo release y la weá tiene una pifia bloqueante. Hay que hacer rollback. ¿Borramos el .git? Chuta, todo de nuevo. ¿Hicimos un shallow clone? Entonces hay que hacer git --fetch unshallow o sea básicamente, todo de nuevo.

En resumen, aunque sí sea más seguro echarse el .git tiene sus contras dependiendo de cuánto dificulta la gestión de los pasos a producción, y puede mitigarse al 99% siguiedo buenas prácticas.

Pero la conclusión final es:

- es 100% seguro mantener el .git en producción? No.
- Si me echo el .git después de cada deploy estoy 100% protegido? No.

Aquí hay dos tipos de aplicaciones. Las que han hackeado y las que van a hackear. No hay de otras. El día que tu aplicación amerite que alguien quera entrarle, te van a entrar. Lo importante no es diseñar para que nadie nunca te entre. Eso es ingenuo. Lo importante es diseñar para que cuando te entren el daño no pueda escalar. Por ejemplo, haciendo que en tu código no haya ninguna credencial que permita escalar la profundidad del hackeo.
 
Upvote 0
Subir