Java远程方法调用RMI利用分析
字数 2083 2025-08-15 21:32:20
Java RMI 安全漏洞分析与利用教学文档
1. 基础概念
1.1 JNDI (Java命名和目录接口)
- 提供统一的客户端API,通过不同的访问提供者接口(JNDI SPI)实现
- 将JNDI API映射为特定的命名服务和目录系统
- 使Java应用程序能与命名服务和目录服务交互
1.2 JRMP (Java远程方法协议)
- Java特有的协议,用于查找和引用远程对象
- 运行在Java RMI之下,TCP/IP之上的线路层协议
1.3 RMI (远程方法调用)
- Java实现远程过程调用的API
- 使客户端程序能调用远程服务器上的对象
- 宗旨是尽可能简化远程接口对象的使用
2. RMI攻击向量
2.1 序列化攻击
- 无版本限制,但部分逻辑会因版本不同而有差异
- 关键版本影响:6u45、7u21修改默认安全设置
2.2 两种bind区别
-
Server ↔ RMI Registry ↔ Client
- bind注册时进行序列化传输服务名&Ref
- 进入RegistryImpl_Skel.dispatch反序列化获取
-
Server(RMI Registry) ↔ Client
- 同一台机器,bind时已有Ref,无需序列化传输
- 只需在bindings list中添加键值
3. 注册与请求流程分析
3.1 bind流程
- ServiceImpl继承UnicastRemoteObject,实例化时通过exportObject创建stub
- 通过bind向RMI Registry注册服务名&stub
- RegistryImpl_Stub#bind中两次writeObject写入序列化的服务名&stub
- RMI Registry通过反序列化获取服务名&stub,写入bindings List
攻击点:Server通过bind操作对RMI Registry进行序列化攻击
3.2 lookup流程
- Client向RMI Registry发送lookup请求(操作数为2)
- RMI Registry反序列化获取查询服务名
- 从bindings list中查询,通过writeObject将stub序列化传输给Client
- Client通过readObject接收
攻击点:
- Client通过lookup操作对RMI Registry进行序列化攻击
- RMI Registry通过lookup操作被动攻击Client
3.3 远程调用机制
- 由RemoteObjectInvocationHandler实现动态代理
- 最终由UnicastRef#invoke实现调用
- marshalValue打包参数,unmarshalValue对返回内容反序列化
4. 攻击方向总结
- 向RMI Registry申请bind操作进行序列化攻击
- 向RMI Registry申请lookup操作进行序列化攻击
- RMI Registry通过lookup操作被动式序列化攻击请求者
5. 具体攻击技术
5.1 bind攻击(RMIRegistryExploit)
- 利用动态代理Remote.class
- 通过AnnotationInvocationHandler触发反序列化
- 需要java.rmi.server.useCodebaseOnly=false(6u45、7u21前默认)
5.2 RMI动态类加载机制
- 本地CLASSPATH找不到类时,从指定codebase加载class
- 防御:6u45、7u21后useCodebaseOnly默认为true
5.3 Client攻击Server
- Server加载远程类时触发
- 需要配置RMISecurityManager且useCodebaseOnly=false
5.4 Server攻击Client
- Client获取结果后需要获取远程类进行本地反序列化
5.5 JRMP攻击
- 直接利用socket通信,不接收服务端返回更安全
- 相关工具:
- payloads.JRMPListener:开启JRMP监听
- payloads.JRMPClient:发送注册Ref
- exploit.JRMPListener:被动传输序列化payload
- exploit.JRMPClient:主动传输序列化payload
6. DGC(分布式垃圾回收)
- 跟踪远程对象在客户机中的使用
- 当引用过期且未更新时,服务器将垃圾回收远程对象
7. JNDI Reference攻击
- Client执行lookup时加载远程恶意类实现RCE
- 防御:
- 6u141、7u131、8u121起默认trustURLCodebase=false
- JEP290对可反序列化类做白名单检测
8. 防御措施
- 升级JDK到安全版本
- 设置java.rmi.server.useCodebaseOnly=true
- 设置com.sun.jndi.rmi.object.trustURLCodebase=false
- 启用JEP290反序列化过滤机制
9. 攻击演示命令示例
- bind攻击:
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit <rmi_ip> <rmi_port> <payload> <args>
- JRMP监听:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener <port> <payload> <args>
- JRMP客户端攻击:
java -cp ysoserial.jar ysoserial.exploit.JRMPClient <target_ip> <target_port> <payload> <args>