JNDI注入分析

AI-摘要
GPT-4.0-turbo GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
JNDI注入分析
Takake1.RMI服务调用
RMI的功能
服务端:将远程对象绑定到注册表(Registry),并发布一个唯一的名称(如
rmi://host:port/ServiceName
)。客户端:通过注册表查找远程对象的引用(Stub),获取调用入口。
1.1.写一个RMIdemo
- 那么我们现在先写一个远程对象的demo
- 远程对象接口
1 | import java.rmi.Remote; |
- 远程对象实现
1 | import java.rmi.RemoteException; |
- RMI服务器
1 | public class RMIServer { |
- RMI客户端
1 | import java.rmi.NotBoundException; |
1.2.调用测试
- 启动服务器
- 客户端连接并调用对象。
- 调用成功,打印hello
- 调用rmi服务需要先注册一个rmi服务,再lookup对象名,再注入中不方便实现,因此使用JNDIRMI,JDNIRMI只需要其中lookup()的参数可控就可以直接调用远程类加载。
2.JNDIRMI调用
- JNDI是 Java 提供的一种 标准化 API,用于统一访问不同类型的命名和目录服务(可以看成一个字典,一个字符串对应一个rmi远程对象)。
- JNDIRMI注入的核心原理就是通过控制 IinitialContext.lookup()参数,让其访问攻击者搭建的一个恶意的远程RMI服务器,通过将rmi的地址绑定一个Reference,这样目标服务器在调用远程rmi指定的类之前,就会去调用Reference绑定的恶意类,执行远程代码。
- 调用流程图
2.1.编写一个JNDIRMIdemo
- JNDIRMI服务器
1 | import javax.naming.InitialContext; |
- JNDIRMI客户端
1 | import javax.naming.InitialContext; |
- 编写恶意类
1 | import java.io.IOException; |
2.2.调用测试
- 启动rmi服务器
- 启动rmijndi服务器
- 启动恶意类http服务
- 启动jndirmi客户端
3.JNDIDAP服务调用
- 调用流程图
3.1. 编写一个JNDIDAPdemo
- JNDILDAPServer
1 | import javax.naming.InitialContext; |
- JNDILDAPClientdemo
1 | import javax.naming.InitialContext; |
- 下载LDAP服务器和客户端
https://directory.apache.org/apacheds/download/download-windows.html
https://directory.apache.org/studio/download/download-windows.html
一个用于启动服务器一个用户ldap客户端连接工具,或者使用仅studio启动服务器,但是不知道为什么我启动了马上又自动关闭了,因此我下载了apacheds来充当ldap服务器。
3.2.调用测试
- 首先启动ldap服务器。
- 启动失败,因此我换成了apacheds来启动服务器。
- 下载安装好之后,直接在服务中启动该程序。
- 然后使用studio客户端连接
- 然后点击完成就可以了。
- 然后启动JDNI服务器。
- 启动jdni客户端
4.JNDI 高版本绕过思路
4.1.思路
- 由于在8u191版本后VersionHelper12类中的loadClass方法加了一个if判断,trustURLCodebase默认为false,默认不会去加载远程的工厂类。因此之后的jndi注入都无法再直接注入,需要依靠其他的依赖进行攻击。
- 因此通过该方法无法再加载远程的Refference工厂类,但是我们可以使用本地的工厂类进行利用。
- 我们可以找实现了ObjectFactory的接口,可执行恶意命令的类。
1 | public Class<?> loadClass(String className, String codebase) |
4.2.实施
再tomcat8的依赖中存在这样一个可利用的BeanFactory,通过该类可执行EL表达式,实现命令执行。
因此想要绕过必须具有tomcat8的依赖,或者springboot,因为springboot项目中自带tomcat依赖。
首先在pom文件中导入以下依赖文件。
1 | <dependencies> |
- 编写RMIServer
1 | import java.rmi.AlreadyBoundException; |
- 编写JNDIRMIServer
1 | import javax.naming.InitialContext; |
- 编写JNDIRMIClient,靶机
1 | import javax.naming.InitialContext; |
- 成功运行三个服务后,命令执行成功弹出计算器。
5.总结
JDK6 | JDK7 | JDK8 | JDK11 | |
---|---|---|---|---|
RMI可用性 | 6u132以下 | 7u122以下 | 8u113以下 | 无 |
LDAP可用性 | 6u211以下 | 7u201以下 | 8u191以下 | 11.0.1以下 |
- JNDI注入的直接利用具有JDK版本限制,如果想利用高版本JDK,需要绕过refference无法加载远程Factory的限制,从而使用本地的Factory。
- 而本地的Factory目前需要用到tomcat8中的BeanFactory来实现执行EL表达式,执行系统命令。
- 该方式必须依赖tomcat8,而在8的高版本中删除了x字段,无法再继续利用。
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果