
[CVE-2022-41828] Exécution de code à distance (RCE) dans le pilote JDBC Amazon AWS Redshift
Le pilote JDBC Amazon pour Redshift est un pilote JDBC de type 4 qui assure la connectivité à la base de données via les interfaces de programmation d'applications (API) JDBC standard disponibles dans les éditions Java Platform, Enterprise. Le pilote donne accès à Redshift depuis toute application Java, tout serveur d'applications ou toute applet compatible Java.
Un problème potentiel d'exécution de commandes à distance existe dans les versions 2.1.0.7 et antérieures de redshift-jdbc42. Lorsque des plugins sont utilisés avec le pilote, celui-ci instancie les instances de plugins sur la base des noms de classes Java fournis via les propriétés de connexion sslhostnameverifier, socketFactory, sslfactory et sslpasswordcallback. Dans les versions affectées, le pilote ne vérifie pas si une classe de plugin implémente l'interface attendue avant l'instanciation. Cela peut conduire au chargement de classes Java arbitraires, qu'un attaquant averti contrôlant l'URL JDBC peut utiliser pour parvenir à une exécution de code à distance.
Ce problème est corrigé dans redshift-jdbc-42 version 2.1.0.8 et ultérieures.
AWS recommande aux clients utilisant des plugins de mettre à niveau vers redshift-jdbc42 version 2.1.0.8 ou ultérieure. Il n'existe aucune solution de contournement connue pour ce problème.
Afin de corriger ce problème, des modifications ont été apportées à 4 classes Java différentes dans le commit aws/amazon-redshift-jdbc-driver@9999659. Ces classes sont respectivement les suivantes.
@@ -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) {

Pour reproduire CVE-2022-41828, une application Java vulnérable utilisant le framework Spring et intégrant le pilote vulnérable redshift-jdbc42 version 2.1.0.7 comme bibliothèque externe a été développée.