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.
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 configsin--globalpara 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
.gitignoreno es seguridad. Solo evita que un fichero se añada por descuido; no “protege” nada. Congit add -fse salta, y además un fichero ignorado puede estar perfectamente presente en el disco o haberse subido antes. Nunca confíes en.gitignorepara “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 / concepto | Para qué sirve |
|---|---|
.gitignore | Lista de patrones de ficheros que Git ignora (no es seguridad) |
git add -f fichero | Forzar el añadido de un fichero ignorado por .gitignore |
git config user.name/email | Configurar la identidad del autor (sin --global, solo este repo) |
git push -u origin master | Subir tus commits a la rama master del remoto |
Hook pre-receive | Script en el servidor que valida o rechaza un push |
| Push rechazado a propósito | El hook te da la contraseña pero no deja entrar tu commit |