Prevent Insecure Deserialization
Insecure deserialization occurs when untrusted data is used to abuse the logic of an application, inflict denial of service attacks, or execute arbitrary code. Objects can be serialized into strings and later loaded from strings, but deserialization of untrusted data can lead to remote code execution (RCE). Never deserialize data from untrusted sources. Use safer alternatives like JSON for data interchange.
Language: Python
Pickle Deserialization
Incorrect (using pickle with user input):
import pickle
from base64 import b64decode
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
user_obj = request.cookies.get('uuid')
return "Hey there! {}!".format(pickle.loads(b64decode(user_obj)))Correct (use JSON or load from trusted file):
import pickle
import json
@app.route("/ok")
def ok():
# Load from trusted local file
data = pickle.load(open('./config/settings.dat', "rb"))
# Or use JSON for untrusted data
user_data = json.loads(request.data)
return user_dataReferences:
- CWE-502: Deserialization of Untrusted Data
- Python pickle Documentation
Language: JavaScript / TypeScript
Object Deserialization
Incorrect (using insecure deserialization libraries):
var node_serialize = require("node-serialize")
module.exports.handler = function (req, res) {
var data = req.files.products.data.toString('utf8')
node_serialize.unserialize(data)
}Correct (use JSON.parse for untrusted data):
module.exports.handler = function (req, res) {
var data = req.body.toString('utf8')
var parsed = JSON.parse(data)
return parsed
}References:
- CWE-502: Deserialization of Untrusted Data
- OWASP Deserialization Cheat Sheet
Language: Java
ObjectInputStream Deserialization
Incorrect (using ObjectInputStream to deserialize untrusted data):
import java.io.InputStream;
import java.io.ObjectInputStream;
public class Deserializer {
public Object deserializeObject(InputStream receivedData) throws Exception {
ObjectInputStream in = new ObjectInputStream(receivedData);
return in.readObject();
}
}Correct (use JSON or implement input validation):
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.InputStream;
public class SafeDeserializer {
public MyClass deserialize(InputStream data) throws Exception {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(data, MyClass.class);
}
}References:
- CWE-502: Deserialization of Untrusted Data
- OWASP Deserialization of Untrusted Data
- Oracle Java Security Guidelines
Language: Ruby
Marshal/YAML Deserialization
Incorrect (using Marshal.load or YAML.load with user input):
def bad_deserialization
data = params['data']
obj = Marshal.load(data)
yaml_data = params['yaml']
config = YAML.load(yaml_data)
endCorrect (use safe options or trusted data):
def ok_deserialization
# Use YAML.safe_load for untrusted data
config = YAML.safe_load(params['yaml'])
# Load from trusted file
obj = YAML.load(File.read("config.yml"))
# Use JSON for untrusted data
data = JSON.parse(params['data'])
endReferences:
- CWE-502: Deserialization of Untrusted Data
- Ruby Security Advisory
Language: C#
BinaryFormatter Deserialization
Incorrect (using BinaryFormatter which is inherently insecure):
using System.Runtime.Serialization.Formatters.Binary;
public class InsecureDeserialization {
public void Deserialize(string data) {
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(data));
object obj = formatter.Deserialize(stream);
}
}Correct (use System.Text.Json or Newtonsoft with safe settings):
using System.Text.Json;
public class SafeDeserialization {
public MyClass Deserialize(string json) {
return JsonSerializer.Deserialize<MyClass>(json);
}
}References:
- CWE-502: Deserialization of Untrusted Data
- Microsoft BinaryFormatter Security Guide
Language: PHP
unserialize() with User Input
Incorrect (unserializing user-controlled data):
<?php
$data = $_GET["data"];
$object = unserialize($data);Correct (use JSON or hardcoded data):
<?php
// Use json_decode for untrusted data
$object = json_decode($_GET["data"], true);
// Or use unserialize only with hardcoded strings
$object = unserialize('O:1:"a":1:{s:5:"value";s:3:"100";}');References:
- CWE-502: Deserialization of Untrusted Data
- PHP unserialize() Documentation
- OWASP Insecure Deserialization
General Prevention Guidelines
- Never deserialize untrusted data - Treat all external data as potentially malicious
- Use JSON for data interchange - JSON only returns primitive types (strings, arrays, objects, numbers, null)
- Implement integrity checks - Use HMACs to sign serialized data to detect tampering
- Use allowlists for deserialization - Only allow specific, known-safe classes to be deserialized
- Avoid native serialization formats - pickle, Marshal, ObjectInputStream, BinaryFormatter are all dangerous
- Use safe YAML loaders - Always use SafeLoader or safe_load with YAML libraries
- Monitor and log deserialization - Alert on unexpected deserialization attempts
- Keep libraries updated - Apply security patches promptly
References:
- CWE-502: Deserialization of Untrusted Data
- OWASP Deserialization Cheat Sheet
- OWASP Top 10 A08:2021 - Software and Data Integrity Failures