Entrada

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.

Bandit: nivel 15 → 16

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:

  1. La contraseña del nivel actual (bandit15).
  2. Una herramienta que abra una conexión TLS contra localhost:30001 y 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/bandit16 te 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:

  • ncat abre una conexión TCP a localhost:30001.
  • Con --ssl hace 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 --ssl no 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íneaQué hace
QCierra la conexión (verás DONE)
RRenegocia la sesión TLS (RENEGOTIATING)
k / KActualiza 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/null al final para descartarlo, como hicimos con find en niveles anteriores.

Pasar al nivel siguiente

1
2
bandit15@bandit:~$ exit
$ sshpass -p '[REDACTED]' ssh bandit16@bandit.labs.overthewire.org -p 2220

Resumen

Comando / conceptoPara qué sirve
cat /etc/bandit_pass/bandit15Leer la contraseña del usuario actual
SSL/TLSCapa de cifrado sobre TCP; requiere un handshake antes de enviar datos
ncConexiones TCP en texto plano; no sirve para servicios TLS
ncat --ssl host puertoNetcat con soporte TLS (no verifica el certificado por defecto)
openssl s_client -connect host:puertoCliente TLS genérico; muestra certificado y sesión
-quiet / -ign_eofDesactivan los comandos interactivos (Q, R, k, K) y evitan cerrar al llegar a EOF
Redirección < o tuberíaEnviar la contraseña sin copiar y pegar
Esta entrada está licenciada bajo CC BY 4.0 por el autor.