Bandit: nivel 22 → 23
Cómo resolver el nivel 22 → 23 de OverTheWire Bandit leyendo un script de cron que calcula el nombre del fichero con md5sum, y reproduciendo ese cálculo a mano.
Seguimos con cron, pero esta vez el fichero donde cae la contraseña no está a la vista: su nombre lo calcula el propio script. Para resolverlo hay que leer el script, entender cómo genera ese nombre y reproducir el mismo cálculo nosotros a mano. Es un salto importante: pasamos de “leer lo que hay” a “razonar qué va a hacer un programa”.
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ú.
Conexión
1
2
$ sshpass -p '[REDACTED]' ssh bandit22@bandit.labs.overthewire.org -p 2220
bandit22@bandit:~$ export TERM=xterm
El enunciado
El enunciado del nivel nos avisa de que es parecido al anterior y nos vuelve a mandar a /etc/cron.d/. La configuración repite el patrón:
1
2
3
bandit22@bandit:~$ cat /etc/cron.d/cronjob_bandit23
@reboot bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
Igual que en el nivel 21 → 22: una tarea que corre como bandit23 cada minuto, ejecuta un script y manda toda la salida a /dev/null. La diferencia está en el script.
Leer el script
1
2
3
4
5
6
7
8
9
bandit22@bandit:~$ cat /usr/bin/cronjob_bandit23.sh
#!/bin/bash
myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)
echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"
cat /etc/bandit_pass/$myname > /tmp/$mytarget
Vamos línea a línea, porque toda la gracia está aquí:
myname=$(whoami): guarda en la variablemynameel nombre del usuario que ejecuta el script. Como el cron lo lanza como bandit23, aquímynamevalebandit23(¡no bandit22!).mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1): esta es la clave. Calcula el nombre del fichero destino así:echo I am user $mynameproduce el textoI am user bandit23.| md5sumcalcula el hash MD5 de ese texto.md5sumdevuelve el hash seguido de un guion (hash -).| cut -d ' ' -f 1corta esa salida usando el espacio como separador (-d ' ') y se queda con el primer campo (-f 1), es decir, solo el hash, sin el ` -` del final.
cat /etc/bandit_pass/$myname > /tmp/$mytarget: vuelca la contraseña de bandit23 en/tmp/<hash>.
En resumen: la contraseña de bandit23 está en un fichero de /tmp cuyo nombre es el MD5 del texto I am user bandit23. El detalle que engaña: el nombre se calcula con whoami, que es bandit23 cuando lo ejecuta el cron, no el usuario que somos ahora.
Un MD5 es una función de hash: convierte cualquier texto en una cadena de longitud fija, y para la misma entrada da siempre la misma salida. Por eso podemos reproducir el cálculo: si usamos exactamente el mismo texto, obtenemos exactamente el mismo nombre de fichero que generó el script.
La solución: reproducir el cálculo
Calculo yo mismo el hash, usando el nombre del usuario objetivo (bandit23):
1
2
bandit22@bandit:~$ echo I am user bandit23 | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349
Y ahora leo el fichero de /tmp con ese nombre:
1
2
bandit22@bandit:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
[REDACTED]
Ahí está la contraseña de bandit23.
Cuidado con las comillas y los espacios: el texto tiene que ser exactamente
I am user bandit23. Un espacio de más, o ponerbandit22por costumbre, da un hash distinto y, por tanto, un fichero que no existe. El hash es determinista, así que o lo clavas o no sale.
Otra forma: ejecutar el propio script… pero no
La tentación es ejecutar el script directamente para que haga el trabajo. No funciona como esperas: si tú (bandit22) lo ejecutas, whoami devuelve bandit22, intentará leer /etc/bandit_pass/bandit22 (que sí puedes leer, es el tuyo) y lo escribirá en el /tmp correspondiente a bandit22. No te da la contraseña de bandit23. La contraseña de bandit23 solo la puede escribir alguien que sea bandit23, y eso es justo lo que hace el cron por nosotros. Por eso la vía correcta es dejar que el cron haga su trabajo y nosotros recalcular el nombre para leer su resultado.
Pasar al nivel siguiente
1
2
bandit22@bandit:~$ exit
$ sshpass -p '[REDACTED]' ssh bandit23@bandit.labs.overthewire.org -p 2220
El siguiente nivel es el que anticipábamos: un cron que ejecuta un script en un directorio donde tú puedes escribir. Ahí ya no lees, sino que colocas tu propio script para que lo ejecute bandit24.
Resumen
| Comando / concepto | Para qué sirve |
|---|---|
$(comando) | Sustitución de comandos: guardar la salida en una variable |
whoami | Mostrar el usuario actual (aquí, el que ejecuta el cron) |
md5sum | Calcular el hash MD5 de una entrada |
cut -d ' ' -f 1 | Quedarse con el primer campo, separando por espacios |
| Hash determinista | La misma entrada da siempre el mismo hash: se puede reproducir |
cat /etc/bandit_pass/$myname > /tmp/$mytarget | Volcar la contraseña en un fichero de nombre calculado |