BabyPython - "1 CAT COMPANY CTF" crypto and deserialization challenge
On the 1 CAT COMPANY CTF we didn’t manage to finalize our solution for the BabyPython challenge, created by Vahe Karapetyan, but one of our team members - Varik Matevosyan, solved it anyways after the time was up.
Below is his write-up, enjoy!
Analyzing the challenge
One of the most interesting and difficult challenges on the 1Cat CTF was the “Baby Python”. In the challenge description we find a URL and a python file to download:
|
|
Let’s first check the website. When we open the page we can see that each time it is giving us a random string. e.g.
After taking a look at the provided source code we see this a crypto challenge:
|
|
Python pickle
So the SecurePickle
class is for loading decrypted pickles and for dumping encrypted ones. As eval is evil so is the pickle. So if we will be able to pass our payload to pickle.loads
method it will execute our code.
But we have 2 problems before moving forward:
- Where is the endpoint accepting user input and passing it into the
pickle.loads
sink? - And the second one is that the strings are encrypted with CBC encryption, so we need a key to construct our payload, or do we?
The first problem was solved pretty easily, we just ran a directory fuzzer, found /loads
endpoint, then ran param miner and found out that it accepts ?obj=
query parameter. Passing any encrypted string we got previously from the request to website root http://baby.2021.ctf.cyhub.am/
, the page responds with a plaintext string test!
.
|
|
We can consider that this method decrypts the CBC message and passes it to pickle.loads
function, so this surely is the source.
Padding oracle attack
As the first problem is solved, let’s find out whether or not we can construct a payload that will be decrypted by the server. After some googling, we found out that CBC encryption is vulnerable to Padding oracle attacks if it is padded by a random IV, which is true in this case.
Here are some resources that helped us understand the attack:
- https://www.youtube.com/watch?v=aH4DENMN_O4
- https://www.youtube.com/watch?v=7XZdsR0jHjo
- https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/02-Testing_for_Padding_Oracle
TL;DR - an attacker can encrypt an arbitrary message without knowing the encryption key and that’s what we needed.
PadBuster
During further research, we also found a ready-to-go exploit by Aon’s Cyber Labs - PadBuster which is a Perl script that will automatically exploit the vulnerable server after passing some required arguments to it.
|
|
Exploit
To generate the proper payload we should dump a string with pickle and encode it with base64:
|
|
This will open a reverse shell to our remote server at 54.212.140.241
.
So the final arguments for the script will be:
|
|
After running the script and waiting about 30-40 minutes we get our encrypted message:
|
|
Now let’s set a Netcat listener at port 4444 nc -l 4444
and pass the payload to the server:
|
|
As soon as the page is opened we get our reverse shell and reading the environment variables, we find the long-awaited flag: