Bandit: nivel 18 → 19
Cómo resolver el nivel 18 → 19 de OverTheWire Bandit cuando un .bashrc modificado te expulsa al entrar por SSH, ejecutando comandos remotos sin abrir una shell interactiva.
Este nivel tiene truco: tenemos la contraseña correcta, pero en cuanto entramos por SSH nos echan. Alguien ha tocado el .bashrc del usuario para cerrar la sesión nada más empezar. La clave está en entender cuándo se ejecuta el .bashrc y cómo usar SSH para lanzar comandos sin abrir una sesión interactiva.
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ú.
El enunciado
El enunciado del nivel dice que la contraseña del siguiente nivel está en un fichero readme en el home, pero que alguien ha modificado el .bashrc para cerrar la sesión en cuanto te conectas por SSH.
Ya lo avisábamos al final del nivel anterior.
Primer intento: conectarse como siempre
1
$ sshpass -p '[REDACTED]' ssh bandit18@bandit.labs.overthewire.org -p 2220
La autenticación funciona, sale el banner de bienvenida de OverTheWire… y justo después la conexión se cierra. No llegamos a ver el prompt bandit18@bandit:~$, así que ni siquiera da tiempo a hacer el export TERM=xterm de siempre.
¿Por qué? Cuando entras por SSH de la forma normal, el servidor te abre una shell interactiva de bash, y bash, al arrancar una shell interactiva, ejecuta el fichero ~/.bashrc. Si en ese fichero alguien ha puesto un exit, la shell se cierra nada más abrirse, y con ella tu conexión.
La solución: pasarle un comando a SSH
ssh no solo sirve para abrir una sesión: si después del destino escribes un comando, lo ejecuta en el servidor y se desconecta, sin abrir una shell interactiva. Así que le pido que ejecute bash:
1
$ sshpass -p '[REDACTED]' ssh bandit18@bandit.labs.overthewire.org -p 2220 bash
Esta vez no me echa. Eso sí, la pantalla se queda “en blanco”: no hay prompt. Pero la shell está ahí escuchando, y si escribo comandos, los ejecuta:
1
2
3
4
ls
readme
cat readme
[REDACTED]
Y ya tenemos la contraseña de bandit19.
¿Por qué funciona? Cuando SSH ejecuta un comando, no te asigna una terminal (TTY) y el bash que lanzamos arranca como shell no interactiva: lee lo que le escribes por la entrada estándar y lo ejecuta, sin prompt y sin colores. Y las shells no interactivas no ejecutan el ~/.bashrc (el .bashrc de Ubuntu, además, empieza con una comprobación que sale de inmediato si la shell no es interactiva). Resultado: el exit trampa nunca llega a ejecutarse.
En esta “shell sin prompt” no tiene sentido
export TERM=xterm: no hay terminal que configurar. Tampoco funcionarán bien programas que necesiten una pantalla completa, comonanooless. Para leer un fichero,cates más que suficiente.
Otras formas de hacerlo
1. Ejecutar directamente el comando que necesitas
Si ya sabes qué quieres hacer, no hace falta abrir ninguna shell: le pasas el comando a SSH y te devuelve la salida.
1
2
$ sshpass -p '[REDACTED]' ssh bandit18@bandit.labs.overthewire.org -p 2220 cat readme
[REDACTED]
Incluso puedes encadenar varios entre comillas para que se ejecuten todos en el servidor:
1
$ sshpass -p '[REDACTED]' ssh bandit18@bandit.labs.overthewire.org -p 2220 'ls -la; cat readme'
Con ls -la verás también el .bashrc. Si haces cat .bashrc por este mismo método, puedes encontrar la línea que te echa al final del fichero. Es la forma de ver la trampa con tus propios ojos.
2. Una shell interactiva de verdad, sin .bashrc
Si quieres un prompt normal, puedes forzar a SSH a asignar una terminal con -t y pedirle una shell que no cargue el .bashrc:
1
2
3
$ sshpass -p '[REDACTED]' ssh -t bandit18@bandit.labs.overthewire.org -p 2220 /bin/sh
$ cat readme
[REDACTED]
/bin/sh es una shell distinta a bash y no lee ~/.bashrc, así que no se activa la trampa. Con -t además tienes TTY, así que ves un prompt (más sencillo, solo $). La misma idea con bash:
1
$ sshpass -p '[REDACTED]' ssh -t bandit18@bandit.labs.overthewire.org -p 2220 bash --norc
--norc le dice a bash, literalmente, que no cargue el .bashrc.
3. Traerte el fichero con scp
scp copia ficheros por SSH, y como no abre ninguna shell interactiva, el .bashrc no le afecta. Puedes copiar el readme a tu máquina y leerlo allí:
1
2
3
$ sshpass -p '[REDACTED]' scp -P 2220 bandit18@bandit.labs.overthewire.org:readme .
$ cat readme
[REDACTED]
Ojo:
scpusa-Pen mayúscula para el puerto, al revés quessh, que usa-pen minúscula. Es un fallo muy típico.
Pasar al nivel siguiente
Ya fuera de bandit18 (con el método de la shell sin prompt, basta con exit o Ctrl+D), entro en el siguiente nivel:
1
$ sshpass -p '[REDACTED]' ssh bandit19@bandit.labs.overthewire.org -p 2220
El siguiente nivel introduce un concepto muy importante para la escalada de privilegios: los binarios setuid, programas que se ejecutan con los permisos de su propietario en lugar de los tuyos.
Resumen
| Comando / concepto | Para qué sirve |
|---|---|
~/.bashrc | Script que bash ejecuta al abrir una shell interactiva |
ssh usuario@host -p 2220 comando | Ejecutar un comando en el servidor sin abrir sesión interactiva |
ssh ... bash | Shell no interactiva: sin prompt, pero ejecuta lo que escribas |
ssh -t | Forzar la asignación de una terminal (TTY) |
/bin/sh / bash --norc | Shells que no cargan el .bashrc |
scp -P 2220 usuario@host:fichero . | Copiar un fichero del servidor a tu máquina |