Ce mail provient de l'extérieur, restons vigilants ===================================================================== CERT-Renater Note d'Information No. 2026/VULN1013 _____________________________________________________________________ DATE : 13/10/2026 HARDWARE PLATFORM(S): / OPERATING SYSTEM(S): Systems running org.postgresql:postgresql (Maven) versions prior to 42.7.14. ==================================================================== https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-rhp9-mr79-r74h https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-hggc-j2qh-988m https://github.com/pgjdbc/pgjdbc/security/advisories/GHSA-f64h-wr5q-3qf3 _____________________________________________________________________ requireAuth is silently not enforced when the value excludes every authentication method Moderate sehrope published GHSA-rhp9-mr79-r74h Package org.postgresql:postgresql (Maven) Affected versions >= 42.7.11, <= 42.7.13 Patched versions 42.7.14 Description Impact When the requireAuth connection property excludes all six authentication methods the driver knows, for example requireAuth=!password,!md5,!gss,!sspi,!scram-sha-256,!none, the driver enforces no restriction and accepts any method the server asks for, including cleartext password. An attacker positioned between the application and its server can then ask for cleartext password authentication and receive the database password. The six exclusions may appear in any order, with or without spaces around the commas. A value with no method in it, such as requireAuth=,, is affected the same way. Other values are not affected. A positive list such as requireAuth=scram-sha-256, and a partial exclusion such as requireAuth=!password,!md5, are both enforced correctly. The property has no default value, so a deployment that does not set it is unaffected. A value that excludes every method denies every method, so with the fix in place such a configuration cannot complete any connection. Nobody sets such a value on purpose, so an affected deployment has it by mistake, and on affected versions its connections work normally, which hides the mistake. Patches See https://github.com/pgjdbc/pgjdbc/releases/tag/REL42.7.14 After the upgrade, a connection whose requireAuth value excludes every method is refused with SQLState 08004 and the message Authentication method is not allowed by requireAuth, or with the channel binding error when channelBinding=require is also set. A value with no method in it is rejected as an invalid requireAuth value. Replace such a value with a positive list of the methods your server uses, as described under Workarounds. Workarounds If your requireAuth value excludes all six methods or names none, replace it with a positive list of the methods your server actually uses, for example requireAuth=scram-sha-256. A positive list is enforced correctly on every affected version. A deployment that uses SCRAM over TLS can also set channelBinding=require. It refuses every authentication request other than SCRAM, cleartext password included. It is available in every affected version and needs a server that offers SCRAM-SHA-256-PLUS, so a deployment that uses md5, GSS, or SSPI cannot use it. Independently of this issue, verify the server certificate with sslmode=verify-full against a trusted CA, which is what prevents an attacker from presenting a substitute server in the first place. Root cause AuthMethod.parseRequireAuth returns null both when the property is unset and when the value leaves no method allowed, and AuthMethod.checkAuth treats null as "no restriction". The value that should allow no method therefore allows every method. Severity Moderate 5.9/ 10 CVSS v3 base metrics Attack vector Network Attack complexity High Privileges required None User interaction None Scope Unchanged Confidentiality High Integrity None Availability None CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N CVE ID CVE-2026-107314 Weaknesses WeaknessCWE-636 _____________________________________________________________________ Driver stores bytes of earlier messages in place of a large value on GSS-encrypted connections Moderate davecramer published GHSA-hggc-j2qh-988m Package org.postgresql:postgresql (Maven) Affected versions >= 42.7.4, < 42.7.6 Patched versions 42.7.6 Description Summary On a connection with GSS encryption (gssEncMode=prefer or require), pgjdbc 42.7.4 and 42.7.5 can send the previous contents of the GSS send buffer in place of the first 16320 bytes of a value, and the server stores the value without an error. The stored value then holds bytes of the messages the driver sent just before it on that connection, such as the statement's SQL text, its other parameters, and earlier rows of the same batch, instead of the bytes the application supplied. 42.7.6 fixed the defect in PR #3500, which reported only the ArrayIndexOutOfBoundsException described below. 42.7.3 and earlier, and connections without GSS encryption, are not affected. Details GSSOutputStream.write(byte[], int, int) sends each buffer-length chunk of a long write straight from the caller's array, through writeWrapped(b, off, buf.length). In 42.7.4 and 42.7.5, writeWrapped hands the stream's own buffer to GSS instead of its argument: private void writeWrapped(byte[] b, int off, int len) throws IOException { try { byte[] token = gssContext.wrap(buf, off, len, messageProp); off is an offset into the caller's array, so the call wraps buf[off, off + buf.length). The buffer is sized to the GSS wrap limit for a 16380-byte token, 16320 bytes with MIT Kerberos. Two outcomes follow: When off is not 0, the range runs past the end of buf, and the write fails with ArrayIndexOutOfBoundsException, which the application sees as An I/O error occurred while sending to the backend. This is the failure PR #3500 fixed. When off is 0, the call wraps the buffer as it stands, and the server receives the previous buffer contents in place of the first 16320 bytes of the value. A write shorter than two buffers raises no exception, and the server stores the value; a longer write fails on its second chunk. off is 0 at the first chunk when the write starts at array offset 0 and the GSS buffer is empty or exactly full as the write begins. The buffer is exactly full when the bytes written before the value, such as the message header and the value's length, end exactly at the end of the buffer. It is empty when an earlier write of the same value ended there, as with a ByteStreamWriter that writes its data in several calls. Which case applies depends on the sizes of what the driver wrote before the value. A value the driver writes from a byte array in one call reaches this code: a bind parameter in text or binary form (setString, setBytes), a ByteStreamWriter bind parameter, CopyIn.writeToCopy, and LargeObject.write. InputStream parameters such as setBinaryStream go through the buffer and are not affected. The code came with eeb37dd ("perf: replace BufferedOutputStream with unsynchronized PgBufferedOutputStream, increase the send buffer size"), first released in 42.7.4. 96f6862 fixed it, released in 42.7.6: - byte[] token = gssContext.wrap(buf, off, len, messageProp); + byte[] token = gssContext.wrap(b, off, len, messageProp); PoC GssWrap.java binds a ByteStreamWriter whose data comes in two writes. The first brings the GSS send buffer to a chosen fill level; the second writes 16420 bytes of 'B', 100 more than the buffer holds, from array offset 0. The other parameter of the same INSERT carries a marker. The program reads the buffer's fill level through reflection only to reach the alignment on every run; in an application, the sizes of the preceding messages decide it. run.sh runs in a throwaway postgres:17 container. It starts an MIT Kerberos KDC and a PostgreSQL server that accepts only hostgssenc, then runs GssWrap with each driver jar in /probe: javac --release 11 -cp postgresql-42.7.5.jar -d probe GssWrap.java cp run.sh jaas.conf postgresql-*.jar probe/ docker run --rm -v "$PWD/probe:/probe:ro" --entrypoint bash postgres:17 /probe/run.sh Output with 42.7.5 built from tag REL42.7.5 and a 42.7.14-SNAPSHOT build, PostgreSQL 17.11, OpenJDK 21: === /probe/postgresql-42.7.14-SNAPSHOT.jar driver 42.7.14-SNAPSHOT, server 17.11 (Debian 17.11-1.pgdg13+2) gss_authenticated=true, encrypted=true send stream org.postgresql.gss.GSSOutputStream, buffer 16320 bytes case | result buffer empty before write 2 | stored 32740 bytes; of the 16420 bytes of write 2, 0 are not 'B'; first marker at 0 one byte left in the buffer | stored 32740 bytes; of the 16420 bytes of write 2, 0 are not 'B'; first marker at 0 === /probe/postgresql-42.7.5.jar driver 42.7.5-SNAPSHOT, server 17.11 (Debian 17.11-1.pgdg13+2) gss_authenticated=true, encrypted=true send stream org.postgresql.gss.GSSOutputStream, buffer 16320 bytes case | result buffer empty before write 2 | stored 32740 bytes; of the 16420 bytes of write 2, 16319 are not 'B'; first marker at 16293 one byte left in the buffer | org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.; root cause java.lang.ArrayIndexOutOfBoundsException: arraycopy: last source index 16321 out of bounds for byte[16320] With 42.7.5, the first 16320 bytes of the second write were replaced by the previous buffer contents, which included the marker from the other parameter; with the buffer one byte short of full, the statement failed instead. 42.7.4 has the same GSSOutputStream code as 42.7.5 and was not run separately. GssWrap.java run.sh jaas.conf Impact Applications are affected when they connect with gssEncMode=prefer or require to a server that accepts GSS encryption and write values of at least 16320 bytes. The default, gssEncMode=allow, does not start GSS encryption. Most such writes fail with the exception above; the rest are stored with their first 16320 bytes replaced. The application then stores data it did not supply, and the replacement bytes come from other messages sent just before the value on the same connection: the statement's SQL text, its other parameters, and earlier rows of the same batch. Values stored by 42.7.4 or 42.7.5 over GSS encryption can already contain such data. Upgrade to 42.7.6 or later. On 42.7.4 and 42.7.5, the workaround is to turn GSS encryption off with gssEncMode=disable and use TLS for transport encryption instead. Severity Moderate 4.2/ 10 CVSS v3 base metrics Attack vector Network Attack complexity High Privileges required Low User interaction None Scope Unchanged Confidentiality Low Integrity Low Availability None CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N CVE ID CVE-2026-107313 Weaknesses WeaknessCWE-201 Credits @vlsi vlsi Finder _____________________________________________________________________ Driver stores bytes of earlier statements when it pads a value shorter than its declared length Moderate sehrope published GHSA-f64h-wr5q-3qf3 Package org.postgresql:postgresql (Maven) Affected versions >= 42.7.4, <= 42.7.13 Patched versions 42.7.14 Description Summary When an application sends a value shorter than the length it declared, pgjdbc 42.7.4 through 42.7.13 fills the missing bytes with bytes of it sent earlier on the same connection, instead of zeros, and the server stores them. The stored value can contain SQL text and parameter values of earlier, unrelated statements. 42.7.3 and earlier fill the same bytes with zeros. The declared length reaches the driver through public API: Entry point Declared length PreparedStatement.setObject(int, ByteStreamWriter) ByteStreamWriter.getLength() is larger than what writeTo() writes CopyIn.writeToCopy(ByteStreamWriter) the same CopyIn.writeToCopy(byte[], int, int) the length runs past the end of the array PGCopyOutputStream.write(byte[], int, int) the same, for writes larger than the stream's buffer (64 KiB, 65536 bytes, by default); smaller writes throw ArrayIndexOutOfBoundsException LargeObject.write(byte[], int, int) the same java.sql.Blob.setBytes(long, byte[], int, int) the same; PgBlob.setBytes calls LargeObject.write directly (not run separately) In each case the driver accepts the call without an error. Details The driver pads a short value to keep the protocol message at the length it already announced. PgBufferedOutputStream.writeZeros is documented as "Writes the required number of zero bytes to the output stream", but it zeroes only the part of its buffer it overwrote while the buffer held data. When the buffer is empty on entry (count == 0), startPos is 0, so Arrays.fill(buf, 0, Math.min(startPos, len), (byte) 0); zeroes nothing, and the loop that follows flushes the whole buffer as it stands: the bytes of the messages sent before. The buffer is empty on entry in two cases. The last write was long enough for PgBufferedOutputStream.write to send it past the buffer (8192 to 16384 bytes with the default buffer, depending on how much the buffer held before it), and the buffer still holds whatever was sent before, including earlier statements. Or the data ended exactly at a buffer boundary and write flushed the full buffer, which then holds the last bytes sent before the padding: the statement's SQL text, its other parameters, earlier rows of the same batch, and part of the value itself. The send buffer is min(maxSendBufferSize, max(8192, socket send buffer size)) bytes, which is 8192 with the default maxSendBufferSize, so each padded value can carry up to maxSendBufferSize bytes of earlier traffic, repeated to fill the padding. Connections with GSS encryption (gssEncMode) are affected through the second case: GSSOutputStream inherits writeZeros, and its buffer is sized to the GSS wrap limit for a 16380-byte token, 16320 bytes with MIT Kerberos. Measured over hostgssenc against PostgreSQL 17.11 with MIT Kerberos from Debian 13: a ByteStreamWriter whose data ended at the buffer boundary stored 16359 non-zero bytes in a 16409-byte padding, and in a batch the padding of the second row contained a parameter of the first row. Data that ended one byte before the boundary stored zeros. The code came with 6f0d54a ("perf: remove PGStream.streamBuffer and reuse PgBufferedOutputStream's buffer when sending data from InputStream"), first released in 42.7.4. Fix: - // The buffer is empty at this point, and startPos..buf.length is filled with zeros - // So fill the beginning with zeros as well. - Arrays.fill(buf, 0, Math.min(startPos, len), (byte) 0); + // count is 0 here, but buf still holds the bytes of earlier writes + Arrays.fill(buf, 0, Math.min(buf.length, len), (byte) 0); startPos is then unused and can go. The same change fixes GSS-encrypted connections, because GSSOutputStream inherits writeZeros; with it, the three GSS cases above stored zeros. Range checks do not replace this fix. The open pull requests #4384 (COPY), #4377 (LargeObject.write), and #4362 (BlobOutputStream.write) reject an out-of-range (off, len), and their descriptions treat the padding as zeros. No range check covers a ByteStreamWriter that writes less than getLength(): the driver has already sent the message length by then, so it can only finish the message, and the padding has to be zeros. Measured with EntryPoints.java below, each entry point on its own connection after a SELECT that bound the marker: Entry point 42.7.13 #4384 (cb5ce17) writeZeros fix on master bind parameter, ByteStreamWriter marker stored marker stored zeros CopyIn.writeToCopy(byte[], int, int) marker stored IndexOutOfBoundsException zeros CopyIn.writeToCopy(ByteStreamWriter) marker stored marker stored zeros LargeObject.write(byte[], int, int) marker stored marker stored zeros QueryExecutorImpl.sendBind also pads, through PGStream.sendZeros, when a parameter's InputStream fails or ends early. It then skips the Execute message, so the value is not stored. This path was not tested. PoC PaddingRepro.java binds a string with a marker in SELECT length(?), then writes a 300000-byte bytea of which the application supplies 200000 bytes, once as a bind parameter and once through COPY. Run it with JDK 11 or later against any database where the user can create a table: java -cp postgresql-42.7.13.jar PaddingRepro.java 'jdbc:postgresql://127.0.0.1:5432/test?user=test&password=test' Expected, as with 42.7.3: 0 non-zero bytes in the padding and 0 for the marker position in both rows. Actual, PostgreSQL 18.6, OpenJDK 21.0.9, macOS: driver 42.7.13, server 18.6 (Debian 18.6-1.pgdg13+2) via | length | non-zero bytes in the padding | first marker at bind | 300000 | 86232 | 200096 copy | 300000 | 86193 | 200072 The same program on other versions: Version bind: non-zero bytes / marker at copy: non-zero bytes / marker at 42.6.0 0 / 0 0 / 0 42.7.3 0 / 0 0 / 0 42.7.4 86232 / 200096 86193 / 200072 42.7.13 86232 / 200096 86193 / 200072 master 265de13 86232 / 200096 86193 / 200072 master with the fix 0 / 0 0 / 0 PaddingRepro.java EntryPoints.java (the entry point table) Impact Applications are affected when they pass a declared length larger than the data through one of the entry points above. The padded value then contains up to maxSendBufferSize bytes (8192 by default; 16320 with GSS encryption) of what the driver sent earlier on that connection: SQL text and parameter values of recent statements, which the application never passed for this value. On a pooled connection those statements can come from other requests. The value does not have to be large: a value whose data ends exactly at a send buffer boundary is padded with the bytes sent just before it, such as other parameters of the same statement and earlier rows of the same batch. An attacker who can make the application store such a value and read it back can repeat this to collect earlier traffic. Values stored by an affected version through such a call can already contain this data. A correct application, where the declared length always matches the data, is not affected. No connection property turns the behavior off; the workaround is to make the declared length match the data. Severity Moderate 5.3/ 10 CVSS v3 base metrics Attack vector Network Attack complexity High Privileges required Low User interaction None Scope Unchanged Confidentiality High Integrity None Availability None CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N CVE ID CVE-2026-107315 Weaknesses WeaknessCWE-201 WeaknessCWE-226 Credits @vlsi vlsi Finder ========================================================= + CERT-RENATER | tel : 01-53-94-20-44 + + 23/25 Rue Daviel | fax : 01-53-94-20-41 + + 75013 Paris | email:cert@support.renater.fr + =========================================================