CVE-2024-32888 (published 2024-05-15T03:15Z)

The Amazon JDBC Driver for Redshift is a Type 4 JDBC driver that provides database connectivity through the standard JDBC application program interfaces (APIs) available in the Java Platform, Enterprise Editions. Prior to version 2.1.0.28, SQL injection is possible when using the non-default connection property `preferQueryMode=simple` in combination with application code which has a vulnerable SQL that negates a parameter value. There is no vulnerability in the driver when using the default, extended query mode. Note that `preferQueryMode` is not a supported parameter in Redshift JDBC driver, and is inherited code from Postgres JDBC driver. Users who do not override default settings to utilize this unsupported query mode are not affected. This issue is patched in driver version 2.1.0.28. As a workaround, do not use the connection property `preferQueryMode=simple`. (NOTE: Those who do not explicitly specify a query mode use the default of extended query mode and are not affected by this issue.)


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
commit_details: repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
author: Beaux Sharifi
author_date: 2024-05-14 16:41:41-07:00
msg: Update CHANGELOG.md for version 2.1.0.28
repository: repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
repo_name: aws/amazon-redshift-jdbc-driver
description: Redshift JDBC Driver. It supports JDBC 4.2 specification.
repo_language: Java
owner: aws
file_changes: filename: CHANGELOG.md
change_type: ModificationType.MODIFY
diff: @@ -1,6 +1,18 @@
 Changelog
 =========
 
+v2.1.0.28 (2024-05-14)
+----------------------
+- Security improvements (CVE-2024-32888)
+- Consolidated SDK API calls for retrieving cluster credentials for serverless instances.
+- Added logging of returned cluster identifiers during custom domain name resolution to aid debugging.
+- Added Object IDentifier (OID) mappings for missing Redshift data types.
+- Added null check for IsServerless property within IamHelper to address Dbeaver error (GitHub Issue #114)
+
+v2.1.0.27 (2024-05-07)
+----------------------
+- This version was published to Maven in error and is not recommended for use.
+
 v2.1.0.26 (2024-02-12)
 ----------------------
 - Enhanced capability to retrieve results of OUT parameters from stored procedures by parsing the result set [Bhavik Shah]

programming_language: Markdown
repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
commit_details: repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
author: Bhavik Shah
author_date: 2024-05-06 18:33:00-07:00
msg: More security improvements.
repository: repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
repo_name: aws/amazon-redshift-jdbc-driver
description: Redshift JDBC Driver. It supports JDBC 4.2 specification.
repo_language: Java
owner: aws
file_changes: filename: SimpleParameterList.java
change_type: ModificationType.MODIFY
diff: @@ -284,27 +284,64 @@ class SimpleParameterList implements V3ParameterList {
       textValue = paramValues[index].toString();
       int paramType = paramTypes[index];
 
-      if (paramType == Oid.TIMESTAMP) {
-        type = "timestamp";
-      } else if (paramType == Oid.TIMESTAMPTZ) {
-        type = "timestamp with time zone";
-      } else if (paramType == Oid.TIME) {
-        type = "time";
-      } else if (paramType == Oid.TIMETZ) {
-        type = "time with time zone";
-      } else if (paramType == Oid.DATE) {
-        type = "date";
-      } else if (paramType == Oid.INTERVAL) {
-        type = "interval";
-      } else if (paramType == Oid.INTERVALY2M) {
-        type = "interval year to month";
-      } else if (paramType == Oid.INTERVALD2S) {
-        type = "interval day to second";
-      } else if (paramType == Oid.NUMERIC) {
-        type = "numeric";
-      }
-      else {
-        type = null;
+      switch (paramTypes[index])
+      {
+        case Oid.INT2:
+          type = "int2";
+          break;
+        case Oid.INT4:
+          type = "int4";
+          break;
+        case Oid.INT8:
+          type = "int8";
+          break;
+        case Oid.FLOAT4:
+          type = "real";
+          break;
+        case Oid.FLOAT8:
+          type = "double precision";
+          break;
+        case Oid.TIMESTAMP:
+          type = "timestamp";
+          break;
+        case Oid.TIMESTAMPTZ:
+          type = "timestamp with time zone";
+          break;
+        case Oid.TIME:
+          type = "time";
+          break;
+        case Oid.TIMETZ:
+          type = "time with time zone";
+          break;
+        case Oid.DATE:
+          type = "date";
+          break;
+        case Oid.INTERVAL:
+          type = "interval";
+          break;
+        case Oid.INTERVALY2M:
+          type = "interval year to month";
+          break;
+        case Oid.INTERVALD2S:
+          type = "interval day to second";
+          break;
+        case Oid.NUMERIC:
+          type = "numeric";
+          break;
+        case Oid.UUID:
+          type = "uuid";
+          break;
+        case Oid.BOOL:
+          type = "boolean";
+          break;
+        case Oid.BOX:
+          type = "box";
+          break;
+        case Oid.POINT:
+          type = "point";
+          break;
+        default:
+          type = null;
       }
     }
     return quoteAndCast(textValue, type, standardConformingStrings);

programming_language: Java
repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
commit_details: repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
author: Bhavik Shah
author_date: 2024-05-06 18:14:19-07:00
msg: Security improvements.
repository: repo_url: https://github.com/aws/amazon-redshift-jdbc-driver
repo_name: aws/amazon-redshift-jdbc-driver
description: Redshift JDBC Driver. It supports JDBC 4.2 specification.
repo_language: Java
owner: aws
file_changes: filename: SimpleParameterList.java
change_type: ModificationType.MODIFY
diff: @@ -184,6 +184,30 @@ class SimpleParameterList implements V3ParameterList {
     bind(index, NULL_OBJECT, oid, binaryTransfer);
   }
 
+  private static String quoteAndCast(String text, String type, boolean standardConformingStrings)
+  {
+    StringBuilder sb = new StringBuilder((text.length() + 10) / 10 * 11); // Add 10% for escaping.
+    sb.append("('");
+    try {
+      Utils.escapeLiteral(sb, text, standardConformingStrings);
+    } catch (SQLException e) {
+      // This should only happen if we have an embedded null
+      // and there's not much we can do if we do hit one.
+      //
+      // To force a server side failure, we deliberately include
+      // a zero byte character in the literal to force the server
+      // to reject the command.
+      sb.append('\u0000');
+    }
+    sb.append("'");
+    if (type != null) {
+      sb.append("::");
+      sb.append(type);
+    }
+    sb.append(")");
+    return sb.toString();
+  }
+
   @Override
   public String toString(int index, boolean standardConformingStrings) {
     --index;
@@ -191,96 +215,99 @@ class SimpleParameterList implements V3ParameterList {
       return "?";
     } else if (paramValues[index] == NULL_OBJECT) {
       return "NULL";
-    } else if ((flags[index] & BINARY) == BINARY) {
+    }
+    String textValue;
+    String type;
+    if ((flags[index] & BINARY) == BINARY) {
       // handle some of the numeric types
-
       switch (paramTypes[index]) {
         case Oid.INT2:
           short s = ByteConverter.int2((byte[]) paramValues[index], 0);
-          return Short.toString(s);
+          textValue = Short.toString(s);
+          type = "int2";
+          break;
 
         case Oid.INT4:
           int i = ByteConverter.int4((byte[]) paramValues[index], 0);
-          return Integer.toString(i);
+          textValue = Integer.toString(i);
+          type = "int4";
+          break;
 
         case Oid.INT8:
           long l = ByteConverter.int8((byte[]) paramValues[index], 0);
-          return Long.toString(l);
+          textValue = Long.toString(l);
+          type = "int8";
+          break;
 
         case Oid.FLOAT4:
           float f = ByteConverter.float4((byte[]) paramValues[index], 0);
           if (Float.isNaN(f)) {
             return "'NaN'::real";
           }
-          return Float.toString(f);
+          textValue = Float.toString(f);
+          type = "real";
+          break;
 
         case Oid.FLOAT8:
           double d = ByteConverter.float8((byte[]) paramValues[index], 0);
           if (Double.isNaN(d)) {
             return "'NaN'::double precision";
           }
-          return Double.toString(d);
+          textValue = Double.toString(d);
+          type = "double precision";
+          break;
 
         case Oid.UUID:
-          String uuid =
+          textValue =
               new UUIDArrayAssistant().buildElement((byte[]) paramValues[index], 0, 16).toString();
-          return "'" + uuid + "'::uuid";
+          type = "uuid";
+          break;
 
         case Oid.POINT:
           RedshiftPoint pgPoint = new RedshiftPoint();
           pgPoint.setByteValue((byte[]) paramValues[index], 0);
-          return "'" + pgPoint.toString() + "'::point";
+          textValue = pgPoint.toString();
+          type = "point";
+          break;
 
         case Oid.BOX:
           RedshiftBox pgBox = new RedshiftBox();
           pgBox.setByteValue((byte[]) paramValues[index], 0);
-          return "'" + pgBox.toString() + "'::box";
+          textValue = pgBox.toString();
+          type = "box";
+          break;
+
+        default:
+          return "?";
       }
-      return "?";
     } else {
-      String param = paramValues[index].toString();
-
-      // add room for quotes + potential escaping.
-      StringBuilder p = new StringBuilder(3 + (param.length() + 10) / 10 * 11);
-
-      // No E'..' here since escapeLiteral escapes all things and it does not use \123 kind of
-      // escape codes
-      p.append('\'');
-      try {
-        p = Utils.escapeLiteral(p, param, standardConformingStrings);
-      } catch (SQLException sqle) {
-        // This should only happen if we have an embedded null
-        // and there's not much we can do if we do hit one.
-        //
-        // The goal of toString isn't to be sent to the server,
-        // so we aren't 100% accurate (see StreamWrapper), put
-        // the unescaped version of the data.
-        //
-        p.append(param);
-      }
-      p.append('\'');
+      textValue = paramValues[index].toString();
       int paramType = paramTypes[index];
+
       if (paramType == Oid.TIMESTAMP) {
-        p.append("::timestamp");
+        type = "timestamp";
       } else if (paramType == Oid.TIMESTAMPTZ) {
-        p.append("::timestamp with time zone");
+        type = "timestamp with time zone";
       } else if (paramType == Oid.TIME) {
-        p.append("::time");
+        type = "time";
       } else if (paramType == Oid.TIMETZ) {
-        p.append("::time with time zone");
+        type = "time with time zone";
       } else if (paramType == Oid.DATE) {
-        p.append("::date");
+        type = "date";
       } else if (paramType == Oid.INTERVAL) {
-        p.append("::interval");
+        type = "interval";
       } else if (paramType == Oid.INTERVALY2M) {
-        p.append("::interval year to month");
+        type = "interval year to month";
       } else if (paramType == Oid.INTERVALD2S) {
-        p.append("::interval day to second");
+        type = "interval day to second";
       } else if (paramType == Oid.NUMERIC) {
-        p.append("::numeric");
+        type = "numeric";
+      }
+      else {
+        type = null;
       }
-      return p.toString();
     }
+    return quoteAndCast(textValue, type, standardConformingStrings);
   }
 
   @Override

programming_language: Java