files running at hellothere.final2012.ghostintheshellcode.com
Summary: MITM attack
Here we have server and client source, both with bind sockets. It’s rather suspisious.
The scheme
The scheme is modified Diffie-Hellman:
We know only g and p.
r,s,t are random in each session.
h is known both to server and client.
server -> client: g^r % p, g^s % p
client -> server: (g^r)^h % p, g^t % p
server checks inputs, and generates shared key = (g^r)^h * (g^t)^s % p = g^(r*h+s*t) % p.
MITM attack
So, there are two ports: 9998 for server and 9999 for client. Let’s realize MITM attack:
- Get g^r % p, g^s % p from server, and held the connect.
- Send them both to client, and get right numbers
Now, if we send these two numbers to the server, we won’t be able to calculate the shared key – we can’t calculate g^(s*t) % p part. Let’s look into checking code:
(ans,d)=self.recv(2) if(ans==pow(entA,r,field)): #print "Authenticated" key=(entA*pow(d,s,field))%field # < - - - - - - calcIv= hashlib.sha256() calcIv.update(hex(key)) calcKey= hashlib.sha512() calcKey.update(hex(key)) enc=AES.new(calcKey.digest()[0:32],2,calcIv.digest()[:16]) self.request.sendall(enc.encrypt(winningKey)) |
We can fool the server! It only checks the first number (ans), the second (d) can be everything. Well, we can put 0 – then the key will be 0, so it will be easy to decrypt the message. Also 1 is a case (then the key is just first number from client):
SERV = sock("hellothere.final2012.ghostintheshellcode.com", 9998) CLI = sock("hellothere.final2012.ghostintheshellcode.com", 9999) gr, gs = recv(SERV, 2) send(CLI, gr, gs) ghr, gt = recv(CLI, 2) send(SERV, ghr, 0) cipher = SERV.recv(4096) key = long(0) # it will has 'long' type after computations calcIv= hashlib.sha256() calcIv.update(hex(key)) calcKey= hashlib.sha512() calcKey.update(hex(key)) enc=AES.new(calcKey.digest()[0:32],2,calcIv.digest()[:16]) print enc.decrypt(cipher) |
The flag: __It’s Better left unread__
1 comment
Awesome! But I was very close…