Cracking the SECDIM S/W Challenge
My good security expert friend has recently shared this lovely puzzle that SECDIM uses for filtering out potential candidates. I couldn’t help myself but give it a shot. So, here it goes.
Intro
On their careers page, you’ll find these lovely, yet simple instructions.
Exploration
Ok. So first step is to pull down the Docker image, run it and then investigate the payload.
$ docker run -it secdim/interview:latest
That gives this lovely output:
[i] Please send your application to
Traceback (most recent call last):
File "/usr/src/app/main.py", line 22, in <module>
print(unhide(key, email))
File "/usr/src/app/main.py", line 16, in unhide
raise NotImplementedError
NotImplementedError
The exception that we get back hints that it is apparently a Python-based Docker image and exception hints that some kind of exception has occurred. Giving us the first clue NotImplementedError
- probably implying that a solution will be here. 🤔
Next; let’s override the entry point to the docker image and let’s take a peek into its content. Some experts might also hint that “unpackaging” the image would be a good idea. But since we are adventurous lets just go in…
$ docker run -it --entrypoint /bin/sh secdim/interview
/usr/src/app $ ls -l
-rw-rw-rw- 1 root root 569 Jun 27 2021 main.py
Inside the container, we’ll find this lovely main.py
Python script:
import base64
from os import getenv
def hide(key, string):
encoded_chars = []
for i in range(len(string)):
key_c = key[i % len(key)]
encoded_c = chr(ord(string[i]) + ord(key_c) % 256)
encoded_chars.append(encoded_c)
encoded_string = ''.join(encoded_chars)
return base64.b64encode(encoded_string.encode('utf-8'))
def unhide(key, string):
raise NotImplementedError
email = b"w4vCl8OSwp/CpMKNZGtnbMKhw5jCmMKVwpTCmcKdwpPCnMKkwqE="
key = getenv("KEY")
print("[i] Please send your application to ")
print(unhide(key, email))
Nice.
So apparently we have a script that has “encoded” email and some kind of KEY
is needed for ncoding and decoding. Script pulls the key-value out of the environment with the help of Python’s stdin function getenv
. Let’s see if that exists in the container…
$ docker run -it --entrypoint /usr/bin/env secdim/interview |grep -i key
KEY=c2f35b3819ae32000e9541172c7e2216
And it does…
Coding time!
Apparently the email that you need to solve this is encoded in the email
variable, and to encode/unhide it you need a “key”. We now have both. The last peace that is now missing is the implementation of the unhide function. To understand unhiding we should first look at the hiding function. There are 3 pieces to it - base64 encoding/decoding, loops and modulo 256 mathematical operations. The code loops are pretty basic and if you ever took any algebra or basic crypto class you’ll soon recognise the famous “Caesar cipher” (or Vigenère cipher). The decrypt / unhide for it is very well known.
With this function, source email and key we can now write the full solution like so:
import base64
from os import getenv
def hide(key, string):
encoded_chars = []
for i in range(len(string)):
key_c = key[i % len(key)]
encoded_c = chr(ord(string[i]) + ord(key_c) % 256)
encoded_chars.append(encoded_c)
encoded_string = ''.join(encoded_chars)
return base64.b64encode(encoded_string.encode('utf-8'))
def unhide(key, string):
chars = []
encoded_string = base64.urlsafe_b64decode(string).decode()
for i, e in enumerate(encoded_string):
key_c = key[i % len(key)]
chrc = ord(e) - ord(key_c) if ord(e) - ord(key_c) >= 0 else ord(e) - ord(key_c) + 256
c = chr(chrc)
chars.append(c)
return ''.join(chars)
# key = getenv("KEY")
key="c2f35b3819ae32000e9541172c7e2216"
email = b"w4vCl8OSwp/CpMKNZGtnbMKhw5jCmMKVwpTCmcKdwpPCnMKkwqE="
print("[i] Please send your application to ")
print(unhide(key, email))
Then you send a friendly email…
Done. ✅