【Java安全】RMI基础

文章目录

    • 介绍
    • 实现
      • 服务端 Server
      • 客户端 Client
    • 通信过程
      • 数据端与注册中心(1099 端口)建立通讯
      • 客户端与服务端建立 TCP 通讯
      • 客户端序列化传输 调用函数的输入参数至服务端
      • 总结

介绍

RMI 全称 Remote Method Invocation(远程方法调用),即在一个 JVM 中 Java 程序调用在另一个远程 JVM 中运行的 Java 程序,这个远程 JVM 既可以在同一台实体机上,也可以在不同的实体机上,两者之间通过网络进行通信。

RMI的一般要用到的组件:

  • Remote Interface:远程接口

需要定义一个接口,继承自 java.rmi.Remote,表明可以被远程对象调用的方法。
远程调用可能发生网络异常 , 所以每个方法都必须显式抛出 RemoteException

  • Remote Object Implementation:远程接口的具体实现

一般需要继承UnicastRemoteObject类, 将对象导出成一个 可以通过 TCP 调用的远程对象

  • Server:服务端,注册远程对象到 RMI 注册中心。
  • Client:客户端,查找远程对象并调用其方法。
  • Registry:注册端提供服务注册与服务获取。即 Server 端向 Registry 注册服务,比如地址、端口等一些信息,Client 端从 Registry 获取远程对象的一些信息,如地址、端口等,然后进行远程调用。

实现

服务端 Server

定义远程接口

package RMI.Server;import java.rmi.Remote;
import java.rmi.RemoteException;public interface Hello extends Remote {public String sayHello(String name) throws RemoteException;
}

远程接口的实现

package RMI.Server;import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;public class HelloImpl extends UnicastRemoteObject implements Hello {public HelloImpl() throws RemoteException {super(); //也可以什么都不写,隐式调用//如果没有继承UnicastRemoteObject,就需要手动导出: UnicastRemoteObject.exportObject(this, 0); }@Overridepublic String sayHello(String name) throws RemoteException {return "Hello " + name;}
}

服务端

主要是创建 RMI 注册表(使用默认端口 1099),创建服务实现类的实例,将远程对象绑定到注册表中

package RMI.Server;import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;public class RMIServer {public static void main(String[] args) {try{//实例化远程对象HelloImpl obj = new HelloImpl();//启动本地的RMI注册服务(一般默认 1099 端口),创建注册中心LocateRegistry.createRegistry(1099);Registry registry = LocateRegistry.getRegistry();//绑定远程对象registry.bind("HelloImpl", obj);//或者import java.rmi.Naming;//Naming.bind("rmi://127.0.0.1:1099/HelloImpl", obj);}catch (Exception e){e.printStackTrace();}}
}

客户端 Client

连接到本地(localhost)的 RMI 注册表然后查找相应名字的远程对象,最后调用远程方法,传入相应参数

package RMI.Client;import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import RMI.Server.Hello; // 导入服务器端的远程接口public class RMIClient {public static void main(String[] args) throws Exception {//连接到服务器Registry registry = LocateRegistry.getRegistry("localhost", 1099);//通过名字查找远程对象Hello hello = (Hello) registry.lookup("HelloImpl");//调用远程对象上面的方法String response = hello.sayHello("xpw");System.out.println("response :"+response);}}

先运行服务端, 再运行客户端, 在客户端就可以看到调用了远程对象的方法了

在这里插入图片描述

通信过程

很多复制粘贴的来自其他师傅的博客,了解了一下内部通信的知识,还没有动手去尝试抓包

数据端与注册中心(1099 端口)建立通讯

  • 客户端查询需要调用的函数的远程引用,注册中心返回远程引用和提供该服务的服务端 IP 与端口。

在这里插入图片描述

客户端与注册中心(1099 端口)建立通讯完成后,客户端 向注册中心发送了⼀个 “Call” 消息,注册中心回复了⼀个 “ReturnData” 消息,然后客户端新建了⼀个 TCP 连接,连到服务端的 33769 端⼝

在这里插入图片描述

AC ED 00 05是常见的 Java 反序列化 16 进制特征
注意以上两个关键步骤都是使用序列化语句

客户端与服务端建立 TCP 通讯

客户端发送远程引用给服务端,服务端返回函数唯一标识符,来确认可以被调用

在这里插入图片描述

同样使用序列化的传输形式

以上两个过程对应的代码是这两句

Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);  
RemoteObj remoteObj = (RemoteObj) registry.lookup("remoteObj"); // 查找远程对象

这里会返回一个 Proxy 类型函数,这个 Proxy 类型函数会在我们后续的攻击中用到。

客户端序列化传输 调用函数的输入参数至服务端

  • 这一步的同时:服务端返回序列化的执行结果至客户端

在这里插入图片描述

以上调用通讯过程对应的代码是这一句

remoteObj.sayHello("hello");

可以看出所有的数据流都是使用序列化传输的,那必然在客户端和服务带都存在反序列化的语句。

总结

整个过程进⾏了两次TCP握⼿,也就是我们实际建⽴了两次 TCP连接。

第⼀次建⽴TCP连接是连接远端 ip 的1099端⼝,这也是我们在代码⾥看到的端⼝,⼆ 者进⾏沟通后,我向远端发送了⼀个“Call”消息,远端回复了⼀个“ReturnData”消息,然后我新建了⼀ 个TCP连接,连到远端的33769端⼝。

之所以是33769端口, 因为在“ReturnData”这个包中,返回了⽬标的IP地址,其后跟的⼀个字节 \x00\x00\x83\xE9 ,刚好就是整数 33769 的网络序列

所以捋一下整个的过程: 首先客户端连接Registry,并在其中寻找Name是HelloImpl的对象,这个对应数据流中的Call消息;然后Registry返回⼀个序列化的数据,这个就是找到的Name=HelloImpl的对象,这个对应数据流中的ReturnData消息;客户端反序列化该对象,发现该对象是⼀个远程对象,地址在 127.0.0.1:33769 ,于是再与这个地址建⽴TCP连接;在这个新的连接中,才执⾏真正远程 ⽅法调⽤,也就是 HelloImpl()

各个元素之间的关系

在这里插入图片描述

RMI Registry就像⼀个⽹关,他⾃⼰是不会执⾏远程⽅法的,但RMI Server可以在上⾯注册⼀个Name 到对象的绑定关系;RMI Client通过Name向RMI Registry查询,得到这个绑定关系,然后再连接RMI Server;最后,远程⽅法实际上在RMI Server上调⽤。

参考文章

代码审计社区 Java安全漫谈
https://drun1baby.top/2022/07/19/Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B9%8BRMI%E4%B8%93%E9%A2%9801-RMI%E5%9F%BA%E7%A1%80/#Java-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B9%8B-RMI-%E4%B8%93%E9%A2%98-01-RMI-%E5%9F%BA%E7%A1%80
https://fushuling.com/index.php/2023/01/30/java%e5%ae%89%e5%85%a8%e7%ac%94%e8%ae%b0/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88065.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL索引面试问题梳理

本文系统剖析MySQL索引的核心机制: ‌索引分类全景图‌:详解聚簇/非聚簇索引的逻辑差异与物理存储特点‌B树的统治性优势‌:通过对比Hash/B树揭示InnoDB的底层选择逻辑 一、索引分类的常见困惑解析 1. 按物理存储分类 类型 存储内容 数量限…

SSH密钥 与 Ed25519密钥 是什么关系

SSH 密钥与 Ed25519 密钥的关系可以从技术实现和应用场景两个角度理解。简而言之:Ed25519 密钥是 SSH 密钥的一种类型,用于在 SSH 协议中实现安全认证。以下是详细解释: 1. SSH 密钥的通用概念 SSH(Secure Shell)是一…

【PyTorch 当前版本不支持 NVIDIA GeForce RTX 5060 Ti处理办法】

报错信息 X:\Stable-Diffusion-WebUI\system\python\lib\site-packages\torch\cuda\__init__.py:215: UserWarning: NVIDIA GeForce RTX 5060 Ti with CUDA capability sm_120 is not compatible with the current PyTorch installation. The current PyTorch install supports…

Docker部署PaddleX实现PaddleOcr

Docker部署PaddleX实现PaddleOcr 一、版本说明二、安装PaddleX三、基础服务化部署四、接口调用实现表格识别五、调参优化一、版本说明 PaddleX 3.0Ubuntu20.04.1Docker version 26.1.3, build 26.1.3-0ubuntu1~20.04.1二、安装PaddleX 查看服务器信息 docker安装PaddleX 根据 …

深入学习c++之---AVL树

VL树简介​ AVL树是一种自平衡二叉搜索树,通过平衡因子(Balance Factor, BF)​和旋转操作,确保树始终保持平衡,避免退化成链表,从而保证查找、插入、删除的时间复杂度稳定在 ​O(log n)​。 ​核心特点​…

【PTA数据结构 | C语言版】输出 1 ~ n

本专栏持续输出数据结构题目集,欢迎订阅。 文章目录题目代码题目 给定正整数 n,输出 1 ~ n,每个数字占一行。 本题旨在测试不同的算法在各种数据情况下的表现。各组测试数据特点如下: 数据 0:测试基本正确性&#x…

如何禁止用户复制页面内容?

某些特定的业务场景下,我们可能会有禁止用户复制页面内容的需求。比如: 付费内容保护:在线小说、付费课程等,希望防止内容被轻易拷贝和传播。试卷或答题系统:防止考生将题目复制出去寻求场外帮助。敏感信息展示&#x…

React + PDF.js 预览 PDF 文件:从基础实现到高级优化的完整指南

关键点 PDF.js:Mozilla 开发的开源 JavaScript 库,用于在浏览器中渲染 PDF 文件。React 集成:结合 React 组件化特性,实现高效、交互式的 PDF 预览功能。功能实现:支持 PDF 文件加载、页面导航、缩放、搜索、书签和注…

新能源汽车BMS电感产品应用及选型推荐

在新能源电动汽车中,BMS(电池管理系统)如同一个守护者,默默守护电池的安全与性能。它精准监控电压、电流、温度,防止过充过放,并通过智能均衡技术提升续航能力。电感在BMS系统的电源转换、滤波和隔离通信等…

【机器学习笔记 Ⅱ】12随机森林

随机森林(Random Forest)详解 随机森林是一种基于集成学习(Ensemble Learning)的高性能分类/回归算法,通过构建多棵决策树并综合其预测结果,显著提升模型的准确性和鲁棒性。其核心思想是“集体智慧优于个体…

问题 1:MyBatis-plus-3.5.9 的分页功能修复

问题 1:MyBatis-plus-3.5.9 的分页功能修复 使用 Sw‏agger 接口文档‎依次对上述接口进行测 试,发现 listU⁡serVOByPage 接口有一些问题! 分页好像没有生效,还是查出了全部数据: 由于我们用的是 MyBatis Plus 来操…

Qt 如何提供在线帮助

Qt 如何提供在线帮助一、概述二、工具提示、状态提示和"Whats This?"帮助1、工具提示(Tool Tips)添加工具提示到控件富文本工具提示全局工具提示设置延迟显示控制自定义工具提示窗口禁用工具提示工具提示与状态栏联动特点:2、状态提示(Status Tips)3、&q…

Typecho站点关闭插件开发全指南:从原理到实现

文章目录 开发Typecho站点关闭插件:从原理到实现一、背景与需求分析二、插件设计思路2.1 技术选型2.2 功能模块设计三、插件开发实现3.1 插件基础结构3.2 插件主文件实现3.3 核心功能实现3.4 后台管理界面3.5 关闭页面模板四、插件配置完善4.1 配置表单实现4.2 定时任务处理五…

详细解析 .NET 依赖注入的三种生命周期模式

文章目录一、Transient(瞬时生命周期)原理使用方式核心特性适用场景优势劣势二、Scoped(作用域生命周期)原理使用方式核心特性适用场景优势劣势三、Singleton(单例生命周期)原理使用方式核心特性适用场景优…

软件工程经济与伦理

前言 各位帅哥美女,能看到这篇博客的都有口福了,学习这门课程就像遨游在大份的海洋,一不小心就吃上一口。能看到这篇博客说明我们是有缘人可以点赞收藏一下,这篇博客可以在你无比饥饿的时候给你送上一坨!(香…

AI 体验走查 - 火山引擎存储的 AI UX 探索之路

01 概述 火山引擎存储技术团队驱动 AI 自主完成用户体验走查 / 可用性测试的执行与评价,帮助业务改善交互体验。 立项“故事走查”的背景诉求和 AI 机遇 如何搭建“AI 评价”能力,精准识别交互问题 让交互体验故事走查变为技术产品,讲解系…

【世纪龙科技】汽车零部件检验虚拟实训室-助力汽车职教实训

在汽车产业加速向电动化、智能化转型的背景下,职业院校汽车专业教学面临新的挑战:传统实训受限于设备数量不足、操作风险高、标准化程度低等问题,导致学生实践机会有限,技能掌握不扎实。如何让学生在有限资源下高效掌握零部件检验…

MySQL常用操作 查看表描述以及表结构、连接数及缓存和性能指标

查看表描述以及表结构查看数据库名SHOW DATABASES; SELECT DATABASE(); SELECT DATABASE() AS current_database;查看数据库中表的列表SHOW TABLES; SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA your_database_name; SELECT TABLE_NA…

音视频学习(三十六):websocket协议总结

概述项目描述标准RFC 6455使用端口默认 80(ws),443(wss)基于协议TCP特性全双工、低开销、持久连接、可穿透代理特点 全双工通信: WebSocket 允许客户端和服务器之间建立一个持久的连接,并且数据…

docker版本nacos的搭建

1.下载镜像2.拷贝出容器中对应的配置文件,logs,data,conf3.编写yaml配置文件version: 3.8 services:nacos-server:image: nacos/nacos-server:v2.4.0container_name: nacos-serverrestart: unless-stoppedports:- "8848:8848" # …