Jetty常见利用方式
Jetty
本文首发于先知社区:https://xz.aliyun.com/t/11821
Eclipse Jetty是一个Java Web 服务器和Java Servlet容器。虽然 Web 服务器通常与向人们提供文档相关联,但 Jetty 现在通常用于机器对机器的通信,通常在更大的软件框架内。Jetty 是作为Eclipse Foundation的一部分开发的免费和开源项目。Web 服务器用于Apache ActiveMQ、Alfresco、Scalatra、Apache Geronimo、Apache Maven、Apache Spark、Google App Engine、Eclipse、FUSE、iDempiere、Twitter 的 Streaming API和Zimbra。Jetty 也是Lift、Eucalyptus、OpenNMS、Red5、Hadoop和I2P等开源项目中的服务器。Jetty 支持最新的 Java Servlet API(支持JSP)以及协议HTTP/2和WebSocket。
在开始了解Jetty利用方式之前,需要了解一下关于Jetty
小知识
$JETTY_HOME
映射Jetty
分发目录即start.jar
启动目录$JETTY_BASE
包含配置文件、WEB应用。在Jetty
启动机制中,会优先高到低的顺序加载配置:- 命令行
$JETTY_BASE
目录及其文件- 使用选项指定的目录
--include-jetty-dir
及其文件 $JETTY_HOME
目录及其文件
至于演示使用的环境,除了使用vulhub外,我还自行搭建了一个简单的环境,至于如何搭建建议看官网手册。
0x0 特征
0x00 响应Server标头
发送HTTP请求时,响应包的Server标头会返回Jetty版本信息(默认返回)。
0x01 GET请求
在GET请求的URL后面添加;
(也有说是;"
,但是我复现时发现使用;
也能达到相同的目的),可以识别大部分的Jetty中间件
Jetty
服务器响应包一般都为200
,Nginx
一般为404
向Jetty
服务器请求数据中添加;test
,响应包为200
接着向Nginx
服务器请求包添加相同的数据,响应包为404
0x02 404页面
Jetty服务,默认情况下会在404页面
显示当前版本信息
0x1 WEB.xml
Web.xml
别名部署标识符文件(Deployment Descriptor file),一般来说Web.xml
文件一般都是在WEB-INF目录中。Web.xml
危害几乎都是信息泄露
,无法单独拿该漏洞做文章!
下面看一个简单的Web.xml
1 | <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" |
xml
文件根元素被命名为web-app
servlet
服务器设置servlet-name
服务器名称servlet-class
服务器类servlet-mapping
定义servlet
和URL
模式之间的映射servlet-name
该名称对应servlet-name
url-pattern
用来解析URL- 上面xml文件作用是将网址路径
/*
映射到mysite.server.ComingSoonServlet
应用类
需要注意的是。在Java Servlet Spec 3.0
后,可以不用web.xml
文件配置应用程序,可以通过Java类和注解
到达相同的目的
至于xml
其他标识符这里就不继续讲解了,有需要可以访问链接查询
0x2 CVE漏洞
0x01 Jetty WEB-INF 敏感信息泄露漏洞(CVE-2021-28164)
影响版本: 9.4.37-9.4.38
直接访问/WEB-INF/web.xml
显示404
在/WEB-INF/...
前面添加/%2e
可以绕过下载web.xml
,记住不能直接使用浏览器写入/%2e
,不然可能会因为浏览器解析问题导致失败
1 | /%2e/WEB-INF/web.xml |
0x02 Jetty 通用 Servlets 组件 ConcatServlet 信息泄露漏洞(CVE-2021-28169)
影响版本:<= 9.4.40、10.0.2、11.0.2
正常情况无法通过/static?/WEB-INF/web.xml
访问到敏感文件web.xml
将W进行双重URL编码可以绕过拦截,访问敏感文件web.xml
1 | /static?/%2557EB-INF/web.xml |
0x03 Jetty WEB-INF 敏感信息泄露漏洞(CVE-2021-34429)
影响版本:9.4.37-9.4.42, 10.0.1-10.0.5, 11.0.1-11.0.5
jetty 9.4.40虽然说修复了%2e
导致的敏感信息泄露漏洞CVE-2021-28164,但是由于修复不完善还可以使用下面三个方法绕过
- unicode形式URL编码:
/%u002e/WEB-INF/web.xml
\0
组合.
导致的绕过:/.%00/WEB-INF/web.xml
\0
组合..
导致的绕过:/a/b/..%00/WEB-INF/web.xml
访问/%u002e/WEB-INF/web.xml
绕过下载
1 | /%u002e/WEB-INF/web.xml |
0x04 CVE-2020-27223 DOS
影响版本:
Jetty 9.4.6——Jetty 9.4.36
Jetty 10.0.0
Jetty 11.0.0
在Eclipse Jetty 9.4.6.v20170531
到 9.4.36.v20210114(含)、10.0.0
和 11.0.0
中,当Jetty处理包含多个带有大量“质量”(即 q)参数的 Accept标头的请求时,由于处理这些质量值的 CPU 使用率高,服务器可能会进入拒绝服务 (DoS) 状态,从而导致处理这些质量值的CPU时间用尽数分钟。
环境搭建:
1 | git clone https://github.com/motikan2010/CVE-2020-27223 |
环境搭建好了,直接使用环境内的poc脚本
1 | ./cve-2020-27223-poc1.sh |
0x05 jetty走私(CVE-2017-7656、CVE-2017-7657、CVE-2017-7658)
影响版本:
- 9.2.x:9.2.25v20180606
- 9.3.x:9.3.24.v20180605
- 9.4.x:9.4.11.v20280605
想看详细讲解jetty
走私过程。推荐看原文:https://regilero.github.io/english/security/2019/04/24/security_jetty_http_smuggling/#toc4
环境搭建使用Dockerfile
1 | FROM jetty:9.4.9 |
运行Dockerfile
- 遇到tomcat.apache.org证书过期,可以把
sample.war
软件放到本地http
服务器下载
HTTP/0.9
1 | printf 'GET /?test=4564 HTTP/0.9\r\n'\ |
双倍内容长度
1 | printf 'GET /?test=4970 HTTP/1.1\r\n'\ |
块大小属性截断
1 | printf 'POST /?test=4975 HTTP/1.1\r\n'\ |
0x3 上下文
Jetty当没有设置根应用目录、文件时,会显示webapps
里目录信息
如果没有设置根应用程序,而是通过web.xml
映射方式提供服务,那么可以采用下面方式获取应用上下文目录
demo-simple.xml配置
1 |
|
通过浏览器访问,jetty
会正常进行工作,但是,如果我们在Host
标头中附带不属于xml Item
标签内的信息通过GET请求发送,在应用响应的结果中会显示目录上下文
信息
在xml Item
标签添加127.0.0.1
演示
无法通过添加127.0.0.1 Host 标头
获取上下文目录信息
使用新的标头,依然可以获取上下文信息
0x4 上传RCE
jsp Jetty
是基于Apache Jasper
的模块支持JSP
默认情况下,org.eclipse.jetty.jsp.JettyJspServlet
负责处理Jetty
中的JSP
文件。
$JETTY_HOME/etc/webdefault.xml
配置文件,默认情况下会将下面类型文件解析为JSP
文件
jetty中要解析JSP
文件,需要启动jsp
模块
1 | java -jar start.jar --module=jsp |
0x01 常见上传目录
常见上传JSP
一般都会保存在$JETTY_BASE/webapps/root
,这种RCE
方式只需要了解一下就行。
0x02 上传临时目录
Jetty
如果没有设置固定的”工作”目录,每次启动服务时生成的临时目录都会附带上随机数字字符串
临时目录结构如下:
1 | "jetty-"+host+"-"+port+"-"+resourceBase+"-_"+context+"-"+virtualhost+"-"+randomdigits+" |
- 我看文档说时会在上面的目录结构后加上
.dir
,但是我环境中就没有发现有加上.dir
。这里需要注意一下,有可能是我的问题。 0.0.0.0
是主机地址,8080
是端口,test_war
是resourceBase,test
(root
)是上下文路径(将/转换为_),any
是虚拟主机,randomdigits
是一串随机数字。
这里我的上下文目录可能有些多,所以看起来有点乱,只需要知道test
(root
)代表的是webapps
里面的目录即可。
如果能找到已经创建的临时目录,可以尝试上传shell
到$JETTY_BASE/work/"jetty-"+host+"-"+port+"-"+resourceBase+"-_"+context+"-"+virtualhost+"-"/webapps/
中
- 测试时,我发现临时目录中没有
webapps
目录,那么就无法成功访问。
设置工作目录
设置工作目录只需要在${jetty.base}
目录创建一个work
目录,而且work
目录一般都用作WEB
应用程序所有临时文件夹的父目录,启动服务时,会在work
目录创建临时目录
在“工作”目录下的临时目录结构如下:
1 | "jetty-"+host+"-"+port+"-"+resourceBase+"-_"+context+"-"+virtualhost+"-" |
0.0.0.0
是主机地址,8080
是端口,demo-simple_war
是resourceBase,test
(root
)是上下文路径(将/转换为_),any
是虚拟主机。
0x5 上传war文件rce
当无法上传jsp
文件时,我们还可以上传war
文件GETSHELL
。
制作war webshell
文件只需要将shell
文件压缩成war
后缀即可
1 | zip -r shell.war index.jsp |
将war
文件上传到$jetty_base/webapps/
,这样就可以RCE
了
服务器没有开启jsp
模块,那么即使上传war
文件也无法RCE
,只能使用servlet
创建java
应用完成RCE
0x6 上传XML文件RCE
除去上述上传jsp
、war
文件可以RCE
外,还可以通过上传XML
文件进行RCE
XML
文件有自己的语法,允许实例化任何对象,并调用getter
、setter
和方法。
- 下面只是简单演示复现,如果想看更详细的内容推荐看这个链接
XML代码
1 |
|
XML
文件上传后无需要服务器重启,jetty
的热部署功能会自动扫描部署新的web
应用程序
0x7 上传文件XSS
JETTY
服务器不仅可以上传总所周知的.html
或.svg
文件,还可以上传其他冷门扩展名的文件。
有效载荷:
xml 载荷
<a:script xmlns:a="http://www.w3.org/1999/xhtml">alert('PTSWARM')</script>
html 载荷
<script>alert('PTSWARM')</script>
我这里比较懒就直接抄作业了
除了上述这些文件可以上传导致XSS外,如果JETTY
服务器响应时没有Content-type 标头,可以尝试自定义内容MIME
类型,都可以导致XSS
,不过载荷一般都是使用<script>alert('PTSWARM')</script>
0x8 Jetty绕WAF
jetty
绕过这段,我没弄成本地环境,也找不到相关环境。所以就直接用原文的内容。
原文地址:https://swarm.ptsecurity.com/jetty-features-for-hacking-web-apps/
0x01 绕过waf拦截目录
了解了Jetty
服务器如何解析URL
地址,我们可以绕过代理服务器上的过滤器。想象一下,Jetty
服务器部署在NGINX
代理后面,其规则阻止对 /adminURL/*
的请求。
1 | location ~ /adminURL/ { |
如果只在代理上配置了这个规则,我们可以向 /adminURL;random/
发送HTTP
请求,并获得对服务器上受保护资源的访问权限。
0x02 绕过waf读取文件
JSP文件代码
1 | <%@ page import="java.io.File" %> |
应用程序从用户请求中接收filename
参数,使用该参数中的路径打开文件,并将文件内容返回给用户。这是一个允许我们读取任意文件的漏洞。但是,如果应用程序受到WAF
的保护,该WAF
会阻止所有在GET或POST
参数中包含/
的请求呢?
被WAF
拦截情况下,可以利用request.getParameter
方法处理参数的方式。getParameter
在不同的中间件服务器上工作方式都有所不同。getParameter
在jetty
应用程序调用时,getParameter
会在GET
和POST
参数中查找值。如果使用POST
请求发送Content-Type: multipart/form-data
,Jetty
会将该请求使用单独的解析器来解析。
如果POST参数中包含_charset_
字段,则多部份解析将使用指定的编码处理所有参数
。这样我们可以使用字符编码来绕过WAF
拦截,因为WAF
不可能识别所有不同编码的字符
图片中使用的是ibm037
编码
使用上面的方法绕过waf
需要服务器启动多部份处理。如果服务器托管处理文件上传的应用程序,则将启用多部分处理。
不启动多部份处理的服务器可能会跟图片下提示
0x03 jetty 边界解析
解析多部份请求的边界时,解析器在到达;
边界字符串就会停止。;
后面的所有字符串都会被忽略。
0x04 jetty 清除反斜杠
jetty从多部份请求中提取参数名称时,会把反斜杠清除,即\[any_symbol]
被转换成[any_symbol]
。我们可以利用该机制绕过WAF
,下面使用XSS
漏洞演示
参考链接
https://docs.oracle.com/cd/E24329_01/web.1211/e21049/web_xml.htm#WBAPP529
https://examples.javacodegeeks.com/enterprise-java/jetty/jetty-web-xml-configuration-example/
https://swarm.ptsecurity.com/jetty-features-for-hacking-web-apps/
https://www.eclipse.org/jetty/documentation/jetty-11/operations-guide/index.html
https://github.com/motikan2010/CVE-2020-27223
https://github.com/vulhub/vulhub
https://regilero.github.io/english/security/2019/04/24/security_jetty_http_smuggling/#toc4