Web logs

Aperi'CTF 2019 - Forensic (100 pts).

Aperi’CTF 2019 - Web logs

Challenge details

Event Challenge Category Points Solves
Aperi’CTF 2019 Web logs Forensic 100 11

Web logs

Le site web de l’entreprise Foo-Bar s’est fait attaquer la semaine dernière. L’administrateur a eu le temps de lancer une capture Wireshark afin d’avoir une tracabilité des potentielles fuites de données. Investiguez et retrouver les données exfiltrées.

Challenge: dump.pcap - md5sum: c6934a72b6db09d78baf72748c6cd4a4

TL;DR

We got a pcap of a Time Based SQLi exploitation. A small python script let us recover the exfiltred data.

Methodology

Wireshark

Since the file is a pcap file, we can open it with Wireshark.

wireshark dump.pcap &

wireshark.png

We can see that we’ve got only HTTP requests, both have the same pattern:

GET /?user=Alex%22%20AND%20ASCII(SUBSTR(%09%09%09(SELECT%20passwd%20FROM%20accounts%20ORDER%20BY%20user%20LIMIT%200,1)%09%09%09,1,1))=113%20AND%20SLEEP(3)%20AND%20%221%22=%221 HTTP/1.1\r\n

Once decoded:

GET /?user=Alex" AND ASCII(SUBSTR((SELECT passwd FROM accounts ORDER BY user LIMIT 0,1),1,1))=113 AND SLEEP(3) AND "1"="1 HTTP/1.1\r\n`

Looking at the requests, we can see that the attacker is performing a time based SQL injection. ASCII() return the ascii value of a letter. SUBSTR() return a letter for a given position. Here each position is comparing to a range from 0 to 255. When a result is evaluated to true (ascii value is correct) then the response will take 3 seconde to arrive. In other word, we have to get every correct requests with 3 seconds of delay before next requests.

For example, the request number 98 is a correct one because the next one has a delay of more than 3 seconds:

3sec.png

Scripting

Time to script! We’ll do a python script to get every correct requests. Moreover, we’ll not display the whole request but only the ascii part.

from scapy.all import *

p = rdpcap("dump.pcap")
output = ''

for i in range(len(p)-1):
	if (p[i+1].time - p[i].time) > 3:  # more than 3 secondes between current and following packet
		rep = str(p[i][Raw])  # Get Request
		rep = int(rep.split("%20AND%20SLEEP(3)")[0].split("=")[-1])  # Get ASCII value
		if rep != 0:
			output += chr(rep)  # append ASCII value as char
		elif output[-1] != '\n':  # line break between values
			output += '\n'
print(output)

Ouput:

accounts
user
passwd
Administrator
Alex
Baptiste
APRK{SqLi_LoGs_ArE_s0_b1g_x1y2z3}
Zeeck4
Cre4sed
sqli

Flag

APRK{SqLi_LoGs_ArE_s0_b1g_x1y2z3}

Zeecka