Worth 200 points, with the description:
We were pretty sure the service at tonnerre.pwning.xxx:8561 (source) was totally secure. But then we came across this website and now we’re having second thoughts… We think they store the service users in the same database?
The link directs to a website which has a SQLi vulnerability. Running sqlmap:
python sqlmap.py -u http://tonnerre.pwning.xxx:8560/login.php --data="password=xxx&username=" -D tonnerre -T users --dump
python sqlmap.py -u http://tonnerre.pwning.xxx:8560/login.php --data="password=xxx&username=" -D tonnerre -T admin_users --dump
we obtain the username get_flag
and a pair of values:
The following protocol is executed:
- The server asks for username and an integer
.
- Then, the server computes
for some (unknown) random value
and known generator and modulus
.
- It responds with
and
.
- The server computes
and then
.
- It then asks for a proof and checks whether
. If not, it rejects.
The first thing we note is that is not known to us, so the first thing we could try is to choose
or
. This would cause
or
, but unfortunately it is not that simple (but almost!). The protocol checks that
. So, it cannot be set to
, is that would violate the condition above. But what about
? That would work! Actually any power
is a viable solution.
This forces . OK, good, since this is a value we can determine! Using
, we may compute
, so we find the key as
. From this only, it is pretty easy. We compute the proof as in the above protocol:
and send it to the server. Performing the described steps, we find the flag:
PCTF{SrP_v1_BeSt_sRp_c0nf1rm3d}
.
The code used to get the flag is
s = socket.create_connection(('tonnerre.pwning.xxx',8561)) print '[+] Connected:', recvuntil('\n').strip('\n') # our crafted public client value public_client = (libnum.modular.invmod(verifier, N) * g**2) % N s.send('get_flag\n') s.send(tostr(public_client)) recvuntil('\n') # obtain residue value residue = int(recvuntil('\n'), 16) public_server = (residue-verifier) % N # compute session key and proof session_key = H(tostr(public_server**2 % N)) proof = H(tostr(residue) + session_key) print '[ ] Sending:', proof, '...' s.send(proof + '\n') recvuntil('\n') print '[+] Returned:', recvuntil('\n')
which gives the output: