This is a writeup on Level 4 of InfoSecInstitute’s CTF challenge.
As discussed in Level 2, we begin with a general survey of the page. After checking over the page and not finding anything that stood out, I began inspecting the HTTP headers. (The hint, after all, is “HTTP stands for Hypertext transfer protocol”.)
The response looks about the same, with the exception of an additional cookie that wasn’t present before:
Note: If you’ve been browsing around their site, and came across this level before, the cookie WILL be set on all headers, since it’s set for all pages on the domain ctf.infosecinstitute.com. You can see this for yourself by looking at the cookie file. (In Chrome, visit chrome://settings/cookies)
Since this is clearly encoded, encrypted, or otherwise obfuscated, I made a few (correct) assumptions to find a starting point.
- A low level (Level 4) challenge would use a classical cipher, rather than true symmetric/asymmetric encryption (ala PGP/AES)
- A digraph (“bb”) and two groupings ending with “v(r)f” indicate to me that it’s likely a monoalphabetic substitution cipher.
Note that these assumptions come from having a bit of experience with cryptography, and are simply a starting point. Since we have a short ciphertext, it’s difficult to be sure about anything until we actually attempt decryption. While it could possibly be a Vignere, Playfair, or something more complex, starting off with a simple monoalphabetic substitution cipher seemed like the best bet.
The most well-known of all the classical ciphers is probably the Caesar Shift cipher (or ROT-13). I don’t think I’ve ever met anyone who wasn’t familiar with it, but it’s not a question I typically ask. To be precise, the Casear cipher is a specific key setting for a shift cipher, in which the letters of the alphabet are ROTated by a certain number. The ROT-13 cipher rotates the alphabet by 13 characters, resulting in the following shift:
To solve, simply decode the value of the cookie. (Note that the ‘=’ sign is not part of the allowed message space, so the values will have to be decoded separately.)
If it wasn’t a key of 13, we could try each possible combination, looking for (hopefully English) text that makes sense. This is known as a brute-force attack, and would be the next logical step before moving on to additional cipher types. In fact, if you used an online tool or other program to solve it, it likely worked by generating each of the 26 possible decryptions, then checking which one(s) had one (or both) of the following:
- A character frequency distribution approaching that of the expected plaintext language.
- Common words in the expected plaintext language
Method 1 is the most accurate, given “enough” ciphertext. It’s a statistical comparison between how often certain letters appear in a language, and how often they appear in the ciphertext. When the ciphertext is short, however, this method can fail since there’s not enough data to accurately compare it.
The second method is especially useful in situations like this, where we know some of the plaintext (the words “infosec” and “flag”). In fact, this makes it easier to write the script on-the-fly if you’re not familiar with calculating frequency distributions, or are otherwise “not a math person”. By scanning each decrypted (deciphered) set of characters for these words, we can rapidly narrow down our search for the correct cipher and key. (I wouldn’t waste time searching for “is”, because it’s too short to be significant.)
And, of course, the mandatory Python script:
Which resulted in the following output: