10.jmx安全问题

前言

这一章我们来说说JMX的安全问题把,内容相对来说比较简单,当然,我们还是回给出几个相关的案例

JMX简介

JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等植入管理功能的框架。狭隘的理解,我们可以通过JMX管理、监视我们的java程序。但是不是所有java程序都能被管理,只有通过特定实现的java才能够被管理,这种特定实现机制就是Mbean。

如上所属,利用JMX我们可以控制服务端的特定java程序,具体能够控制哪些java程序,又是如何控制的呢?我们还是用一些小demo来说明。能够被JMX控制的一种java程序被叫做MBean。接下来我们实现一个MBean

MBean 编写与控制

每一个MBean都需要实现一个接口,而且这个接口的命名是有讲究的,必须以MBean结尾,例如我将编写一个GirlFriendMBean接口:

import javax.management.DynamicMBean;

public interface GirlFriendMBean {
    String name = "";
    public void setName(String name);
    public String getName();
    public void sayHello();
}

然后我们需要实现这个MBean,同样的,这个实现的命名也是有讲究的,那就是去掉对应接口的的MBean后缀:

import javax.management.DynamicMBean;

public class GirlFriend implements GirlFriendMBean{
    String name;

    public GirlFriend(String name) {
        this.name = name;
    }

    public GirlFriend(){
        this.name = "Angel";
    }
    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void sayHello() {
        System.out.println("Hello sweet, I am yours");
    }
}

现在实现了MBean,要想他们能够被远程的客户端控制访问,还需要将其绑定到MBeanServer上,具体实现代码如下:

运行Server:

然后我们可以用jdk中自带的jconsole工具访问jmx server,在jdk的bin目录下,运行jconsole,天上地址localhost:1099就可以直接访问到了,可以看到我们实现的JMXGril

我们可以使用jconsole调用JMXGirl的方法,也可以设置其属性,我调用它的sayHello方法,效果如下:

远程MBean注册

上面的的demo展示的是MBean与JMX Server在同一主机上,jmx还提供了一种机制,可以将其他主机上的MBean绑定到别的MBean Server上,着需要用到另外一个文件mlet。我们一起来看一下实现方法把:

注: 以下代码引用自 https://www.anquanke.com/post/id/194126

我们将上述代码打包成jar包,在idea中打jar包参考:https://blog.csdn.net/nopotential/article/details/79018471

然后我们需要编写一个名为mlet的文件:

把mlet文件与刚刚创建的jar包放在同一Web目录下,我们这里可以直接用python2来简单搭建一个http server,运行如下命令就行: python -m SimpleHTTPServer,具体的百度一下吧

然后我们有了MBean,还需要一个MBeanServer吧,这次的MBean Server的实现方式与之前的差别不大,只是绑定的MBean是远程的而已,具体看下代码:

可以看到注释掉中有一个方法getMBeansFromURL,这个方法就是绑定远程类的关键所在,我们可以把mlet的地址作为其参数,然后当调用这个方法的时候,就会远程加载mlet文件中指定的jar文件。这个方法不需要在代码里直接调用,我们一会可以在jconsole中调用。现在运行这个Server,然后依旧用jconsole连接Server:

调用MLet的getMBeansFromURL,参数就是mlet文件的地址

然后你就会发现窗口里多了一个类,这个类就是远程的类了,我们可以执行他的runCmd方法弹个计算器:

控制jmx server端远程加载MBean

上面的demo是在jmx server本地实现的加载远程MBean,jmx危险之处就在于这一过程我们可以在客户端控制。也就是只要某个主机开启了jmx server端口,我们就可以通过自己编写代码或者使用现成的工具是server端加载远程的恶意类。

自己编写代码,代码同样引用别人的:

当然,用现成的工具他不香吗?个人觉得这个jython版的mjet挺好用的: https://github.com/mogwailabs/mjet

案例

这是最近(19年)爆出的一个apache solr的jmx配置错误导致的漏洞(其实就是默认开启了jmx端口)

这篇文章我放在另外一个项目里了,只是简单的复现:

https://github.com/Maskhe/vuls/tree/master/apache_solr/cve-2019-12409

其他

jmx的安全问题不复杂,主要就是对外开放了jmx端口,所以,就这么简单带过吧,see you~

Last updated