我是如何捡到Jetty CVE的

admin 2022年5月30日01:05:38安全文章评论9 views3436字阅读11分27秒阅读模式

前言

前段时间在分析Jetty漏洞时无意捡了个CVE,下面是当时分析该漏洞并挖掘到CVE的记录。

CVE-2021-28164

该漏洞影响9.4.37.v202102199.4.38.v20210224版本,攻击者可通过/%2e/WEB-INF/绕过WEB-INF下文件的访问限制,读取WEB-INF下的文件内容。目前该漏洞我仅在9.4.38.v20210224复现成功。

漏洞复现

首先使用IDEA创建一个maven的web项目,修改POM文件添加Jetty依赖,这个依赖使用阿里云的源是找不到的,可以修改为maven的官方源,并为maven设置socks代理来解决下载依赖的问题,下面是我的POM文件配置。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<name>jetty_CVE-2021-28169</name>
<groupId>org.example</groupId>
<artifactId>jetty_CVE-2021-28169</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.38.v20210224</version>
<configuration>
<httpConnector>
<port>8082</port>
</httpConnector>
<webApp>
<contextPath>/</contextPath>
</webApp>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
</dependencies>
</project>

加载依赖后,通过mvn jetty:run命令运行jetty,访问/%2e/WEB-INF/web.xml读取xml文件,至此漏洞复现成功。

我是如何捡到Jetty CVE的

漏洞分析

根据Jetty官网的描述,这个漏洞是由于servlet和url解析产生了不一致导致的。所以当使用/%2e进行绕过时,一定会进入到servlet,由于在Jetty中所有HTTPservlet的请求都会过javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletRespons),所以可以在该函数打断点观察程序后续的执行逻辑。

我是如何捡到Jetty CVE的    接下来会进入到org.eclipse.jetty.servlet.DefaultServlet#doGet,在该方法中又会调用org.eclipse.jetty.server.ResourceService#doGet方法。

我是如何捡到Jetty CVE的

org.eclipse.jetty.server.ResourceService#doGet中会根据传入的路径获取文件内容。

我是如何捡到Jetty CVE的

当获取的内容为目录时,则列出目录结构,所以也可以通过/%2e/WEB-INF/读取WEB-INF下的目录我是如何捡到Jetty CVE的

当正常读取到文件内容时,则将读取到的文件内容发送到客户端。

我是如何捡到Jetty CVE的

通过上面的分析,之所以能进行文件读取操作,是因为DefaultServlet的处理导致的,通过查阅文档,DefaultServlet映射路径为/,主要作用为上下文提供对静态内容的处理。所以如果程序中将其他的servlet mapping设置为/,访问/%2e/WEB-INF/web.xml将不会触发读取漏洞,因为请求不会交给DefaultServlet处理。

那么为什么直接访问/./WEB-INF/web.xml不会触发漏洞呢?

org.eclipse.jetty.server.Request#setMetaData中会对请求的URI进行解析,在这个过程中会获取URL解码后的url并通过setPathInfo进行设置。

我是如何捡到Jetty CVE的

org.eclipse.jetty.server.handler.ContextHandler#isProtectedTarget中会判断请求的路径是否以/WEB-INF开头,由于url解码后的url并不满足条件,因此绕过了此处黑名单的检测,才能顺利的执行到DefaultServlet的方法,否则会直接返回。

我是如何捡到Jetty CVE的

我是如何捡到Jetty CVE的

为什么通过/./WEB-INF/web.xml可以顺利的请求到/WEB-INF/web.xml文件呢?

这个取决于org.eclipse.jetty.server.handler.ContextHandler#getResource方法,在该方法中通过canonicalPath对路径进行处理,所有的/./都会被转换为/

我是如何捡到Jetty CVE的

除了%2e编码绕过,能否通过其他方式绕过?

在获取org.eclipse.jetty.http.HttpURI#getDecodedPath获取解码参数时,主要是通过获取_decodedPath属性的值来实现的,而这个属性在org.eclipse.jetty.http.HttpURI#parse(org.eclipse.jetty.http.HttpURI.State, java.lang.String, int, int)方法中别赋值,首先通过canonicalPath/.//../形式的url进行转换,再通过decodePath进行解码。

我是如何捡到Jetty CVE的

decodePath中还会将%u002e,%2e;;;转换为.,因此也可以使用这种方式绕过。

我是如何捡到Jetty CVE的

我们知道,这个漏洞之所以使用url编码,是为了绕过canonicalPath/./的转换,但经过我们上面的分析也可以通过/.;/WEB-INF/web.xml来绕过,那么为什么不能使用这种方式绕过呢?

首先确实可以通过/.;/来绕过canonicalPath方法,但是实际使用这种方式会爆400,这是为什么呢?

我是如何捡到Jetty CVE的

我是如何捡到Jetty CVE的

根据报错定位到org.eclipse.jetty.server.Request#setMetaData,isAmbiguous的返回结果是由_ambiguous决定的,所以要找到哪里给_ambiguous赋值。

我是如何捡到Jetty CVE的

org.eclipse.jetty.http.HttpURI#checkSegment中,当要处理的字符的前一个字符为.或者..时,会返回false,并给_ambiguous赋值。

我是如何捡到Jetty CVE的

我是如何捡到Jetty CVE的

注意代码__ambiguousSegments.put("%2e", Boolean.TRUE);,这里如果改为false,那么就无法使用/%2e/WEB-INF/web.xml来绕过。

除了读取xml文件,能否读取WEB-INF下的class或者jsp文件?

      当读取jsp文件时,并不会得到jsp文件的内容,因为HTTPServlet会将请求交给JettyJspServlet,会去解析jsp的内容,但使用这种方式也可以让我们直接去执行WEB-INF下的jsp文件。

我是如何捡到Jetty CVE的

至于class或者jar文件,可以直接读取内容,所以利用该漏洞读取源码。

我是如何捡到Jetty CVE的

漏洞修复

最后看下官方是如何修复这个漏洞,有无绕过的可能。

我是如何捡到Jetty CVE的

只有当ambiguous为true时才会执行上面的代码,但如果我们用%u002e就可以绕过该限制。

我是如何捡到Jetty CVE的

联系jetty获取CVE

我是如何捡到Jetty CVE的

总结

通过对这个漏洞的分析,一方面觉得花费时间去跟进漏洞是值得的,另外身为一个做漏洞挖掘的,深入分析漏洞的原理是必要的,这也是能挖掘到新漏洞的前提。最后总结下这个漏洞的利用

  • 目录遍历,枚举/WEB-INF下的目录结构

我是如何捡到Jetty CVE的

  • 源码读取,除了可以读取配置文件,也可以读取class文件

我是如何捡到Jetty CVE的

  • 执行/WEB-INF下的JSP文件

我是如何捡到Jetty CVE的


原文始发于微信公众号(雁行安全团队):我是如何捡到Jetty CVE的

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月30日01:05:38
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  我是如何捡到Jetty CVE的 http://cn-sec.com/archives/815106.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: