Challenge sur l’exfiltration d’un fichier Docx xoré, joué pendant le CTF annuel organisé par l’ANSSI.
Énoncé
Notre SoC a détecté qu’un document confidentiel avait été exfiltré ! La méthode utilisée ne semble pas avancée et heureusement, une capture réseau a pu être faite au bon moment… Retrouvez ce document.
Découverte du pcap
Pour ce challenge on dispose d’un fichier pcap de 19 Mo.
Voici rapidement à quoi il ressemble.
À première vue, on a du DNS, du HTTP, du HTTPS : ça ressemble à une navigation web banale.
Pour y voir plus clair, on lance cette commande qui nous permet de déterminer quels protocoles sont présents dans la capture :
$ tshark -r exfiltration.pcap |awk '{print $7}' |sort -u
1
2
3
4
5
6
7
8
9
| DNS
HTTP
HTTP/XML
ICMP
OCSP
TCP
TLSv1
TLSv1.2
TLSv1.3
|
Dans un contexte d’exfiltration, les protocoles qui nous intéresseront le plus au premier regard seront DNS et ICMP.
Regardons les domaines des requêtes DNS.
$ tshark -r exfiltration.pcap -Y 'dns' -Tfields -e dns.qry.name |sort -u
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| status.geotrust.com
n5dscf.akamaiedge.net
status.geotrust.com
n1dscf.akamaiedge.net
n1dscf.akamaiedge.net
n1dscf.akamaiedge.net
n2dscf.akamaiedge.net
fastlane.rubiconproject.com
fastlane.rubiconproject.com
fastlane.rubiconproject.com
optimized-by.rubiconproject.net.akadns.net
fastlane.rubiconproject.com
optimized-by.rubiconproject.net.akadns.net
optimized-by.rubiconproject.net.akadns.net
perf-optimized-by.rubiconproject.net.akadns.net
perf-optimized-by.rubiconproject.net.akadns.net
optimized-by.rubiconproject.net.akadns.net
...
|
On en obtient un paquet, mais aucun n’est réellement suspect, ou alors il s’agit de trackers web.
On se penche donc sur l’ICMP :
$ tshark -r exfiltration.pcap -Y 'icmp'
1
2
3
4
5
6
7
8
9
10
11
12
| 5183 2019-04-29 21:18:37,434515 192.168.1.26 → 198.18.0.10 ICMP 42 Echo (ping) request id=0x0000, seq=0/0, ttl=64
5184 2019-04-29 21:18:37,438237 198.18.0.10 → 192.168.1.26 ICMP 60 Echo (ping) reply id=0x0000, seq=0/0, ttl=52
5228 2019-04-29 21:18:38,526199 192.168.1.26 → 198.18.0.10 ICMP 42 Echo (ping) request id=0x0000, seq=0/0, ttl=64
5229 2019-04-29 21:18:38,529140 198.18.0.10 → 192.168.1.26 ICMP 60 Echo (ping) reply id=0x0000, seq=0/0, ttl=52
5382 2019-04-29 21:18:39,646903 192.168.1.26 → 198.18.0.10 ICMP 81 Echo (ping) request id=0x0000, seq=0/0, ttl=64
5393 2019-04-29 21:18:39,650153 198.18.0.10 → 192.168.1.26 ICMP 81 Echo (ping) reply id=0x0000, seq=0/0, ttl=52 (request in 5382)
6265 2019-04-29 21:18:41,067100 192.168.1.26 → 198.18.0.10 ICMP 65 Echo (ping) request id=0x0000, seq=0/0, ttl=64
6266 2019-04-29 21:18:41,070125 198.18.0.10 → 192.168.1.26 ICMP 65 Echo (ping) reply id=0x0000, seq=0/0, ttl=52 (request in 6265)
6297 2019-04-29 21:18:42,159239 192.168.1.26 → 198.18.0.10 ICMP 82 Echo (ping) request id=0x0000, seq=0/0, ttl=64
6298 2019-04-29 21:18:42,162210 198.18.0.10 → 192.168.1.26 ICMP 82 Echo (ping) reply id=0x0000, seq=0/0, ttl=52 (request in 6297)
6321 2019-04-29 21:18:43,264340 192.168.1.26 → 198.18.0.10 ICMP 65 Echo (ping) request id=0x0000, seq=0/0, ttl=64
6322 2019-04-29 21:18:43,266807 198.18.0.10 → 192.168.1.26 ICMP 65 Echo (ping) reply id=0x0000, seq=0/0, ttl=52 (request in 6321)
|
Intéressant, on a très peu de paquets pour une grosse capture. Regardons les données qu’ils transportent :
$ tshark -r exfiltration.pcap -Y 'icmp && ip.src == 192.168.1.26' -Tfields -e data.data |tr -d ':' |xxd -r -p
1
2
3
4
| config : exfiltered_file_size=4193bytes
config : file_type=DOCX
config : data_len_for_each_packet=random
config : encryption=XOR
|
Ce sont nos premières infos sur l’exfiltration !
Maintenant, on sait que :
- L’exfiltration a lieu de 192.168.1.26 vers 198.18.0.10
- Le fichier transporté est un fichier Docx, transporté sur plusieurs paquets de tailles randoms
- Le Docx est xoré
Analyse de l’exfiltration
Il s’agit maintenant de déterminer comment ce fichier a été exfiltré.
Pour cela, filtrons tous les paquets à la recherche de ceux correspondant à notre IP source et notre IP destination. Dans Wireshark, on peut entrer le filtre ip.src == 192.168.1.26 && ip.dst == 198.18.0.10
On obtient la liste de paquets suivante.
Les trames HTTP POST attirent très vite notre attention, et voici ce qu’elles contiennent.
On a donc le paramètre data
, qui contient sûrement un fragment de notre fichier Docx xoré, et le paramètre uuid
, qui ne nous sert à rien.
On ressort tshark pour extraire les données des requêtes POST qui nous intéressent :
1
2
| filtre='ip.src == 192.168.1.26 && ip.dst == 198.18.0.10 && urlencoded-form'`
tshark -r exfiltration.pcap -Y "$filtre" -Tfields -e urlencoded-form.value |cut -d ',' -f 1 |tr -d '\n' |xxd -r -p > docx.xor`
|
Déchiffrement du fichier
On a maintenant récupéré notre Docx, plus qu’à la déxorer. Après quelques essais via l’uuid, on détermine que ce n’est pas la clé puisque le fichier déchiffré est illisible. On sort donc xortool
.
$ xortool -b docx.xor
Parmi les clés guess, on retrouve “ecsc”, ça sent bon. De plus, xortool essaie de déchiffrer notre fichier avec toutes les clés qu’il teste, et stocke tout ça dans un dossier xortool_out
du répertoire courant.
Nous, on veut voir s’il a réussi à trouver du fichier Word :
$ file xortool_out/* |grep -i 'word'
1
| xortool_out/000.out: Microsoft Word 2007+
|
Il nous en a sorti un !
$ libreoffice xortool_out/000.out
Flag
ECSC{v3ry_n01sy_3xf1ltr4t10n}