Apache Commons Configuration远程代码执行漏洞分析
首先可以看一下官方的漏洞描述:
https://lists.apache.org/thread/tdf5n7j80lfxdhs2764vn0xmpfodm87s
Apache Commons Configuration performs variable interpolation, allowing properties to be dynamically evaluated and expanded. The standard format for interpolation is “${prefix:name}”, where “prefix” is used to locate an instance of org.apache.commons.configuration2.interpol.Lookup that performs the interpolation. Starting with version 2.4 and continuing through 2.7, the set of default Lookup instances included interpolators that could result in arbitrary code execution or contact with remote servers. These lookups are:
– “script” – execute expressions using the JVM script execution engine (javax.script)
– “dns” – resolve dns records
– “url” – load values from urls,
including from remote servers Applications using the interpolation defaults in the affected versions may be vulnerable to remote code execution or unintentional contact with remote servers if untrusted configuration values are used. Users are recommended to upgrade to Apache Commons Configuration 2.8.0, which disables the problematic interpolators by default.
翻译一下就是Apache Commons Configuration允许动态的插值,标准格式是${prefix:name},会根据prefix的值去寻找对应的lookup方法,支持script,dns,url等方法。
首先下载一下有漏洞的代码,版本2.4-2.7的都在范围。
然后看到src/main/java/org/apache/commons/configuration2/interpol/DefaultLookups.java 枚举类支持的lookup方法,可以看到支持:
SCRIPT:
URL:
DNS:
去跟进一下加载配置的整个流程,然后看一下如何触发命令执行的代码:
pom.xml:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-configuration2</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
CVE_2022_33980.java
public class CVE_2022_33980 {
public static void main(String[] args) throws ConfigurationException {
Configurations configs = new Configurations();
// 每个Configuration代表这一个配置文件~(依赖beanutils这个jar)
Configuration config = configs.properties("my.properties");
// 遍历
Iterator<String> keys = config.getKeys();
while (keys.hasNext()) {
String key = keys.next();
String value = config.getString(key);
System.out.println(key + " = " + value);
}
}
}
java.home = ${url:https://www.baidu.com}
首先在config.getString下断点:
跟进到org.apache.commons.configuration2.interpol.ConfigurationInterpolator#interpolate:
首先判断了是否以${开头,}结尾:
然后进入到org.apache.commons.configuration2.interpol.ConfigurationInterpolator#resolveSingleVariable:
去除了首尾的${}:
继续跟进resolve方法,可以看到将strValue用:分割
然后跟进fetchLookupForPrefix方法,可以看到这里获取了StringLookupAdapter:
最后通过调用lookup方法,最终调用了org.apache.commons.text.lookup.UrlStringLookup#lookup方法去请求URL:
其他可以利用的标签如javascript、dns等同理。