Entrada

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.

Bandit: nivel 11 → 12

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:

OriginalABC…MNO…Z
ROT13NOP…ZAB…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 conjuntoSe convierte enResultado
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 / conceptoPara qué sirve
ROT13Desplazar 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 conjunto2Sustituir caracteres posición a posición
tr y ficherosSolo lee de stdin: necesita cat o <
comando < ficheroRedirigir un fichero a la entrada estándar
awk '{print $NF}'Imprimir el último campo
codecs.decode(..., 'rot13')ROT13 desde Python
Esta entrada está licenciada bajo CC BY 4.0 por el autor.