Lab 04: Deserialization — Pickle RCE

Objective

Craft malicious Python pickle payloads to achieve Remote Code Execution via a deserialisation vulnerability:

  1. Understand how pickle.loads() on untrusted data allows arbitrary code execution

  2. Craft a malicious pickle that runs id and returns the output in the HTTP response

  3. Read /etc/passwd and write files via serialised payloads

  4. Exploit both the session endpoint and the cache endpoint with the same technique


Background

Python's pickle module serialises Python objects to bytes. The critical danger: pickle can serialise any callable, including os.system. When the victim deserialises your data, the __reduce__ method is called — and if you control that method, you control what runs on the server.

Real-world examples:

  • 2011 Django — session data was stored as pickled bytes in cookies; if SECRET_KEY was leaked, an attacker could forge a session with arbitrary Python code. This affected millions of Django installations.

  • 2022 PyTorch (CVE-2022-45907)torch.load() uses pickle; any model file from an untrusted source could execute arbitrary code on the researcher's machine during training.

  • Apache Spark — RDD serialisation via pickle; cluster workers would execute attacker-controlled code when deserialising distributed task data.

  • Redis cached objects — many Python apps cache pickled objects in Redis; if Redis is exposed or the cache is poisoned, every worker that deserialises the object is compromised.

OWASP: A08:2021 Software and Data Integrity Failures


Architecture

Time

45 minutes


Lab Instructions

Step 1: Setup


Step 2: Launch Kali and Understand Legitimate Pickle

📸 Verified Output:


Step 3: Craft Malicious Pickle — RCE Payload

📸 Verified Output:

💡 __reduce__ is the core of pickle serialisation. When pickle encounters an object, it calls __reduce__() which should return a (callable, args) tuple telling pickle how to reconstruct the object. Pickle then stores "call callable with args". On deserialisation, it executes that call — and there's nothing stopping you from returning (os.system, ("id",)) as the "reconstruction" instructions.


Step 4: Escalate — Read Files and Write Backdoor

📸 Verified Output:


Step 5: Inspect the Pickle Opcodes


Step 6: Bypass Naive Input Validation


Step 7: Remediation Demo — Safe Alternatives


Step 8: Cleanup


Remediation

Further Reading

Last updated