专栏首页卓文见识Java代码审计汇总系列(六)——RCE

Java代码审计汇总系列(六)——RCE

一、概述

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

常见的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方法并解析执行:

常用的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.eval
org.mvel2.MVELInterpretedRuntime.parse
org.mvel2.ast.ASTNode.getReducedValue
org.mvel2.PropertyAccessor.get
org.mvel2.MVEL.execute
org.mvel2.compiler.ExecutableStatement.getValue
org.mvel2.compiler.ExecutableAccesso
org.mvel2.ast.NewObjectNode.getReducedValueAccelerated
org.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工具类的,就会存在命令注入漏洞。

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

<#assign test="freemarker.template.utility.Execute"?new()>
${test("calc")}

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

2)freemarker.template.utility.ObjectConstructor

<#assign ob="freemarker.template.utility.ObjectConstructor"?new()>
<#assign br=ob("java.lang.ProcessBuilder","calc").start()>

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

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

freemarker.template.Template.process
freemarker.core.Environment.process
freemarker.template.TemplateMethodModel.exec
freemarker.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.groovy
 
import 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.me
groovy.lang.GroovyShell.parse|evaluate
groovy.lang.Script.run
groovy.lang.GroovyClassLoader.parseClass
org.codehaus.groovy.runtime.InvokerHelper.newScript|createScript|runScript
org.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)。

本文分享自微信公众号 - 卓文见识(zhuowenjianshi),作者:Jayway

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 浏览器解析与编码顺序及xss挖掘绕过全汇总

    在以往的培训和渗透过程中,发现很多渗透人员尤其是初学者在挖掘xss漏洞时,很容易混淆浏览器解析顺序和解码顺序,对于html和js编码、解码和浏览器解析顺序、哪些...

    Jayway
  • Java代码审计汇总checklist(一)

    重点查看SQL语句是否是拼接而成,且拼接的各个位置的参数值是否可以外部输入,熟悉存在即不存在漏洞的代码写法,如没有SQL注入的java片段:

    Jayway
  • JSON相关漏洞(Hijacking+Injection)挖掘技巧及实战案例全汇总

    本文一是在为测试过程中遇到json返回格式时提供测试思路,二是几乎所有国内的资料都混淆了json和jsonp的区别——这是两种技术;以及json和js...

    Jayway
  • SpringBoot 整合 Redis 的简单案例

    5).新建一个config包,用来存放一些配置文件,新建RedisConfig.java

    凯哥Java
  • 原创投稿 | 如何为Django添加中文搜索服务

    云豆贴心提醒,本文阅读时间7分钟 在使用python的过程中,必然会设计到如何创建web应用,而搜索功能却最为常见,该文档包含了如何整合haystack,el...

    小小科
  • CVE-2017-8759完美复现(另附加hta+powershell弹框闪烁解决方案)

    CVE-2017-8759 是前几天出的 0 DAY ,搜了下,国内几乎没有人复现,这个洞总体来说,危害很大,而且比CVE-2017-0199 更难防御。 漏...

    FB客服
  • Docker + Elasticsearch 集群环境搭建

    无论是安装包形式还是基于Docker,搭建Elasticsearch集群环境还是较为简单的,实操的时候还遇到过一丢小问题,本文用于记录下操作过程。

    happyJared
  • Android SurfaceView学习示例

    SurfaceView是View的子类,使用的方式与任何View所派生的类都是完全相同的,可以像其他View那样应用动画,并把它们放到布局中。  Surfac...

    阳光岛主
  • Eclipse Jetty JettyLauncher 问题解决与使用技巧

    Eclipse Jetty JettyLauncher java.net.SocketException: Unrecognized Windows Socke...

    阿敏总司令
  • 从ORA-01752的错误,透过现象看本质

    这几天开发同学反映了一个问题,有一个Java写的夜维程序,用于每天定时删除历史过期数据,3月10日之前经过了内测,但这两天再次执行的时候,有一条SQL语句一直报...

    bisal

扫码关注云+社区

领取腾讯云代金券