浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

admin 2022年10月19日08:00:39评论275 views字数 2391阅读7分58秒阅读模式

0x00 前言

前段时间Vulhub更新了Jetty相关的漏洞环境,之前没搞过,这次就学习学习。

0x01 漏洞原理

Jetty Servlets中的ConcatServlet、WelcomeFilter类存在多重解码问题,当应用到这两个类之一时,攻击者就可以利用双重URL编码绕过限制来访问WEB-INF目录下的敏感文件,造成敏感信息泄露。

0x02 影响版本

  • 9.x系列 <= 9.4.40

  • 10.x系列 <= 10.0.2

  • 11.x系列 <= 11.0.2

0x03 环境搭建

参考Vulhub:https://github.com/vulhub/vulhub/tree/master/jetty/CVE-2021-28169

0x04 漏洞复现

正常访问是个Example页面:

浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

查看页面源码,其中link标签的href属性值是使用到了ConcatServlet类来优化静态文件的加载:

<link rel="stylesheet" href="/static?/css/base.css&/css/app.css">

基于这种访问方式尝试直接访问WEB-INF下的文件是会返回404的:

/static?/WEB-INF/web.xml

浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

对W进行双重URL编码则成功绕过限制访问得到敏感文件:

/static?/%2557EB-INF/web.xml

浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

这里看到确实设置了ConcatServlet类来优化静态文件加载。

针对WelcomeFilter类的测试可以参考官网GitHub的代码:https://github.com/eclipse/jetty.project/pull/6261/commits/c704b8100a1ccc36f4bb8b80a96f3375dde8d182#diff-70d52a090f69fbcbb6fb9d0899c514474c25c4ea79263f81cbf0e87e3c103bd5

0x05 调试分析

在运行Jetty的命令中添加IDEA中远程调试的参数然后IDEA连接即可:

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar start.jar

之前在关于CVE-2021-28164的文章中已经简单调试过Jetty的主要路由处理过程了,后面就只看本次漏洞的关键点。

直接在ConcatServlet类的doGet()函数中下断点。

访问/static?/WEB-INF/web.xml

在断点中看到,先获取请求查询内容即URI中?号之后/WEB-INF/web.xml,接着根据&即做参数切分,再逐个参数进行操作(URL解码和...等字符处理),最后判断处理后的path值是否以/WEB-INF//META-INF/开头,是的话直接返回404:

浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

可以看到,还想用/.//../等方式已经行不通了,但是URL解码那块代码逻辑还需要继续跟进分析。

访问/static?/%2557EB-INF/web.xml

调试到调用URIUtil.decodePath()函数进行解码的地方:

浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

调试发现只进行了一次URL解码操作:

浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

看下关键的处理逻辑,就是逐个获取请求参数的字符,当遇到%时会对其后面两位字符进行URL解码并替换结果,但是可以看到仅仅替换了一次,这就是漏洞根源:

Utf8StringBuilder builder = null;int end = offset + length;for (int i = offset; i < end; i++){    char c = path.charAt(i);    switch (c)    {        case '%':            if (builder == null)            {                builder = new Utf8StringBuilder(path.length());                builder.append(path, offset, i - offset);            }            if ((i + 2) < end)            {                char u = path.charAt(i + 1);                if (u == 'u')                {                    // TODO remove %u support in jetty-10                    // this is wrong. This is a codepoint not a char                    builder.append((char)(0xffff & TypeUtil.parseInt(path, i + 2, 4, 16)));                    i += 5;                }                else                {                    builder.append((byte)(0xff & (TypeUtil.convertHexDigit(u) * 16 + TypeUtil.convertHexDigit(path.charAt(i + 2)))));                    i += 2;                }            }            else            {                throw new IllegalArgumentException("Bad URI % encoding");            }            break;        case ';':            ...        default:            if (builder != null)                builder.append(c);            break;    }}

0x06 补丁分析

参考官方在9.4.41版本的修复commit:https://github.com/eclipse/jetty.project/pull/6261/commits/c704b8100a1ccc36f4bb8b80a96f3375dde8d182

ConcatServlet类的修复方法就是将path替换为part,即使用原始路径字符串作为分发器就会再次进行URL解码:

浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

0x07 防御方法

升级到9.4.41, 10.0.3, 11.0.3及以上版本。

0x08 参考

https://github.com/eclipse/jetty.project/security/advisories/GHSA-gwcr-j4wh-j3cq

原文始发于微信公众号(98KSec):浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月19日08:00:39
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅析Jetty Servlets URI路径限制绕过漏洞(CVE-2021-28169)https://cn-sec.com/archives/794769.html

发表评论

匿名网友 填写信息