在web安全中,中間件安全也是非常重要的一部分,而中間件的安全問題主要來自兩個方面:一個是中間件本身的開發(fā)缺陷導致的安全問題,另一個是開發(fā)或運維人員在使用時進行了錯誤的配置而導致的安全問題。Tomcat也是眾所周知的,應用最廣泛的中間件了,那么接下來,我們就針對Tomcat中間件進行常見的安全問題及風險進行總結歸納。
Tomcat是屬于Apache下的一個項目分支,類似于這種的軟件項目,官方一般都會同時維護多個版本分支,一般新的產品特性會被更新在最新的大版本中,對于修復bug及漏洞這種就會在舊版本的分支中進行更新,這樣就允許開發(fā)或運維人員在不破壞原有的生產環(huán)境的情況下完成對當前版本軟件的更新。
例如當前你使用的Tomcat版本是6.0.20,當需要進行升級更新時,在6.0版本分支中尋找新的版本(如6.0.25),升級到最新的漏洞修復版本,如果在性能、功能等其他方有新的需求時,沒有必要升級到Tomcat7版本。
對于Tomcat的使用者及維護者來說,就應該密切關注Tomcat官網中對安全漏洞和新版本的發(fā)布公告(http://tomcat.apache.org/security.html)及時了解漏洞信息及新版本的更新信息,這樣就能及時判斷自己所使用的版本是否存在安全隱患,是否需要更新。
首先我們必須保證運行Tomcat的用戶權限不能是高權限,比如windows下的administrator和Linux下的root用戶或用戶組,建議在使用Tomcat時創(chuàng)建一個Tomcat專屬用戶,在保證不影響業(yè)務正常使用的情況下將該用戶權限降至最低,此外還要根據業(yè)務需求來對應用涉及的文件目錄文件夾的讀取、寫入及執(zhí)行的權限進行詳細的分配。這樣一來,就能很大程度上增加攻擊者的攻擊成本。
Example應用
Tomcat在安裝部署后,在webapps默認存在一個examples目錄,該目錄正如其文件名一樣,提供一些示例應用讓使用者來了解Tomcat的特性及功能。這些樣例在業(yè)務上線后并沒有什么用處,建議部署tomcat后,刪除其中的樣例文件(ROOT, balancer,jsp-examples, servlet-examples, tomcat-docs, webdav),避免信息泄露和其他潛在的安全風險。
這些樣例中的session樣例(/examples/servlets/servlet/SessionExample)允許用戶對session進行操縱,因為session是全局通用的,所以用戶可以通過操縱session獲取管理員權限,存在一定的安全風險,不過這種基本上只有在一些比較老的不安全系統(tǒng)中才有可能出現(xiàn),利用條件比較苛刻。
我們編寫3個頁面來模擬一般網站身份驗證的過程。
login.jsp

login1.jsp
<%
if(request.getParameter("username") != null && request.getParameter("password")!= null) {
String username =request.getParameter("username");
String password =request.getParameter("password");
//驗證身份
if (username.equals("admin")&& password.equals("admin")) {
session.setAttribute("login","admin");
response.sendRedirect("index.jsp");
}else {
response.sendRedirect("login.jsp");
}
}
%>
index.jsp
<%
if(session.getAttribute("login")!= null &&((String)session.getAttribute("login")).equals("admin")){
out.println("Login");
} else{
response.sendRedirect("login.jsp");
}
%>
我們將寫好的三個頁面部署到tomcat上,我們首先訪問一下index.jsp頁面看看,訪問之后跳轉至login.jsp。

我們利用examples的session servlet功能操作一下session,將login的值改成admin,生成session。

提交成功之后我們再來訪問一下index.jsp,發(fā)現(xiàn)不會跳轉,直接限制Login,說明我們生成的session有效,通過操作session繞過了登錄。

Admin管理頁面
Tomcat的admin console全稱是Tomcat WEB Server Administration ToolT,該模塊在Tomcat 5.0.4版本之前都是默認安裝的,5.0.4之后版本默認存在該目錄,但是功能并不全,直接使用,從5.5版本開始作為可選模塊進行安裝,安裝后的默認路徑為/admin,與manager配置相同,在tomcat-user.xml文件中進行賬號密碼的配置。該模塊實現(xiàn)了通過web方式對tomcat服務、已部署的應用程序、連接池和其他資源的管理,方便運維及開發(fā)人員的管理和操作。

登錄后,在下圖中的功能,可以配置虛擬目錄,將服務器上的物理路徑與web路徑進行映射,從而可以實現(xiàn)對任意目錄的訪問。



但是需要注意的是,這里需要在tomcat配置中開啟列目錄,將false改為true,否則就會出現(xiàn)如下情形,無法利用該方式讀取文件。


利用該方法進行文件讀取的攻擊方式現(xiàn)在已經幾乎絕跡,也只能在一些內網中找到這樣的古董系統(tǒng),至于古董系統(tǒng)有沒有開放administration tool,就要看命了!
Manager管理頁面
Manager管理平臺我們都很熟悉,也是最常見的,包含多個管理模塊,開啟后方便開發(fā)及運維人員對tomcat項目發(fā)布進行管理。Manager管理平臺默認安裝后是沒有設置登錄口令的,需要在tomcat-user.xml文件中進行配置,與上文的admin管理平臺相同。
在登錄manager后臺時,tomcat使用的是Basic認證方式,在請求的數據包中包含一個Authorization字段,該字段的值為賬號密碼的base64編碼,如圖所示:

Tomcat manager包含4個不同的角色:
manager-gui:允許訪問html頁面接口(即URL路徑為/manager/html/*)
manager-script:允許訪問純文本接口(即URL路徑為/manager/text/*)
manager-jmx:允許訪問JMX代理接口(即URL路徑為/manager/jmxproxy/*)
manager-status:允許訪問Tomcat只讀狀態(tài)頁面(即URL路徑為/manager/status/*)
其中manager-gui、manager-script、manager-jmx三個角色均具備manager-status角色的權限,即這三種角色權限無需再額外添加manager-status權限。實際使用中只需配置manager-gui角色通過html頁面的形式訪問管理平臺。下面我們來分別簡述一下manager的這4個角色。
manager-gui
manager-gui是最常見也是最常用的模塊,我們通常訪問/manager/html看到的頁面就是manager-gui,不同版本之間的功能都大同小異,對于攻擊者來說,最直接的方式就是通過部署應用的功能來部署war包,從而部署webshell后門應用。

manager-script
該模塊下包含了所有管理功能的接口,攻擊者也可以通過這個接口來對tomcat應用發(fā)起攻擊。下面我們來列舉幾個常用的功能:
/manager/text/deploy?path=/xxx
部署web應用,需要注意的是這里部署的文件為war包,在請求時需要使用PUT方法。

查看所有部署的應用。

查看服務器信息。

詳細功能,可以在tomcat的幫助文檔中查看:http://{ip}:{port}/docs/manager-howto.html
manager-status
該模塊訪問后可以看到一些與服務器相關的信息,沒有太多有實際價值的信息,也只能幫助收集到一些簡單的信息。

manager-jmx
Tomcat使用JMX管理方式,在Tomcat的自帶應用manager就是使用了JMX方式來管理Tomcat,以此完成Web應用的動態(tài)部署、啟動、停止。在tomcat的幫助文檔中,提供了下面幾種方式發(fā)送請求獲取相應的信息:
query命令:http://[ip]:[port]/manager/jmxproxy/?qry=
get命令:http:// [ip]:[port]/manager/jmxproxy/?get=
set命令:http:// [ip]:[port]/manager/jmxproxy/?set=
invoke命令:http:// [ip]:[port]/manager/jmxproxy/?invoke=
訪問上面的地址,我們就可以看到不同的信息,通過向不同的參數傳遞特定的參數,也可以獲取到一些敏感信息。不加參數時查詢到的是所有的MBeans的內容,加參數之后就可以查看到具體的MBeans的內容。
例如:
http://[ip]:[port]/manager/jmxproxy/?qry=*%3atype=User%2c*
該查詢可以看到設置的tomcat-user.xml中配置的賬號密碼,甚至還可以通過set命令修改賬號密碼,來設置一個后門賬號。

除此之外,Tomcat下還可以開啟JMX Service,默認情況下Tomcat是不開啟jmx service的,開啟JMX Service需要對/bin目錄下的Catalina.bat/Catalina.sh文件進行更改。
Catalina.bat:
set CATALINA_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10001 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
Catalina.sh:
CATALINA_OPTS="$CATALINA_OPTS-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10001 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
這里沒有對jmx連接設置身份認證,從安全角度來說,需要設置身份認證,設置認證時,需要在配置中添加:
-Dcom.sun.management.jmxremote.password.file=path/jmxremote.password
-Dcom.sun.management.jmxremote.access.file=path/jmxremote.access
在jdk的安裝目錄/jre/lib/management目錄下,有相應的jmxremote.access文件,將文件最后兩行顯示【monitorRole和controlRole】的注釋取消,其中monitorRole為只擁有只讀權限的角色,controlRole有更高權限:讀寫等。默認情況下該目錄下不存在jmxremote.password 文件,我們可以將jmxremote.password.template文件改名,或者復制出來一份再改名即可,然后修改jmxremote.password文件。同樣將文件最后兩行顯示【monitorRole和controlRole】的注釋取消。然后保存。
配置后之后,我們就可以啟動Tomcat,啟動之后先查看一下我們配置的jmx是否正常開啟。

通過java自帶的jconsole來連接我們配置jmx端口。

連接之后,我們可以通過jconsole的頁面看到許多的敏感信息,這些與前面的manager-jmx類似。

同樣的可以通過查看MBean看到tomcat manager配置的賬號密碼,除此之外,還能添加賬號,從而添加后門賬號。


在Catalina->Valve->localhost->AccessLogValve中,可以實現(xiàn)對日志備份的操作,通過前面獲取到的Tomcat物理路徑,根據webapps目錄以及從MBean中獲取到的已安裝的應用,可以構造出web路徑。我們在進行日志備份時,需要備份到不存在的文件中,如果文件已存在,該功能不會對已存在的文件進行覆蓋或追加。

AJP協(xié)議
由于tomcat的html和圖片解析功能相對其他服務器如apche等較弱,所以,一般都是集成起來使用,只有jsp和servlet服務交由tomcat處理,而tomcat和其他服務器的集成,就是通過ajp協(xié)議來完成的。Web客戶訪問Tomcat服務器上JSP組件的兩種方式如圖所示。

在tomcat中有兩個連接器,一個是監(jiān)聽在8080端口,負責建立web的HTTP連接,一個是監(jiān)聽在8009端口,負責Tomcat與其他HTTP服務器進行集成。配置文件server.xml中,關于AJP的配置項默認是關閉的,若需要開啟,將注釋符去掉,重新啟動Tomcat即可。

相對而言,AJP協(xié)議的攻擊利用方式較少,目前爆出的可直接利用的就是CVE-2020-1938(AJP文件包含漏洞)。
Debug模式
Tomcat默認情況下,debug模式是不開啟的,如果需要開啟debug時,要對/bin目錄下的Catalina.bat/Catalina.sh文件進行修改:Windows下在Catalina.bat中添加:
SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
Linux下在Catalina.sh中對jpda相關的內容進行修改

修改完成后,在startup.sh文件中添加jpda,如下所示:

全部修改完成后,我們就可以啟動tomcat了,此時debug模式就正常啟動了。我們通過nmap對tomcat debug端口進行探測,發(fā)現(xiàn)該端口service信息為jdwp。

實際上Tomcat的debug模式也是調用的jvm的調試接口,正如配置文件中顯示的那樣,最終是通過調用jdwp來實現(xiàn)。
JPDA(Java Platform Debugger Architecture,Java平臺調試架構) ,由Java虛擬機后端和調試平臺前端組成, JPDA為Java平臺上的調試器定義了一個標準的體系結構。該體系結構包括3個主要組成部分:JVM TI(Java虛擬機工具接口)、JDI(Java調試連線協(xié)議)和JDWP(Java調試接口)。
在一些低版本的jdk中會存在漏洞,可以通過jdwp來執(zhí)行系統(tǒng)命令。所以對Tomcat的安全配置時,要關閉debug模式。
CVE-2016-8735
漏洞說明:
該漏洞與之前Oracle發(fā)布的mxRemoteLifecycleListener反序列化漏洞(CVE-2016-3427)相關,是由于使用了JmxRemoteLifecycleListener的監(jiān)聽功能所導致。而在Oracle官方發(fā)布修復后,Tomcat未能及時修復更新而導致的遠程代碼執(zhí)行。
該漏洞所造成的最根本原因是Tomcat在配置JMX做監(jiān)控時使用了JmxRemoteLifecycleListener的方法。

影響版本:
漏洞利用:
這里我們使用ysoserial來進行漏洞攻擊利用


CVE-2017-12615 & CVE-2017-12616
漏洞說明:
該漏洞稱之為Tomcat PUT方法任意寫文件漏洞,類似IIS的PUT上傳漏洞。該漏洞可以利用HTTP的PUT方法直接上傳webshell到目標服務器,從而獲取權限。該漏洞是高危漏洞,在Tomcat的web.xml默認情況下不存在該漏洞,但是一但開發(fā)者或者運維人員手動講web.xml中的readonly設置為false,可以通過 PUT / DELETE 進行文件操控。
CVE-2017-12616是對CVE-2017-12615的繞過,影響 7.x、8.x、9.x版本。

影響范圍:
7.0.0 – 7.0.79
漏洞利用:
構造PUT上傳數據包,上傳時內容可以寫jsp一句話木馬,上傳返回201時,表示上傳成功,訪問該文件即可。


上傳繞過方法:
Windows:
1、利用/shell.jsp::$DATA的方式繞過2、/shell.jsp%20,空格繞過3、/shell.jsp/ , Tomcat在處理文件時會刪除最后的/
Linux:
/shell.jsp/ , Tomcat在處理文件時會刪除最后的/
CVE-2019-0232
漏洞說明:
該漏洞是由于Tomcat CGI將命令行參數傳遞給Windows程序的方式存在錯誤,使得CGIServlet被命令注入影響。
該漏洞的利用條件較為苛刻,需同時滿足下列條件:
系統(tǒng)為Windows
啟用了CGI Servlet(默認為關閉)
啟用了enableCmdLineArguments(Tomcat 9.0.*及官方未來發(fā)布版本默認為關閉)
影響范圍:
9.0.0.M1-9.0.17
8.5.0-8.5.39
7.0.0-7.0.93
漏洞利用:

CVE-2020-1938
漏洞描述:
漏洞是Tomcat AJP協(xié)議存在缺陷而導致,攻擊者利用漏洞可以構造特定參數,讀取服務器webapp/ROOT下的任意文件。若目標服務器同時存在文件上傳功能,攻擊者可進一步通過文件包含實現(xiàn)遠程代碼執(zhí)行。
影響范圍:
Apache Tomcat 6
Apache Tomcat 7 < 7.0.100
Apache Tomcat 8 < 8.5.51
Apache Tomcat 9 < 9.0.31
漏洞利用:
使用已公開的漏洞利用工具來進行漏洞利用。