Web ApplicationAugust 12, 2022Insecure Deserialization in Python

In this blog (part of the “Insecure Deserialization” series), we are going to discuss Insecure Deserialization in Python. We briefly discussed “What is Serialization?” and “What is Deserialization?” in our previous blog. 

Synopsis 

Python’s pickle module is used for serialization and deserialization in Python. This module serializes or deserializes Python objects only. It does not allow exchange of data between different programming languages. A key thing to note is that it’s well known for its security and interoperability issues. 

Exploitation  

For the exploitation part we are going to use OWASP SKF Lab. To set it up, we’ll need to have Docker installed on our machine. Run the following command to pull the image as shown in screenshot below. 

docker pull blabla1337/owasp-skf-lab:des-pickle-2 

Now, we’ll run a container based on the image. For that we need to run the following command: 

docker run --rm -ti -p 5000:5000 blabla1337/owasp-skf-lab:des-pickle-2 

We can access the lab via http://0.0.0.0:5000 as shown below. 

The next logical step is to intercept the requests. For this we will need a proxy tool such as Burp Suite. Make sure your browser is set up with the proxy in order to intercept the appropriate requests. Additionally, we’ll need Python3 to be installed on our system.

We’ll start by creating a new user. 

Enable the Burp Suite interceptor and sign-in using the credentials of the newly created user. Also, enable the “Remember me” checkbox while signing in. 

In the HTTP POST request, we can see the “username” and “password” parameters in the body. The “rememberme” parameter shows up in the Cookie header and its value appears to be base64 encoded. Let’s move forward for now. 

Click on the “Home” button and see where that takes us. 

In the HTTP POST request, we can see the “action” parameter in the body. The same “rememberme” field shows up in the Cookie header and its value appears to be base64 encoded. Moving forward now. 

Next, we’ll navigate to the login page and click the Submit button without any credentials and see if we can log-in to the application again. 

As can be seen above, the parameters “username” and “password” are empty. This should probably give us an active session. This is because the Cookie’s “rememberme” is set, and its value is stored in browser. 

It appears (just a wild guess) that the username and password combination (in some format) is serialized, further encoded as a base64 string, and then saved in the cookie’s “rememberme” field. The base64 value is decoded and then deserialized to obtain the username and password while logging in without credentials. We still lack one thing i.e., the application’s backend language. TL;DR we cannot construct a payload to inject in an HTTP POST request until we are certain about the serialization mechanism and until we know the backend technology stack. 

To identify the application’s technology stack, we’ll use the whatweb tool. The tool recognizes web technologies including content management systems (CMS), blogging platforms, statistic/analytics packages, JavaScript libraries, web servers, and embedded devices. A quick scan produces the following output: 

whatweb 0.0.0.0:5000 

We now know that the web application uses Python3. At this point, we’ll assume (again a wild guess) that it uses the pickle module for serialization and deserialization. 

The pickle module implements binary protocols for serializing and deserializing a Python object structure. “Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream (from a binary file or bytes-like object) is converted back into an object hierarchy. 

Now let’s take the base64 value of the “rememberme” field and paste it in the decoder tool of Burp Suite and decode the string.

The only thing remaining is to create a base64-encoded serialized string that, when decoded on the application server, triggers a remote code execution or RCE. Then we’ll simply replace the string with the “rememberme” field of the cookie in the HTTP POST request. To create the payload as a base64-encoded serialized string, we will create a small Python script. The code below must be added to a new file called payload.py. 

It’s really simple to understand this script as well. A class payload is constructed that returns a system call that simply runs netcat to connect to our host machine’s terminal session, where we will be listening on the same IP address (lhost) and Port (lport) that we will input into the script. An object “deserialpayload” is created from this class, which is serialized and stored in “serialpayload”, which is then further encoded using base64 and placed in “rememberme” and displayed. 

Now let’s run the Python script. As can be seen below we obtain a base64 encoded string (payload). 

python3 payload.py  

The LHOST value contains the host machine’s IPv4 address. Entering 192.168.0.182 as LHOST and 1337 as LPORT will cause the Docker container to search for a netcat listener. Next, we’ll run the command to launch a netcat listener on the host computer.  

nc -nvlp 1337 

Now let’s start Burp Suite again and intercept the request sent to http://0.0.0.0:5000/login and replace the value of “rememberme” with the payload string we generated above.

“Forward” the request, and observe the netcat listener. Next, try a few commands to determine if the connection works. 

We are able to successfully get a remote code execution through a deserialization vulnerability in Python.

Mitigation

User-supplied data, such as URL parameters, POST data payloads, and cookies, must always be regarded as untrusted. TL;DR because the pickle module is insecure, it should never be used to deserialize untrusted data. It doesn’t protect against erroneous or maliciously constructed data. Never unpickle data received from an unauthenticated or untrusted source. 

In this blog, we have explored Insecure Deserialization in Python. We have already discussed Insecure Deserialization in PHP. In our upcoming blogs (part of the “Insecure Deserialization” series) we will be discussing Insecure Deserialization vulnerabilities in .Net and Java. 

By partnering with Redfox Security, you’ll get the best security and technical skills required to execute an effective and thorough penetration test. Our offensive security experts have years of experience assisting organizations in protecting their digital assets through penetration testing services. To schedule a call with one of our technical specialists, call 1-800-917-0850 now.

Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. With a combination of data-driven, research-based, and manual testing methodologies, we proudly deliver robust security solutions.

“Join us on our journey of growth and development by signing up for our comprehensive courses, if you want to excel in the field of cybersecurity.”

Redfox Security Team

by Redfox Security Team

Redfox Security is a fast-growing cyber security consulting firm, spread across 4 countries. With over 10 years of global security consulting experience, we help businesses strengthen their security posture. Our mission is to help businesses grow securely with our top-line cyber security consulting services – and that’s exactly what we do.