Entrada

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.

Bandit: nivel 18 → 19

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, como nano o less. Para leer un fichero, cat es 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: scp usa -P en mayúscula para el puerto, al revés que ssh, que usa -p en 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 / conceptoPara qué sirve
~/.bashrcScript que bash ejecuta al abrir una shell interactiva
ssh usuario@host -p 2220 comandoEjecutar un comando en el servidor sin abrir sesión interactiva
ssh ... bashShell no interactiva: sin prompt, pero ejecuta lo que escribas
ssh -tForzar la asignación de una terminal (TTY)
/bin/sh / bash --norcShells que no cargan el .bashrc
scp -P 2220 usuario@host:fichero .Copiar un fichero del servidor a tu máquina
Esta entrada está licenciada bajo CC BY 4.0 por el autor.