java代码审计工具_Java代码审计汇总系列(六)——RCE

本文详细探讨了Java中的远程代码执行(RCE)漏洞,包括OS命令注入、表达式注入(如SpEL、OGNL、MVEL、Fel)、模板注入(如Velocity、FreeMarker)和代码注入(如Groovy)。分析了各类型的审计技巧和典型payload,同时提供了防范措施。
摘要由CSDN通过智能技术生成

02a41cf8c9900074580b83ed6dc2452c.png

一、概述

任意代码执行(Remote Code Execution)是危害最为严重的漏洞之一,挖掘难度也是相对高的,除了常见的文件上传漏洞,还有OS命令注入、表达式注入、模板注入、代码注入和第三方组件漏洞,下面依次讲解审计方法和技巧。

二、分类挖掘技巧

1、OS命令注入

OS命令注入涉及执行系统命令,通过关键字定位执行命令的方法是否参数可控,常用的搜索关键字有:

System|exec|passthru|popen|shell_exec|eval|preg_replace|str_replace|call_user_func|getRuntime().exec|system|execlp|execvp|ShellExecute|wsystem|popen(|getRuntime|ProcessBuilder|execfile|input|Shell|ShellExecuteForExplore(|ShellExecute|execute|.exec|/bin/sh、/bin/bash|cmd

一个典型的OS命令注入案例:

public class RuntimeExec {public static Boolean runtimeExec(String cmd){try {Process proc = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c", cmd});StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");

2、表达式注入

主流的Java表达式主要有OGNL、SpEL、MVEL、EL、Fel、jstl_el等。

2.1 SpEL

Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。在spring中使用parseExpression()方法解析SPEL表达式,使用expression.getValue()方法执行SPEL表达式,如下案例:

e920d1330ccd4a9d0632a0c2f825110b.png

常见的payload是

org.springframework.expression.Expressionexp=parser.parseExpression("T(java.lang.Runtime).getRuntime().exec('calc')");

因此审计SPEL表达式注入需要搜索的关键字有:

org.springframework.expression|parseExpression|getValue|getValueType|value="#{*}

然后逐层跟踪调用关系链,如果parseExpression、getValue、getValueType传入的参数外部可控,就存在spel注入的安全风险,对应的防御办法也是通过白名单限制入参。

2.2  OGNL

OGNL是最常见的表达式之一,Struts2也是因为OGNL表达式而“臭名昭著”。它是Object-Graph Navigation Language的缩写,主要的功能是对对象进行处理,包括存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等。

漏洞产生的原因多为代码调用OGNL的getValue方法并解析执行:

bf50b7d55438b528ebaf54c286a6ba02.png

常用的payload为:

%{@java.lang.Runtime@getRuntime().exec('calc')}

因此审计OGNL表达式注入需检索importognl.*,检查产品是否引用ognl相关类,检查使用了ognl相关代码类的getValue方法和setValue方法是否存在外部参数可控。

2.3 Fel

Fel(Fast Expression Language),是一种开源表达式引擎,支持解释执行和编译执行,支持直接调用任何第三方类中的方法,这种功能使得fast-el表达式可以具有java代码一样的能力,虽然本身对一些危险函数进行了黑名单校验,但因存在遗漏从而造成任意代码执行。

Fel的RCE主要通过其支持的 $ 和 . 运算触发,即通过“$(‘class’).method”形式的语法,调用类和方法,如项目调用了上面的OGNL,则可以对其调用:

$(ognl.Ognl).getvalue(\” @java.lang.Runtime@getRuntime().exec('calc.exe')\”,null)

审计中可搜索importcom.greenpineyu.fel检查是否使用Fel表达式,而后搜索eval/compile函数入参是否外部可控。

防范办法可采用黑名单,禁用$ 和  . 操作符或白名单方法控制表达式中可以的类,修改FelBuilder类中的newSecurityMgr函数,改成默认使用白名单的方式(return new RegexSecurityMgr(enables, null);),并根据实际情况配置允许调用的java类。

2.4 MVEL

MVEL表达式旨在成为更有效的表达式语言,比如直接支持集合、数组和字符串匹配,正则表达式的运算操作等,一般通过MVEL.eval(expression,paramMap)或execute执行,使用的payload一般为:

new java.lang.ProcessBilder(“calc”).start();

审计时搜索org.mvel2相关类,搜索关键字:

org.mvel2.MVEL.evalorg.mvel2.MVELInterpretedRuntime.parseorg.mvel2.ast.ASTNode.getReducedValueorg.mvel2.PropertyAccessor.getorg.mvel2.MVEL.executeorg.mvel2.compiler.ExecutableStatement.getValueorg.mvel2.compiler.ExecutableAccessororg.mvel2.ast.NewObjectNode.getReducedValueAcceleratedorg.mvel2.optimizers.AccessorOptimizer|org.mvel2.optimizers.dynamic.DynamicOptimizer.optimizeObjectCreation

3、模板注入

模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。可以让程序实现界面与数据分离,业务代码与逻辑代码的分离。这方面的介绍参考之前的文章:模板注入漏洞全汇总。

主流的java后端模板引擎包括JSP、Freemarker、Velocity、Thymeleaf等。

3.1 Velocity

Velocity是较为常用的模板引擎,它的RCE主要通过两种方式实现

1)反射机制:

velocity的标签中支持$abc 这样的语法,如果abc是一个对象,则写模板时就可以利用它来进行反射,调用一些该对象的方法。如:

#set ($exec = "test")$exec.class.forName("java.lang.Runtime").getRuntime().exec("calc")

在任意一个.vm文件中注入payload,和在代码中自己调用velocity的解析表达式去执行,结果是相同的。

2)VelocityTools

如果产品有引用velocity-tools的jar包,那么只要在toolbox.xml中配置了ClassTool工具类的,就会存在命令注入漏洞。

1dfe964ce1178ae4680e0f434575dbf0.png

同样,在某个.vm文件中输入payload效果也是一样的:

$class.inspect("java.lang.Runtime").type.getRuntime().exec("calc").waitFor()

审计中要确定是否引用org.apache.velocity相关类,关注evalutate、execute和render的传参是否可控。

3.2 Freemarker

FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。

已公开的有两个可以用来构造命令注入payload:

1)freemarker.template.utility.Execute

${test("calc")}

第一句新建一个类的实例test,第二句通过$赋值执行。

2)freemarker.template.utility.ObjectConstructor

首先新建一个类的实例ob,然后用ob构造一个ProccessBuilder的对象,之后通过创建新变量的方式,把ob构造对象的start方法执行结果赋值给新的变量。

审计中首先要关注是否存在ftl后缀名文件,正向跟踪在何处被处理执行,内容是否外部可控;或搜索是否引用freemarker相关类,关注类和方法:

freemarker.template.Template.processfreemarker.core.Environment.processfreemarker.template.TemplateMethodModel.execfreemarker.template.utility.Execute.exec

4、代码注入

在其他语言里也存在代码注入的漏洞,但在java环境中存在一些脚本语言,典型的有Groovy、JavascriptEngine(ScriptEngineManager)、Jython等。

4.1 Groovy

Groovy是一种基于Java平台的面向对象语言,和java非常的相似,可以兼容所有的java语法。主要有两种漏洞场景:

1)Groovy文件

Groovy 文件可以编译成标准的 Java 类文件并在 Java 代码中重用。如果Groovy文件可外部导入或可修改内容,则可通过在Groovy文件中注入代码,反射调用java的类达到执行任意命令的目的。

TestReflect.groovyimport java.lang.reflect.Method;Class> rt =Class.forName("java.lang.Runtime");Method gr =rt.getMethod("getRuntime");Method ex =rt.getMethod("exec", String.class);ex.invoke(gr.invoke(null),"calc.exe");

2)引用groovy类

使用java调用groovy的方法,如果groovy表达式可通过外部传入且防护校验不足,攻击者可注入恶意代码实现代码注入,执行groovy表达式的类方法一般有:

groovy.util.Eval.megroovy.lang.GroovyShell.parse|evaluategroovy.lang.Script.rungroovy.lang.GroovyClassLoader.parseClassorg.codehaus.groovy.runtime.InvokerHelper.newScript|createScript|runScriptorg.codehaus.groovy.runtime.MethodClosure.MethodClosure

审计中需关注动态脚本编辑、模板导入功能,代码层搜索是否调用org.codehaus.groovy包,如下通过InvokeHelper. newScript方法加载Groovy脚本并执行:

5、第三方组件

查看引用的第三方开源组件,如引用了Fastjson<1.2.60,Shiro<=1.2.4,Xstream<1.4.11,Jackson-databind2.0.0-2.9.9.1,Spring Data Commons,Struts2.0.4-2.3.34/2.5.0-2.5.16,weblogic等存在漏洞的组件均可直接使用Nday进行任意代码执行(RCE)。

org.mvel2.PropertyAccessException: [Error: null pointer: xsetz.indexOf('.')] [Near : {... xsetz.indexOf('.') > 0 ....}] ^ [Line: 1, Column: 1] at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:450) at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:163) at org.mvel2.optimizers.dynamic.DynamicOptimizer.optimizeAccessor(DynamicOptimizer.java:80) at org.mvel2.ast.ASTNode.optimize(ASTNode.java:159) at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:115) at org.mvel2.ast.BinaryOperation.getReducedValueAccelerated(BinaryOperation.java:125) at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85) at org.mvel2.compiler.CompiledExpression.getDirectValue(CompiledExpression.java:123) at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:119) at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:113) at org.mvel2.MVEL.executeExpression(MVEL.java:929) at com.creating.services.mdruleexecute.MdruleMain.lambda$runMdResult$0(MdruleMain.java:85) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NullPointerException: null at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:383) ... 14 common frames omitted
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值