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 &
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:
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}