Apache Solr 之JMX远程代码漏洞分析

来源:岁月联盟 编辑:猪蛋儿 时间:2020-01-29

Apache Solr的8.1.1和8.2.0 linux版本的自带配置文件solr.in.sh中存在ENABLE_REMOTE_JMX_OPTS=”true”选项,并且默认开启,导致apache solr会在默认端口18983端口开放JMX服务,而且不需要身份认证,导致任何可以访问该端口的攻击者能够发起攻击,执行任意命令。
 
JMX和MBean
正如前言所说,这次apache solr 漏洞是JMX问题导致的,所以我们需要选简单介绍下JMX机制。
JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等植入管理功能的框架。狭隘的理解,我们可以通过JMX管理、监视我们的java程序。但是不是所有java程序都能被管理,只有通过特定实现的java才能够被管理,这种特定实现机制就是Mbean。
 
Mbean编写与管理
每一个MBean都需要实现一个接口,下面我们实现一个简单的HelloWorldMBean
public interface HelloWorldMBean {
    public void setGreeting(String greeting);
    public String getGreeting();
    public void printGreeting();
}
public class HelloWorld implements HelloWorldMBean {
    private String greeting = null;
    public HelloWorld(String greeting) {
        this.greeting = greeting;
    }
    public HelloWorld() {
        this.greeting = "Hello World! I am Standard MBean";
    }
    @Override
    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }
    @Override
    public String getGreeting() {
        return this.greeting;
    }
    @Override
    public void printGreeting() {
        System.out.println(this.greeting);
    }
}
如果我们想要监控管理这个HelloWorldMBean,我们需要把该MBean添加到MBeanServer中。代码如下:
public class RemoteMbean {
    public static void main(String[] args){
        try{
            MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
            //---------------------------------------------
            //local mbean
            System.out.println("Register Hello bean...");
            HelloWorld hello = new HelloWorld();
            ObjectName objectHelloName = new ObjectName("JMXHello:name=hello");
            mBeanServer.registerMBean(hello, objectHelloName);
            //这句话非常重要,不能缺少!注册一个端口,绑定url后,客户端就可以使用rmi通过url方式来连接JMXConnectorServer
            Registry registry = LocateRegistry.createRegistry(1099);
            //构造JMXServiceURL
            JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
            //创建JMXConnectorServer
            JMXConnectorServer jmxConnectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null, mBeanServer);
            //启动
            jmxConnectorServer.start();
            System.out.println("JMXConnectorServer is running");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
然后运行该程序,使用jconsole连接localhost:1099

这里我们可以通过jconsole执行远端HelloWorldMbean的printGreeting函数。
 
远程MBean
上节我们所编写的MBean是在本地的,JMX提供一种机制,可以使用远程的MBean。MLet对象,该对象有一个getMBeansFromURL方法,通过该方法我们可以使用远程的MBean。也正是因为这个原因,才导致JMX存在远程代码执行漏洞的可能。下面我们通过代码,观察下结果。

[1] [2] [3] [4]  下一页