CVE-2022-42889 Apache Commons Text RCE 漏洞分析与 CodeQL
字数 1050
更新时间 2025-08-18 17:33:44

Apache Commons Text RCE漏洞(CVE-2022-42889)分析与CodeQL实践

0x01 漏洞概述

漏洞描述:
Apache Commons Text组件在执行变量插值(variable interpolation)时存在远程代码执行漏洞。该组件允许动态评估和扩展属性,标准格式为${prefix:name},其中"prefix"用于查找执行插值的StringLookup实例。在1.5到1.9版本中,默认的Lookup实例集包含可能导致任意代码执行或与远程服务器交互的插值器。

影响版本: 1.5 <= Apache Commons Text <= 1.9

0x02 环境搭建

在Maven项目中添加依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.9</version>
</dependency>

0x03 漏洞复现

基本使用示例

final StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
final String text = interpolator.replace(
    "Base64 Decoder: ${base64Decoder:SGVsbG9Xb3JsZCE=}\n" +
    "Base64 Encoder: ${base64Encoder:HelloWorld!}\n" +
    // 其他插值示例...
);

漏洞利用PoC

import org.apache.commons.text.StringSubstitutor;

public class EXP {
    public static void main(String[] args) {
        StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
        String payload = "${script:js:new java.lang.ProcessBuilder(\"calc\").start()}";
        interpolator.replace(payload);
    }
}

0x04 漏洞分析

关键调用链

  1. StringSubstitutor.createInterpolator()创建字符串替换器
  2. replace()方法调用substitute()方法
  3. 最终调用到org.apache.commons.text.StringSubstitutor#substitute
  4. 解析变量名后调用resolveVariable()
  5. 最终到达org.apache.commons.text.lookup.ScriptStringLookup#lookup

关键点

  • 处理payload时对:前后内容进行Split操作
  • JavaScript引擎被实例化并执行恶意代码
  • 通过scriptEngine.eval()执行任意JavaScript代码

0x05 漏洞修复

在1.11.0版本中移除了不安全的插值器:

  • script
  • dns
  • url

0x06 CodeQL实践

数据库构建注意事项

错误方式:

codeql database create DB_DIR --language=java --command='mvn clean install'

正确方式:

  1. 提取所有相关包(包括JDK和漏洞包)
  2. 反编译这些包
  3. 使用extract-java构造CodeQL数据库

CodeQL查询

Sink点定义

class ScriptEngineEval extends DataFlow::Node {
    ScriptEngineEval() {
        exists(MethodAccess ma | 
            ma.getCallee().hasName("eval") and
            ma.getCallee().getDeclaringType().getASupertype*()
                .hasQualifiedName("javax.script", "ScriptEngine") and
            this.asExpr() = ma.getArgument(0)
        )
    }
}

Source点定义

class PublicMethodParameter extends DataFlow::Node {
    PublicMethodParameter() {
        exists(Method m, Parameter p | 
            m.getDeclaringType().isPublic() and
            m.isPublic() and
            p = m.getAParameter() and
            p.getType().hasName("String") and
            this.asParameter() = p
        )
    }
}

完整查询

/**
 * @kind path-problem
 */
import java
import semmle.code.java.dataflow.DataFlow
import DataFlow::PathGraph 
import semmle.code.java.dataflow.TaintTracking

class Config extends TaintTracking::Configuration {
    Config() { this = "config" }
    
    override predicate isSource(DataFlow::Node source) {
        source instanceof PublicMethodParameter
    }
    
    override predicate isSink(DataFlow::Node sink) {
        sink instanceof ScriptEngineEval
    }
}

from Config cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink, source, sink, "path"

0x07 总结

  1. 该漏洞源于Apache Commons Text组件中不安全的插值器实现
  2. 通过script:前缀可以执行任意JavaScript代码
  3. 使用CodeQL可以有效识别此类漏洞,但需要注意数据库构建方式
  4. 修复方案是移除危险的插值器前缀

参考链接

  • https://l3yx.github.io/2022/12/17/用CodeQL分析漏洞-CVE-2022-42889/
相似文章
相似文章
 全屏