CVE-2024-32888
Description
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.)
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
com.amazon.redshift:redshift-jdbc42Maven | < 2.1.0.28 | 2.1.0.28 |
Patches
30d354a5f26caUpdate CHANGELOG.md for version 2.1.0.28
1 file changed · +12 −0
CHANGELOG.md+12 −0 modified@@ -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]
12a5e8ecfbb4More security improvements.
1 file changed · +58 −21
src/main/java/com/amazon/redshift/core/v3/SimpleParameterList.java+58 −21 modified@@ -284,27 +284,64 @@ public String toString(int index, boolean standardConformingStrings) { 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);
bc93694201a2Security improvements.
1 file changed · +70 −43
src/main/java/com/amazon/redshift/core/v3/SimpleParameterList.java+70 −43 modified@@ -184,103 +184,130 @@ public void setNull(int index, int oid) throws SQLException { 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; if (paramValues[index] == null) { 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
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-x3wm-hffr-chwmghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-32888ghsaADVISORY
- github.com/aws/amazon-redshift-jdbc-driver/commit/0d354a5f26ca23f7cac4e800e3b8734220230319nvdWEB
- github.com/aws/amazon-redshift-jdbc-driver/commit/12a5e8ecfbb44c8154fc66041cca2e20ecd7b339nvdWEB
- github.com/aws/amazon-redshift-jdbc-driver/commit/bc93694201a291493778ce5369a72befeca5ba7dnvdWEB
- github.com/aws/amazon-redshift-jdbc-driver/security/advisories/GHSA-x3wm-hffr-chwmnvdWEB
- github.com/pgjdbc/pgjdbc/security/advisories/GHSA-24rp-q3w6-vc56nvdWEB
- www.sonarsource.com/blog/double-dash-double-trouble-a-subtle-sql-injection-flawghsaWEB
- www.sonarsource.com/blog/double-dash-double-trouble-a-subtle-sql-injection-flaw/nvd
News mentions
0No linked articles in our index yet.