Spiderlabs CTF (Blackhat US 2020)

Goal of this page

I ended up 28th/189+ in this 48h CTF event that took place on Friday, August 7th 2020 3AM French time up to Sunday, August 9th 2020 3AM French time.

About 1200 people registered, 500 teams got created, and 189 of them got at least 1 flag.

These tiles sum up some flags I caught during the SpiderLabs (Trustwave company) CTF (Capture the flag) event. A CTF is a competition where you have computer security-related challenges to solve.
My goal in this article is to have a written note of hacking methods that work on this challenge, and that might work some day in the future in any other challenge / in real life.
So it's quite a personal goal, but I hope you'll find some hints that would apply to you too.

Caught Flags

For your eyes only

The goal here is to get the URL of a remote JS file, by passing some complex if conditions in an obfuscated javascript (it's the first flag I caught btw!)

  1. Look at the network payload of the page (in browser's console or with curl) and see some obfuscated javascript (could also be seen in browser by blocking JS with uBlock)
  2. Deobfuscate the javascript (using online tools, some are better than others)
  3. Put the deobfuscated code into a local html page, so you can easily run and debug it in the browser
  4. Open the page in the browser, look at the conditions to pass. Replace the variables occurences with constants holding the proper values (because variables are read-only). For localStorage part, you may also use localStorage.setItem()
  5. You now get a new script tag inserted in your local HTML page , so just open its URL to get the flag

It's often useless to reverse engineer algorithms in CTF: the most efficent way is to simply replace variable occurences with a constant holding the expected value, which is easy to find when running in debug mode or using console.log(UDmfb[ghsgb](wNDhb, YOGhb))

Keypad.exe

For unknown reasons (obfuscation?) the keypad.exe program of this flag was considered as a "Trojan" by VirusTotal. And running it on a CIRT-monitored computer (work computer) might raise a red flag.
This got me quarantined for no valid reason from my workplace's network :)

  1. Download the keypad.exe program of this challenge, and see it's using .NET Framework
  2. Get dnSpy (the right version, aka 32 bits not 64 bits :) ), install it on windows (might be airgapped like mine) and decompile le program
  3. First flag is easy to get: just make the "Flag" button enabled
  4. I'm unsure how to get the second flag, so I went for brute-forcing it, but got too many valid pin codes out of this… So this is what I started, but in the end, I used the 3rd flag to get the 2nd one easily
    1. Use a System print to show the string that the keypad generated when pressing buttons (it's like a button1button3button24button5 string)
    2. Insert a brute forcing code in the program that iterates over all combinations of buttons and add a System print to show the matching pins and flag
    3. Try every flag?!
  5. The third (and last) flag involves decyphering an AES base64ed message, knowing both key (AAAABBBBCCCCDDDD)and IV (IVIVIVIVIVIVIVIV).
    1. Find the encrypting algorithm (AES) IV and key in the decompiled code
    2. Use online tool (or whatever) to decrypt the base64 encoded string in the "if"
    3. Congratulation, you have the full pin code (and part of flag 2) and so the third flag is yours

You may override the string button2button6… value with the one you know from decrypting the AES string, rather than entering the pin code manually. Same for the 2nd pin code, which is a sub part of the 3rd pin code (because pins are entered one after the other without a reset)

Malcolm

I tried to find the original seed of the random generator, and guess its time() value, but I couldn't make it computable work within the 48H.

As seen in the python script used to create the ciphered string, this flag involves a double-encryption algorithm with a (partially) known plain text and a short key. So it's vulnerable to meet-in-the-middle attack.

We only know part of the plain text (the begining Well done! your flag is…) so the meet-in-the-middle will require a partial match, not an exact one.

  1. Make a first python script that ciphers the plain text Well done! your flag is: <redacted> with all possible keys for key1 (0x000000 — 0xFFFFFF) and save the key1_candidate : ciphered1_hexa pair to a keys1.txt file
  2. Make a second python script that deciphers the 1ae4c56852fde8ca7ec9823587550aa2be3c839caa0a565c6a299e7a5e2cc9998302960abc778ba3ee3c8ad0518b1edae12e4a387fbfcfa25e7b0e249a17ff61 hex string (decode('hex') it first!) with all possible keys for key2 (0x000000 — 0xFFFFFF) and save the key2_candidate : deciphered2_hexa pair to a keys2.txt file
  3. Find a partial match between the ciphered1_hexa and deciphered2_hexa, so you have the key1,key2 pair
  4. Make a last python script that decrypts the ciphered 1ae4c… string with the found keys
# Bruteforce the keys independently python2.7 key1-iterator.py > keys1.txt python2.7 key2-iterator.py > keys2.txt # We only know the begining of the plain text for the ciphered string # So extract the begining of the cipher1/decipher2 # and merge them in a single file to find duplicates cut -c 36-52 keys1.txt > cut.txt cut -c 36-52 keys2.txt >> cut.txt # Sort all the beginings of the cipher1/decipher2 sort cut.txt > sorted.txt # Find duplicated beginings uniq -d sorted.txt > 629ebe03d08600144 # Find this begining in the key files, to grabs the corresponding keys grep 629ebe03d08600144 keys1.txt > da0cd400000000000000000000000000 : 629ebe03d08600144418b6957f4487eee4d8ef1d7fd43085c925bf39a10a6263619de69148b350f114ebea692b980d8e grep 629ebe03d08600144 keys2.txt > b56fee00000000000000000000000000 : 629ebe03d08600144418b6957f4487ee358c40200d87d0809485c0df8fe44086329a4b420283c0484bf375be87f6dbc7993e24f5fd597ada760314f310416945 # Now, decipher the flag python2.7 unmalcolm.py > Well done! your flag is: FLAG-dcab2ae52644a3563fd7daa4adbba3d6 # Tada!
Bash commands used for this flag

It requires a team

Use wireshark to read the pcap file (zipped), grab a zip file from it (it's an SMB conversation between two computers), extract it and see it's a reg file for TeamViewer. The TeamViewer ID 250518223 is in the SMB conversation.

This means you need a windows platform with network to install team view on it, load the reg file, and access the other computer. I don't have such windows-with-network setup, so I left this flag away.

OSINT and Cortex

The OSINT flags were mainly found by Murthy, using Trustwave's twitter and google.
Cortex flags are simple clic-clic searchings in their interface.
See this write-up for more infos on these flags. https://fantafour-haojun.github.io/CTF_Writeup/Spiderlabs_CTF_2020/ is now a dead link.

Remainings

SSO

I got stuck on this one. The only thing I got is that the token is a hex encoded query string, like user=guest×tamp=123456789 and according to the message, the user should be switched to admin, but I couldn't find the secret used for the hashmac (which I suspect is a sha1).
I tried a length extension attack, thinking it's a "fake hmac" like being actually just a sha1, but I couldn't make it work either.

This flag remains unresolved to me.

IoT

In this one, you need to find the "password for a device". Trying some %s%p%x password yeilds strange results, making me think it's a string expansion exploit (aka sprintf(user_defined_value)) but I couldn't manage to exploit it.
I guess you either need to make it an information leak, to read the memory containing the password or the flag. A stack-rewrite (making the program return to somewhere else) seems way harder, because I don't know where to go.

This flag remains unresolved to me.

Social Network

It seems this one has different behavior based on the content of the input fields, leading to a probable SQL injection. I couldn't make it work before the CTF ended.

This flag remains unresolved to me.

Local configuration

This one seems like a command line injection, since using bash-like commands as the host or user lead to different output (say, -v%20hostname makes the page show the verbose output of SSH). I don't know how it was supposed to be exploited.

This flag remains unresolved to me.

Conclusion, and lessons learnt