Bandit: nivel 15 → 16
Cómo resolver el nivel 15 → 16 de OverTheWire Bandit enviando una contraseña a un servicio cifrado con SSL/TLS usando ncat y openssl s_client.
En el nivel anterior hablamos con un servicio de red en texto plano. Ahora el servicio es el mismo concepto, pero cifrado con SSL/TLS, y eso cambia las herramientas: nc ya no nos vale porque no sabe “hablar” TLS. Toca conocer ncat --ssl y, sobre todo, openssl s_client, una herramienta que vas a usar muchísimo en pentesting para inspeccionar servicios cifrados.
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 bandit15@bandit.labs.overthewire.org -p 2220
bandit15@bandit:~$ export TERM=xterm
Como siempre, export TERM=xterm para que la terminal remota se comporte bien con clear, colores y demás.
El enunciado
El enunciado del nivel dice que la contraseña del siguiente nivel se obtiene enviando la contraseña del nivel actual al puerto 30001 de localhost usando cifrado SSL/TLS.
Primero miro qué hay en el home:
1
2
bandit15@bandit:~$ ls
bandit15@bandit:~$
Nada. Este nivel no va de ficheros, va de red. Lo que necesito es:
- La contraseña del nivel actual (bandit15).
- Una herramienta que abra una conexión TLS contra
localhost:30001y me deje mandarle texto.
Paso 1: la contraseña del nivel actual
Las contraseñas de cada usuario están en /etc/bandit_pass/, y cada usuario solo puede leer la suya:
1
2
bandit15@bandit:~$ cat /etc/bandit_pass/bandit15
[REDACTED]
Esto solo funciona porque estoy conectado como
bandit15. Si intentas leer/etc/bandit_pass/bandit16te daráPermission denied: los permisos del fichero solo dejan leerlo a su propio usuario.
Paso 2: hablar con el servicio por TLS
¿Por qué no vale nc?
En el nivel anterior bastaba con nc localhost 30000: abríamos una conexión TCP y lo que escribíamos viajaba tal cual. Pero el servicio del puerto 30001 espera que, nada más conectar, el cliente inicie un handshake TLS: negociar versión y cifrado, recibir el certificado del servidor y acordar las claves de sesión. Solo después de eso empieza a fluir la información (ya cifrada).
El nc que hay en el servidor no sabe hacer ese handshake. Si le mandas la contraseña en texto plano, el servidor recibe bytes que no son un mensaje TLS válido y corta la conexión. Necesitamos un cliente que haga el handshake por nosotros y luego nos deje escribir como si fuera una conexión normal.
La solución: ncat --ssl
ncat es la versión moderna de netcat que viene con Nmap, y una de sus mejoras es precisamente el soporte de SSL/TLS con la opción --ssl:
1
2
3
bandit15@bandit:~$ ncat --ssl localhost 30001
[REDACTED]
[REDACTED]
La primera línea [REDACTED] es la contraseña de bandit15 que pego yo. El servidor la recibe, comprueba que es correcta y me responde con la contraseña de bandit16.
Qué está pasando por debajo:
ncatabre una conexión TCP alocalhost:30001.- Con
--sslhace el handshake TLS antes de nada. - A partir de ahí, lo que escribo por el teclado (stdin) se cifra y se envía, y lo que responde el servidor se descifra y se muestra por pantalla (stdout).
El certificado de este servicio es autofirmado.
ncat --sslno verifica el certificado por defecto, por eso conecta sin quejarse. Si quisieras exigir un certificado válido usarías--ssl-verify, y aquí fallaría. En un laboratorio da igual, pero en la vida real conectar sin verificar el certificado te expone a un ataque man-in-the-middle.
Otras formas de hacerlo
1. ncat sin pegar nada a mano
En vez de hacer cat y copiar/pegar, puedo redirigir el fichero directamente a la entrada de ncat, igual que hicimos con las redirecciones en niveles anteriores:
1
bandit15@bandit:~$ ncat --ssl localhost 30001 < /etc/bandit_pass/bandit15
O con una tubería, que hace lo mismo:
1
bandit15@bandit:~$ cat /etc/bandit_pass/bandit15 | ncat --ssl localhost 30001
Así evitas errores al copiar (un espacio de más, un salto de línea que no toca…) y la contraseña no pasa por tu portapapeles.
2. openssl s_client (la herramienta “oficial”)
openssl s_client es un cliente TLS genérico. Es lo que se usa en el mundo real para ver el certificado de un servidor, qué versiones de TLS acepta o para hablar a mano con servicios cifrados (HTTPS, SMTPS, IMAPS…).
1
bandit15@bandit:~$ openssl s_client -connect localhost:30001
Verás un montón de información: la cadena de certificados, la versión de TLS negociada, el cifrado… y un aviso de que el certificado no se ha podido verificar (es autofirmado). Después se queda esperando: pegas la contraseña, pulsas Enter y te devuelve la del nivel 16.
Pero aquí hay una trampa, y es justo la pista que da el enunciado sobre DONE, RENEGOTIATING o KEYUPDATE. En modo interactivo, s_client interpreta algunas letras al principio de una línea como comandos (sección CONNECTED COMMANDS de man s_client):
| Letra al inicio de línea | Qué hace |
|---|---|
Q | Cierra la conexión (verás DONE) |
R | Renegocia la sesión TLS (RENEGOTIATING) |
k / K | Actualiza las claves (KEYUPDATE) |
Si la contraseña que pegas empieza por una de esas letras, s_client no la envía: ejecuta el comando. La solución es desactivar esos comandos con -quiet (o -ign_eof):
1
bandit15@bandit:~$ openssl s_client -connect localhost:30001 -quiet
3. openssl en una sola línea
Combinando lo anterior con una redirección:
1
bandit15@bandit:~$ openssl s_client -connect localhost:30001 -quiet < /etc/bandit_pass/bandit15
Aquí -quiet hace dos cosas: no imprime la información del certificado y de la sesión, y activa implícitamente -ign_eof. Esto último es importante: cuando la entrada viene de un fichero o una tubería, se acaba enseguida (EOF). Sin -ign_eof, s_client cerraría la conexión en cuanto termina de leer el fichero, a veces antes de que llegue la respuesta del servidor, y no verías la contraseña. Con -ign_eof ignora ese fin de entrada y espera a que el servidor conteste.
Si te molesta el aviso del certificado que sale por la salida de errores, puedes añadir
2>/dev/nullal final para descartarlo, como hicimos confinden niveles anteriores.
Pasar al nivel siguiente
1
2
bandit15@bandit:~$ exit
$ sshpass -p '[REDACTED]' ssh bandit16@bandit.labs.overthewire.org -p 2220
Resumen
| Comando / concepto | Para qué sirve |
|---|---|
cat /etc/bandit_pass/bandit15 | Leer la contraseña del usuario actual |
| SSL/TLS | Capa de cifrado sobre TCP; requiere un handshake antes de enviar datos |
nc | Conexiones TCP en texto plano; no sirve para servicios TLS |
ncat --ssl host puerto | Netcat con soporte TLS (no verifica el certificado por defecto) |
openssl s_client -connect host:puerto | Cliente TLS genérico; muestra certificado y sesión |
-quiet / -ign_eof | Desactivan los comandos interactivos (Q, R, k, K) y evitan cerrar al llegar a EOF |
Redirección < o tubería | Enviar la contraseña sin copiar y pegar |