JNDI学习笔记

news/2024/10/17 14:13:12/

最近在研究JNDI注入漏洞,就先浅浅的学习以下JNDI相关知识。

JNDI对各种目录服务的实现进行抽象和统一化。

在 Java 应用中除了以常规方式使用名称服务(比如使用 DNS 解析域名),另一个常见的用法是使用目录服务作为对象存储的系统,即用目录服务来存储和获取 Java 对象。

比如对于打印机服务,我们可以通过在目录服务中查找打印机,并获得一个打印机对象,基于这个 Java 对象进行实际的打印操作。

为此,就有了 JNDI,即 Java 的名称与目录服务接口,应用通过该接口与具体的目录服务进行交互。从设计上,JNDI 独立于具体的目录服务实现,因此可以针对不同的目录服务提供统一的操作接口。JNDI全称是:Java Naming and Directory Interface,它是一类给Java应用程序提供命名(Naming)和目录(Directory)功能的API编程接口。

JNDI 架构上主要包含两个部分,即 Java API和 SPI。

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

  1. RMI: Java Remote Method Invocation,Java 远程方法调用;
  2. LDAP: 轻量级目录访问协议;

除此之外,用户还可以在 Java 官网下载其他目录服务实现。由于 SPI 的统一接口,厂商也可以提供自己的私有目录服务实现,用户可无需重复修改代码。

命名服务(Naming Service)

它是一个类似于键值对绑定的功能,可以把一个对象作为值跟命名服务上一个名字绑定在一起,然后就可以通过这个名字到命名服务商查询以及使用先前绑定的对象。

目录服务(Directory Service)

名称服务还算比较好理解,那目录服务又是什么呢?简单来说,目录服务是名称服务的一种拓展,除了名称服务中已有的名称到对象的关联信息外,还允许对象拥有属性(attributes)信息。由此,我们不仅可以根据名称去查找(lookup)对象(并获取其对应属性),还可以根据属性值去搜索(search)对象。

举个例子:以打印机服务为例,我们可以在命名服务中根据打印机名称去获取打印机对象(引用),然后进行打印操作;同时打印机拥有速率、分辨率、颜色等属性,作为目录服务,用户可以根据打印机的分辨率去搜索对应的打印机对象。

目录服务(Directory Service)提供了对目录中对象(directory objects)的属性进行增删改查的操作。

LDAP:轻量级目录访问协议,是一种开放的网络协议,用于访问和维护分布式目录服务。LDAP 提供了一种标准化的方式来查询、添加、修改和删除分布式目录中的数据。

RMI:远程方法调用,是 Java 平台提供的一种机制,用于实现分布式应用程序中的远程通信和方法调用。RMI 允许在不同的 Java 虚拟机(JVM)上运行的对象之间进行通信,并调用对方的方法,就像调用本地对象的方法一样。

总而言之,目录服务也是一种特殊的名称服务,关键区别是在目录服务中通常使用搜索(search)操作去定位对象,而不是简单的根据名称查找(lookup)去定位。

JNDI带来优点:由于JNDI提供的接口统一性,当需要访问不同类型的目录服务时,不必再像以前一样分别针对不同的服务协议来实现用于访问的客户端,都可以通过JNDI提供的同一接口访问。

通过JNDI访问Java RMI服务:

package Example1;import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Hashtable;public class JndiRmiTest {public static void main(String[] args) throws Exception{// env是用于创建InitialContext的环境变量属性配置Hashtable env = new Hashtable();// Context.INITIAL_CONTEXT_FACTORY即字符串java.naming.factory.initialenv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.rmi.registry.RegistryContextFactory");// Context.PROVIDER_URL即字符串java.naming.provider.urlenv.put(Context.PROVIDER_URL,"rmi://localhost:1099");// 创建 InitialContextInitialContext context = new InitialContext(env);// 把foo这个名字和sample string绑定在一起String name = "foo";context.bind(name,"sample string");// 根据绑定的名字查询对应绑定的对象Object obj = context.lookup(name);// 在程序中使用查询获得的对象并且打印出来System.out.println(name + "is bound to" + obj);}
}

通过JNDI访问LDAP服务:

package Example1;import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;public class JndiLdapTest {public static void main(String[] args) throws NamingException {// env是用于创建InitialContext的环境变量属性配置Hashtable env = new Hashtable();// Context.INITIAL_CONTEXT_FACTORY即字符串java.naming.factory.initialenv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.rmi.registry.RegistryContextFactory");// Context.PROVIDER_URL即字符串java.naming.provider.urlenv.put(Context.PROVIDER_URL,"ldap://localhost:389");// 创建 InitialContextInitialContext context = new InitialContext(env);// 把 cn=foo,dc=test,dc=org 和 String 对象 sample string绑 定在一起String name = "cn=foo,dc=test,dc=org";context.bind(name,"sample string");Object obj = context.lookup(name);System.out.println(name + "is bind to" + obj);}
}

通过比较可以看出,使用JNDI不管是访问RMI和LDAP服务,执行的代码几乎都是一样的

JNDI中Reference的概念

为了将Java对象绑定到像RMI或者LDAP这些命名目录服务上,可以通过序列化来将特定状态下的对象转换为字节流进行传输和存储。但并不总是可以绑定对象的序列化状态,因为对象可能太大或不符合要求。

处于这样的考虑,JNDI定义了"命名引用"的概念,可以创建一个Reference,把它和要绑定得对象关联到一起,这样就只需要将对象的Reference绑定到目录服务上,而不用绑定原本的对象。Reference中会存有如何构造出关联对象的信息。命名目录服务的客户端在查询到Reference时,会根据Reference里的信息还原得到原本的绑定对象。

也就是说不在管理对象,而是通过管理Reference来管理对象。


http://www.ppmy.cn/news/86675.html

相关文章

Spring Cloud(Kilburn 2022.0.2版本)系列教程(二) 服务消费者(RestTemplate+Loadbalancer)

Spring Cloud(Kilburn 2022.0.2版本)系列教程(二) 服务消费者(RestTemplate+Loadbalancer) 为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000 一、服务消费 可以参考上节eurekaClientConsumer。 在启动类中,我们已经注入了一个restTemplate…

Linux音频和视频命令速查表

在Linux系统中,有许多命令可以帮助我们处理音频和视频文件,从基本的播放和转码,到编辑和处理音频、视频流。 本文将提供一个Linux音频和视频命令速查表,帮助您快速查找并了解各种常用的命令及其用法。 音频命令 播放音频文件 a…

超长溢出头部省略打点,坑这么大,技巧这么多?

目录 需求 利用 direction 实现头部超长溢出打点 简单介绍一下 direction: 另外两个与排版相关的属性还有: direction: rtl 会导致使用下划线 _ 连接的数字内容排版错误 多方案解决 方案一:两次 direction 反转 当然,这里…

【2023年第三届长三角高校数学建模竞赛】A 题 快递包裹装箱优化问题 20页完整论文及代码

相关链接 【2023年第三届长三角高校数学建模竞赛】A 题 快递包裹装箱优化问题 详细数学建模过程 1 题目 2022 年,中国一年的包裹已经超过 1000 亿件,占据了全球快递事务量的一半以上。近几年,中国每年新增包裹数量相当于美国整个国家一年的…

Yolov5涨点神器:注意力机制---多头上下文集成(Context Aggregation)的广义构建模块,助力小目标检测,暴力涨点

1.数据集性能验证 在crack道路缺陷检测任务中,多头上下文集成(Context Aggregation)的广义构建模块实现暴力涨点mAP50从0.954提升至0.992 🏆🏆🏆🏆🏆🏆Yolov5/Yolov7魔术师🏆🏆🏆🏆🏆🏆 ✨✨✨魔改网络、复现前沿论文,组合优化创新 🚀🚀🚀…

order by排序语句的用法

文章目录 学习连接语法用法示例1、按单个列的值排序2、按多个列的值排序3、按指定的规则排序4、按中文拼音字母顺序5、Order by和where条件共用 数据库中常用order by关键字对结果集进行排序,又可使用desc和asc来进行指定规则的排序。 学习连接 数据库:…

当你学会这项python数据提取神器时,请做好升职准备!

一、什么是 jsonpath ● JsonPath 是一种信息抽取类库,是从 JSON 文档中抽取指定信息的工具,提供多种语言实现版本,包括:JavaScript、Python、PHP 和 Java。 *文末领10节自动化精品课* 二、特点 ● 只能提取 JSON 格式的数据 ●…

Pinna的使用以及pinna的持续化存储(两种方法)

一、简介 pinia是 vue3 新的状态管理工具,简单来说相当于之前 vuex,它去掉了 Mutations 但是也是支持 vue2 的,需要的朋友可以参考下 二、使用方法 1.安装 npm install pinia -S 2..引入 import { createPinia,PiniaPluginContext } from p…