Aperi’CTF 2019 - Web logs
Détails du challenge
| Event | Challenge | Category | Points | Solves |
|---|---|---|---|---|
| Aperi’CTF 2019 | Web logs | Forensique | 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
Nous avons obtenu un pcap d’une exploitation de SQLi Time Based. Un petit script python nous a permis de récupérer les données exfiltrées.
Méthodologie
Wireshark
Le fichier étant un fichier pcap, nous pouvons l’ouvrir avec Wireshark.
wireshark dump.pcap &

On peut voir que nous n’avons que des requêtes HTTP, toutes deux ayant le même 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
Une fois décodée :
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`
En regardant les requêtes, on peut voir que l’attaquant réalise une SQL injection time based. ASCII() renvoie la valeur ascii d’une lettre. SUBSTR() renvoie une lettre pour une position donnée. Ici, chaque position est comparée à une plage allant de 0 à 255. Lorsqu’un résultat est évalué à vrai (la valeur ascii est correcte), alors la réponse mettra 3 secondes à arriver. En d’autres termes, nous devons récupérer toutes les requêtes correctes ayant un délai de 3 secondes avant la requête suivante.
Par exemple, la requête numéro 98 est une requête correcte car la suivante a un délai de plus de 3 secondes :

Scripting
Passons au script ! Nous allons faire un script python pour récupérer toutes les requêtes correctes. De plus, nous n’afficherons pas la requête entière mais uniquement la partie ascii.
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)
Sortie :
accounts
user
passwd
Administrator
Alex
Baptiste
APRK{SqLi_LoGs_ArE_s0_b1g_x1y2z3}
Zeeck4
Cre4sed
sqli
Flag
APRK{SqLi_LoGs_ArE_s0_b1g_x1y2z3}