Entrada

Bandit: nivel 31 → 32

Cómo resolver el nivel 31 → 32 de OverTheWire Bandit haciendo un push a un repositorio Git, saltándose un .gitignore con git add -f y configurando la identidad del autor.

Bandit: nivel 31 → 32

Hasta ahora, con Git, solo leíamos repositorios. Este nivel le da la vuelta: tenemos que escribir en uno, haciendo un push. Y por el camino nos topamos con dos obstáculos muy reales: un .gitignore que intenta impedir que subamos el fichero, y la configuración de identidad que Git exige para poder commitear.

Las contraseñas de los niveles aparecen como [REDACTED]. Siguiendo las normas de OverTheWire, no publico credenciales: la gracia es que llegues a ellas tú.

Clonar el repo (desde tu máquina)

Como siempre, desde tu máquina local. La credencial de bandit31-git es la contraseña de bandit31.

1
2
3
4
$ cd $(mktemp -d)
$ git clone ssh://bandit31-git@bandit.labs.overthewire.org:2220/home/bandit31-git/repo
$ cd repo
$ cat README.md
1
2
3
4
5
6
This time your task is to push a file to the remote repository.

Details:
    File name: key.txt
    Content: 'May I come in?'
    Branch: master

El enunciado es claro: hay que crear un fichero key.txt con el contenido May I come in? y subirlo (push) a la rama master.

El primer obstáculo: el .gitignore

Creo el fichero con cualquier editor (nano, vim, lo que uses):

1
$ echo 'May I come in?' > key.txt

Pero antes de añadirlo, miro bien el repo, incluidos los ficheros ocultos (-a):

1
2
3
4
5
$ ls -la
...
.gitignore
$ cat .gitignore
*.txt

Ahí está la trampa: el .gitignore contiene *.txt. Un .gitignore le dice a Git qué ficheros ignorar, es decir, que no los tenga en cuenta ni los suba. El patrón *.txt ignora todos los ficheros con extensión .txt… justo la de nuestro key.txt. Si hago un git add key.txt normal, Git lo ignora sin rechistar.

Saltarse el .gitignore: git add -f

Para forzar a Git a añadir un fichero ignorado se usa la opción -f (force):

1
$ git add -f key.txt

El -f le dice “sé que está en el .gitignore, añádelo igualmente”. Sin él, Git lo saltaría y nunca llegaría al commit.

El segundo obstáculo: la identidad del autor

Intento hacer el commit:

1
$ git commit -m "Creamos un nuevo archivo"

Y Git se niega:

1
2
3
*** Please tell me who you are.
...
fatal: unable to auto-detect email address

Git no deja commitear sin saber quién eres: cada commit lleva un autor (nombre y email). En tu máquina normal esto ya está configurado, pero en un repo recién clonado en un directorio temporal, no. Lo configuro solo para este repo (sin --global):

1
2
$ git config user.name bandit31
$ git config user.email bandit31@overthewire.org

El valor da igual, puede ser cualquier cosa; Git solo quiere que el campo no esté vacío. Uso git config sin --global para que afecte solo a este repositorio y no me toque la configuración de mi máquina.

Y ahora el commit sí pasa:

1
2
$ git add -f key.txt
$ git commit -m "Creamos un nuevo archivo"

La solución: hacer el push

Subo mi commit a la rama master del remoto:

1
$ git push -u origin master

Me pide la contraseña de bandit31-git y, tras subir los objetos, el servidor valida lo que he enviado y responde:

1
2
3
4
5
remote: ### Attempting to validate files... ####
remote: Well done! Here is the password for the next level:
remote: [REDACTED]
...
 ! [remote rejected] master -> master (pre-receive hook declined)

Ahí está la contraseña de bandit32. Fíjate en el detalle final: el push aparece como [remote rejected] / pre-receive hook declined. Eso es normal y esperado, no es un error tuyo.

¿Por qué el push se “rechaza” pero igual te da la contraseña?

El servidor tiene un hook pre-receive: un script que se ejecuta en el remoto antes de aceptar un push y que puede aceptarlo o rechazarlo. Aquí ese hook comprueba si has subido key.txt con el contenido correcto:

  • Si lo has hecho bien, te imprime la contraseña…
  • …pero luego rechaza el push de todas formas, para no modificar realmente el repositorio del juego.

Es decir, el hook te usa solo como mecanismo de validación: te premia con la contraseña pero no deja que tu commit entre en el repo. Por eso ves el mensaje de éxito (Well done!) y el rechazo (remote rejected) a la vez.

Los hooks de Git (pre-receive, pre-commit, post-receive…) son scripts que se ejecutan automáticamente en momentos concretos del ciclo de vida de Git. En el mundo real se usan para validar código, lanzar CI/CD, impedir que se suban secretos, etc. Aquí es lo que valida tu reto.

Por qué esto importa en seguridad

Dos ideas que te vas a encontrar de verdad:

  • El .gitignore no es seguridad. Solo evita que un fichero se añada por descuido; no “protege” nada. Con git add -f se salta, y además un fichero ignorado puede estar perfectamente presente en el disco o haberse subido antes. Nunca confíes en .gitignore para “ocultar” secretos.
  • Los hooks del lado servidor son una herramienta de control potente: validar lo que entra, bloquear pushes que contengan credenciales (pre-receive + un escáner de secretos), forzar políticas… Entender que el servidor puede ejecutar lógica propia al recibir un push es clave tanto para defender como para atacar.

Pasar al nivel siguiente

1
$ sshpass -p '[REDACTED]' ssh bandit32@bandit.labs.overthewire.org -p 2220

Se acabó Git. El siguiente nivel es uno de los más míticos de Bandit: te meten en una “uppercase shell” que convierte todo lo que escribes a mayúsculas. Tendrás que escapar de ella con un truco muy ingenioso.

Resumen

Comando / conceptoPara qué sirve
.gitignoreLista de patrones de ficheros que Git ignora (no es seguridad)
git add -f ficheroForzar el añadido de un fichero ignorado por .gitignore
git config user.name/emailConfigurar la identidad del autor (sin --global, solo este repo)
git push -u origin masterSubir tus commits a la rama master del remoto
Hook pre-receiveScript en el servidor que valida o rechaza un push
Push rechazado a propósitoEl hook te da la contraseña pero no deja entrar tu commit
Esta entrada está licenciada bajo CC BY 4.0 por el autor.