Bandit: nivel 11 → 12
Todas las letras del fichero están rotadas 13 posiciones. Entendemos qué es ROT13, por qué el mismo comando cifra y descifra, y lo deshacemos con tr.
En el nivel anterior la contraseña venía codificada en base64. Ahora el disfraz es todavía más antiguo: cada letra del fichero ha sido desplazada 13 posiciones en el alfabeto. Es lo que se conoce como ROT13, una variante del cifrado César, y lo vamos a deshacer con un comando que ya nos ha salido antes: tr.
Las contraseñas aparecen como
[REDACTED], siguiendo las normas de OverTheWire. También ocultamos la contraseña en ROT13, porque deshacerlo es inmediato.
Conexión al nivel 11
1
2
$ sshpass -p '[REDACTED]' ssh bandit11@bandit.labs.overthewire.org -p 2220
bandit11@bandit:~$ export TERM=xterm
El enunciado
Según el enunciado del nivel 12, la contraseña está en el fichero data.txt, donde todas las letras minúsculas y mayúsculas han sido rotadas 13 posiciones.
1
2
3
4
bandit11@bandit:~$ ls
data.txt
bandit11@bandit:~$ cat data.txt
Gur cnffjbeq vf [REDACTED]
Gur cnffjbeq vf no significa nada… hasta que aplicamos ROT13 y se convierte en The password is.
¿Qué es ROT13?
ROT13 (rotate by 13) sustituye cada letra por la que está 13 posiciones más adelante en el alfabeto inglés, volviendo al principio cuando se llega al final:
| Original | A | B | C | … | M | N | O | … | Z |
|---|---|---|---|---|---|---|---|---|---|
| ROT13 | N | O | P | … | Z | A | B | … | M |
Solo afecta a las letras: los números, espacios y símbolos se quedan igual. Y respeta mayúsculas y minúsculas: una a pasa a n y una A pasa a N.
Tiene una propiedad muy curiosa: como el alfabeto tiene 26 letras y 13 es justo la mitad, aplicar ROT13 dos veces te devuelve el texto original. Es decir, cifrar y descifrar es exactamente la misma operación.
Igual que base64, ROT13 no protege nada: no hay clave y cualquiera lo deshace en un segundo. Se usaba (y se usa) para ocultar spoilers o respuestas de acertijos, no para seguridad.
Deshacer el ROT13 con tr
1
2
bandit11@bandit:~$ cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'
The password is [REDACTED]
tr (translate) sustituye caracteres uno a uno: el primer conjunto dice qué caracteres cambiar y el segundo por cuáles. El carácter en la posición 1 del primer conjunto se cambia por el de la posición 1 del segundo, el 2 por el 2, y así sucesivamente.
Desmontemos los conjuntos:
| Primer conjunto | Se convierte en | Resultado |
|---|---|---|
A-Z (A hasta Z) | N-ZA-M (N hasta Z, y luego A hasta M) | A→N, B→O … M→Z, N→A … Z→M |
a-z (a hasta z) | n-za-m (n hasta z, y luego a hasta m) | a→n, b→o … m→z, n→a … z→m |
El truco está en N-ZA-M: son las mismas 26 letras, pero empezando por la N. Al emparejarlas posición a posición con A-Z, cada letra queda desplazada 13 sitios. Lo mismo para las minúsculas.
Ya usamos tr en el nivel 5 → 6 para limpiar la salida. Aquí vemos su uso más clásico: traducir un juego de caracteres en otro.
Quedarnos solo con la contraseña
1
2
bandit11@bandit:~$ cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m' | awk '{print $NF}'
[REDACTED]
El mismo $NF del nivel anterior: la frase vuelve a ser The password is ..., y $NF imprime el último campo.
Otras formas
1. Sin cat, pero con redirección (no como argumento)
En niveles anteriores dijimos que cat fichero | sobraba porque grep, sort o base64 aceptan el fichero como argumento. tr es la excepción: solo lee de la entrada estándar. Si intentas pasarle el fichero, falla:
1
2
3
bandit11@bandit:~$ tr 'A-Za-z' 'N-ZA-Mn-za-m' data.txt
tr: extra operand 'data.txt'
Try 'tr --help' for more information.
Así que aquí el cat sí tiene sentido. Si quieres prescindir de él, la forma correcta es la redirección de entrada <, que conecta el fichero con la stdin de tr:
1
2
bandit11@bandit:~$ tr 'A-Za-z' 'N-ZA-Mn-za-m' < data.txt
The password is [REDACTED]
Es la pareja de la redirección 2> que vimos en el nivel 6 → 7: allí mandábamos stderr a un fichero, aquí metemos un fichero por stdin.
2. Comprobar que ROT13 es su propia inversa
1
2
3
4
$ echo "hola" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
ubyn
$ echo "hola" | tr 'A-Za-z' 'N-ZA-Mn-za-m' | tr 'A-Za-z' 'N-ZA-Mn-za-m'
hola
Aplicarlo una vez lo “cifra”; aplicarlo otra vez lo deja como estaba. Por eso no existe un comando distinto para descifrar: el mismo tr sirve para las dos cosas.
3. Con Python
1
2
bandit11@bandit:~$ python3 -c "import codecs; print(codecs.decode(open('data.txt').read(), 'rot13'), end='')"
The password is [REDACTED]
Python trae ROT13 incorporado en el módulo codecs. Es más largo que tr, pero vale la pena conocerlo: en scripts de pentesting o CTF es habitual ir encadenando decodificaciones (base64, ROT13, hex…) dentro del mismo programa.
Pasar al nivel siguiente
1
2
bandit11@bandit:~$ exit
$ sshpass -p '[REDACTED]' ssh bandit12@bandit.labs.overthewire.org -p 2220
Resumen
| Comando / concepto | Para qué sirve |
|---|---|
| ROT13 | Desplazar cada letra 13 posiciones (variante del cifrado César) |
tr 'A-Za-z' 'N-ZA-Mn-za-m' | Aplicar o deshacer ROT13 (es la misma operación) |
tr conjunto1 conjunto2 | Sustituir caracteres posición a posición |
tr y ficheros | Solo lee de stdin: necesita cat o < |
comando < fichero | Redirigir un fichero a la entrada estándar |
awk '{print $NF}' | Imprimir el último campo |
codecs.decode(..., 'rot13') | ROT13 desde Python |