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

java代码审计工具_Java代码审计汇总系列(六)——RCE_第1张图片

一、概述

任意代码执行(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表达式,如下案例:

java代码审计工具_Java代码审计汇总系列(六)——RCE_第2张图片

常见的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工具类的,就会存在命令注入漏洞。

java代码审计工具_Java代码审计汇总系列(六)——RCE_第3张图片

同样,在某个.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)。

你可能感兴趣的:(java代码审计工具)