JNDI注入
内容提要
本文介绍JNDI注入攻击的原理、利用条件及不同JDK版本的限制。攻击者通过RMI或LDAP协议绑定恶意Reference或序列化对象,使客户端加载远程恶意类执行代码。文章提供示例代码,并说明高版本JDK可通过本地反序列化链绕过限制。
延伸解读
JNDI注入的利用条件与JDK版本限制
JNDI注入的利用条件包括客户端lookup()方法参数可控或服务端Reference的classFactoryLocation参数可控。JDK版本是关键限制:6u45、7u21后默认启用useCodebaseOnly,禁止远程加载类;6u141、7u131、8u121后RMI和CORBA的远程codebase被禁用;6u211、7u201、8u191后LDAP的远程codebase也被禁用。因此,高版本JDK下传统远程codebase方式失效,需寻找其他利用途径。
高版本JDK的绕过思路:本地反序列化链
在JDK 8u191等版本中,LDAP的Reference方式被限制,但LDAP仍可存储Java序列化对象。当返回属性中存在javaSerializedData时,客户端会调用readObject进行反序列化。攻击者可利用本地ClassPath中的反序列化利用链(如Commons-Collections)构造恶意序列化数据,通过LDAP服务返回,实现代码执行。这种方式不依赖远程codebase,因此不受trustURLCodebase限制。
实际利用中的注意事项
利用JNDI注入时,需注意目标JDK版本,不同版本对应不同利用方式。例如,JDK 7下可使用RMI Reference方式,而JDK 8u191后需使用LDAP序列化对象方式。此外,攻击者需搭建恶意RMI或LDAP服务,并确保恶意类或序列化数据可被目标访问。文章示例中,攻击者通过RMI绑定恶意Reference,并利用HTTP服务提供恶意class文件,成功执行命令。
Q&A
什么是JNDI注入攻击?
JNDI注入是一种通过可控的JNDI lookup()参数或Reference的classFactoryLocation参数,使客户端访问恶意RMI或LDAP服务,加载远程恶意类并执行代码,从而实现远程代码执行的攻击方式。
JNDI注入的利用条件有哪些?
利用条件包括:客户端的lookup()方法参数可控,或服务端使用Reference时classFactoryLocation参数可控。此外,JDK版本也影响利用方式,不同版本对远程codebase的限制不同。
不同JDK版本对JNDI注入有什么限制?
JDK 6u45、7u21之后,java.rmi.server.useCodebaseOnly默认设为true,禁用自动加载远程类;JDK 6u141、7u131、8u121之后,com.sun.jndi.rmi.object.trustURLCodebase默认false,禁止RMI和CORBA远程codebase;JDK 6u211、7u201、8u191之后,com.sun.jndi.ldap.object.trustURLCodebase默认false,禁止LDAP远程codebase。
JNDI注入的两种主要方式是什么?
两种方式:一是通过RMI或LDAP绑定恶意Reference,使客户端加载远程类;二是通过LDAP返回序列化对象,利用本地反序列化链执行代码。
高版本JDK下如何绕过JNDI注入的限制?
高版本JDK下,远程codebase方式基本失效,但可以通过LDAP返回序列化对象,利用本地ClassPath中的反序列化链(如CommonsCollections)来执行代码,这种方式不受trustURLCodebase限制。
JNDI注入的示例中,恶意对象如何执行命令?
示例中恶意对象EvilObj在静态代码块中调用exec("gnome-calculator"),当客户端加载该类时,静态代码块自动执行,从而弹出计算器。