高版本JDK下JNDI漏洞利用方法精简总结
编辑前言
高版本JDK在RMI和LDAP的 trustURLCodebase 做了限制,修复后的JDK版本无法在不修改该参数的情况下通过远程加载ObjectFactory类的方式执行Java代码。目前公开常用的利用方法有通过Tomcat的 org.apache.naming.factory.BeanFactory 工厂类调用 javax.el.ELProcessor#eval 方法或 groovy.lang.GroovyShell#evaluate 方法,以及通过LDAP的 javaSerializedData 反序列化gadget,但在一些特殊情况下这些方法可能不适用,于是探讨其他利用方法。
基于BeanFactory的利用方法
绕过原理
LDAP和RMI收到服务端反序列化的 Reference 对象后,会根据 classFactory 属性从本地classpath中实例化一个ObjectFactory对象,然后调用其 getObjectInstance 方法。Tomcat的 org.apache.naming.factory.BeanFactory 类会把 Reference 对象的 className 属性作为类名实例化对象,从 Reference 对象的Addrs参数集合中获取 forceString 类型的参数,按逗号和等号分割后,根据propName作为方法名称反射调用相应方法。 javax.el.ELProcessor#eval 和 groovy.lang.GroovyShell#evaluate 这两个方法可只传一个String参数执行攻击代码,且依赖库常见,因此被经常使用。
可用的利用类
MLet:JDK自带的
javax.management.loading.MLet类,继承自URLClassloader,有一个无参构造方法和addURL(String)、loadClass(String)方法。可用于gadget探测,但单靠ClassLoader.loadClass无法触发static代码块,暂时无法RCE。GroovyClassLoader:原理和MLet基本相同,可实现RCE,但由于已有
groovy.lang.GroovyShell可用,该类价值不大。SnakeYaml:
new org.yaml.snakeyaml.Yaml().load(String)符合条件,依赖库使用比Groovy更常见,有一定利用价值。XStream:
new com.thoughtworks.xstream.XStream().fromXML(String)符合条件,可用于攻击。MVEL:入口
org.mvel2.MVEL#eval(String)因无参构造方法是private修饰,不符合条件,但可从org.mvel2.sh.ShellSession#exec(String)进入,通过执行内置命令调用MVEL.eval解析表达式。NativeLibLoader:JDK的
com.sun.glass.utils.NativeLibLoader类有loadLibrary(String)方法,可加载指定路径的动态链接库文件,结合WEB功能或写文件gadget上传动态链接库后可执行命令。
XXE & RCE
漏洞发现
通过搜索实现 javax.naming.spi.ObjectFactory 接口的类,发现Tomcat的 org.apache.catalina.users.MemoryUserDatabaseFactory 工厂类可能存在漏洞。该类会实例化 MemoryUserDatabase 对象,从 Reference 中取出 pathname、readonly 参数赋值,然后调用 open() 和 save() 方法。
XXE漏洞
open() 方法会根据 pathname 发起本地或远程文件访问,使用commons-digester解析返回的XML内容,存在XXE漏洞。
RCE漏洞及利用方法
问题分析:在Linux系统下,由于目录跳转问题,需要在
CATALINA.BASE文件夹下创建特定目录,可使用BeanFactory执行创建目录的利用类,如org.h2.store.fs.FileUtils#createDirectory(String)。利用方法:
创建Tomcat管理员:让JNDI返回特定的
ResourceRef对象,可覆盖CATALINA.BASE/conf/tomcat-users.xml文件,实现创建Tomcat管理员的目的。写Webshell:让JNDI返回另一个
ResourceRef对象,可将包含攻击代码的XML写入web目录,实现写Webshell的功能。
JDBC RCE
根据classpath下可用的jdbc驱动构造相应的payload,实现RCE。
dbcp
分为dbcp1和dbcp2,又分为commons-dbcp和Tomcat自带的dbcp。当 InitialSize > 0 时,会调用 getLogWriter 方法创建数据库连接。提供了不同版本dbcp的RCE方法。
tomcat - jdbc
可使用 org.apache.tomcat.jdbc.pool.DataSourceFactory 实现RCE。
druid
参考《JNDI jdk高版本绕过—— Druid》 ,和dbcp原理一样,可构造相应的 Reference 对象实现RCE。
Deserialize
虽然在查看 ObjectFactory 时发现有几个类有反序列化的地方,但JNDI本身就能反序列化。
引用
- 0
- 0
-
分享