0x00 前言
前段时间Vulhub更新了Jetty相关的漏洞环境,之前没搞过,这次就学习学习。
0x01 漏洞原理
Jetty 9.4.37引入对RFC3986的新实现,而URL编码的
.
字符被排除在URI规范之外,这个行为在RFC中是正确的,但在servlet的实现中导致攻击者可以通过%2e
来绕过限制,下载WEB-INF目录下的任意文件,导致敏感信息泄露。该漏洞在9.4.39中修复。
实际测试中发现,是能同时绕过限制来下载WEB-INF和META-INF两个目录下的任意文件的(前提是存在该目录)。
0x02 影响版本
-
9.4.37.v20210219
-
9.4.38.v20210224
0x03 环境搭建
参考Vulhub:https://github.com/vulhub/vulhub/tree/master/jetty/CVE-2021-28164
0x04 漏洞复现
正常访问页面如下:
尝试访问/WEB-INF/web.xml
,返回404:
在Web路径前面添加URL编码的./
即可权限绕过查看到web.xml的敏感信息:
/%2e/WEB-INF/web.xml
../
是可以的:
/noexist/%2e%2e/WEB-INF/web.xml
0x05 调试分析
在运行Jetty的命令中添加IDEA中远程调试的参数然后IDEA连接即可:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar start.jar
下面看下一些关键点即可。
场景一:访问/WEB-INF/web.xml
在该漏洞版本中,可以看到Jetty Server在初始化HttpConnection类时,会将HTTP解析器遵从的是RFC7230_LEGACY:
往下调试,HttpURI类的parse()函数在处理URL路径时,在识别到;?#/
等字符时会有一个检测URI的函数checkSegment()来对URI中是否存在..;
、%2e
、%2e%2e
等特殊字符进行检测:
接着在Request类的setMetaData()函数是设置请求相关的方法类型、URI和请求路径信息等,其中会判断该URI是否存在上述的特殊字符,这里没有就跳过其中的代码逻辑:
设置完请求各项内容之后,往下就会调用到HTTPChannel中的action——Dispatch分发请求:
往下会看到会调用isProtectedTarget()函数检测URL路径是否为保护路径,是的话则直接将响应设置为404:
跟进isProtectedTarget()函数,这里保护目标含有/web-inf
且忽略大小写和URL路径进行比较,我们访问的路径刚好匹配因此返回true:
再往后,就是返回404响应然后结束整个请求响应处理的过程了。
场景二:访问/%2e/WEB-INF/web.xml
直接调试到checkSegment()函数中,识别到%2e
并标记了出来:
往下,在Request类的setMetaData()函数中进入了hasAmbiguousSegment()判断为真的逻辑中,其中compliance就是RFC7230_LEGACY、其中的sections并不包含NO_AMBIGUOUS_PATH_SEGMENTS这一项,因此直接放行往下执行进行path的URL解码然后设置到PathInfo中:
由于path以/./
开头,绕过了isProtectedTarget()函数的检测,从而导致继续往下正常处理请求返回内容:
往下就是chain.doFilter()调用拦截器,然后就是doGet()发送请求获取响应内容回来:
OK,至此我们已经发现漏洞产生的根源所在就是Jetty遵循的RFC7230_LEGACY没有包含NO_AMBIGUOUS_PATH_SEGMENTS即RFC3986、从而并没有对识别到的%2e
进行处理。
我们看到NO_AMBIGUOUS_PATH_SEGMENTS中链接的RFC3986的URL,其中就说到了会把URI路径中的.
和..
删除掉的操作:https://datatracker.ietf.org/doc/html/rfc3986#section-3.3
The path segments "." and "..", also known as dot-segments, aredefined for relative reference within the path name hierarchy. Theyare intended for use at the beginning of a relative-path reference(Section 4.2) to indicate relative position within the hierarchicaltree of names. This is similar to their role within some operatingsystems' file directory structures to indicate the current directoryand parent directory, respectively. However, unlike in a filesystem, these dot-segments are only interpreted within the URI pathhierarchy and are removed as part of the resolution process (Section5.2).
0x06 补丁分析
这里简单看下9.4.40版本的代码修复情况。
在RFC7230_LEGACY的sections中,添加了NO_AMBIGUOUS_PATH_PARAMETERS:
接着在判断存在歧义字符的为true之后的那段代码逻辑中,由于URI没有歧义参数因此没法直接进入第三个判断条件逻辑直接报错,而是继续往下执行:
接着就判断URI存在歧义字符的话就直接调用URIUtil.canonicalPath()函数进行URI规范化处理,其是专门处理.
和..
字符的,从而杜绝了该漏洞:
0x07 防御方法
-
升级到9.4.39及以上版本;
-
或者更新
start.d/http.ini
包含以下内容来启用HttpCompliance模式RFC7230_NO_AMBIGUOUS_URIS:
ajetty.http.compliance=RFC7230_NO_AMBIGUOUS_URIS
0x08 参考
https://github.com/eclipse/jetty.project/security/advisories/GHSA-v7ff-8wcx-gmc5
原文始发于微信公众号(98KSec):浅析Jetty URI路径限制绕过漏洞(CVE-2021-28164)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论