!62 Fix CVE-2021-23214 CVE-2021-23222

From: @wk333 
Reviewed-by: @bzhaoop 
Signed-off-by: @bzhaoop
This commit is contained in:
openeuler-ci-bot 2022-03-14 01:20:35 +00:00 committed by Gitee
commit 423049e686
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
3 changed files with 239 additions and 1 deletions

108
CVE-2021-23214.patch Normal file
View File

@ -0,0 +1,108 @@
From e92ed93e8eb76ee0701b42d4f0ce94e6af3fc741 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 8 Nov 2021 11:01:43 -0500
Subject: [PATCH] Reject extraneous data after SSL or GSS encryption handshake.
The server collects up to a bufferload of data whenever it reads data
from the client socket. When SSL or GSS encryption is requested
during startup, any additional data received with the initial
request message remained in the buffer, and would be treated as
already-decrypted data once the encryption handshake completed.
Thus, a man-in-the-middle with the ability to inject data into the
TCP connection could stuff some cleartext data into the start of
a supposedly encryption-protected database session.
This could be abused to send faked SQL commands to the server,
although that would only work if the server did not demand any
authentication data. (However, a server relying on SSL certificate
authentication might well not do so.)
To fix, throw a protocol-violation error if the internal buffer
is not empty after the encryption handshake.
Our thanks to Jacob Champion for reporting this problem.
Security: CVE-2021-23214
---
src/backend/libpq/pqcomm.c | 12 ++++++++++++
src/backend/postmaster/postmaster.c | 24 ++++++++++++++++++++++++
src/include/libpq/libpq.h | 1 +
3 files changed, 37 insertions(+)
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index ee2cd86866da..93f2e0b81d32 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1183,6 +1183,18 @@ pq_getstring(StringInfo s)
}
}
+/* --------------------------------
+ * pq_buffer_has_data - is any buffered data available to read?
+ *
+ * This will *not* attempt to read more data.
+ * --------------------------------
+ */
+bool
+pq_buffer_has_data(void)
+{
+ return (PqRecvPointer < PqRecvLength);
+}
+
/* --------------------------------
* pq_startmsgread - begin reading a message from the client.
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 5775fc0c0910..1e0936e5b482 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -2049,6 +2049,18 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
return STATUS_ERROR;
#endif
+ /*
+ * At this point we should have no data already buffered. If we do,
+ * it was received before we performed the SSL handshake, so it wasn't
+ * encrypted and indeed may have been injected by a man-in-the-middle.
+ * We report this case to the client.
+ */
+ if (pq_buffer_has_data())
+ ereport(FATAL,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("received unencrypted data after SSL request"),
+ errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
+
/*
* regular startup packet, cancel, etc packet should follow, but not
* another SSL negotiation request, and a GSS request should only
@@ -2081,6 +2093,18 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
return STATUS_ERROR;
#endif
+ /*
+ * At this point we should have no data already buffered. If we do,
+ * it was received before we performed the GSS handshake, so it wasn't
+ * encrypted and indeed may have been injected by a man-in-the-middle.
+ * We report this case to the client.
+ */
+ if (pq_buffer_has_data())
+ ereport(FATAL,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("received unencrypted data after GSSAPI encryption request"),
+ errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
+
/*
* regular startup packet, cancel, etc packet should follow, but not
* another GSS negotiation request, and an SSL request should only
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
index b1152475ace5..54c5fa779773 100644
--- a/src/include/libpq/libpq.h
+++ b/src/include/libpq/libpq.h
@@ -72,6 +72,7 @@ extern int pq_getmessage(StringInfo s, int maxlen);
extern int pq_getbyte(void);
extern int pq_peekbyte(void);
extern int pq_getbyte_if_available(unsigned char *c);
+extern bool pq_buffer_has_data(void);
extern int pq_putbytes(const char *s, size_t len);
/*

123
CVE-2021-23222.patch Normal file
View File

@ -0,0 +1,123 @@
From 844b3169204c28cd086c1b4fae4a2cbdd0540640 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 8 Nov 2021 11:14:56 -0500
Subject: [PATCH] libpq: reject extraneous data after SSL or GSS encryption
handshake.
libpq collects up to a bufferload of data whenever it reads data from
the socket. When SSL or GSS encryption is requested during startup,
any additional data received with the server's yes-or-no reply
remained in the buffer, and would be treated as already-decrypted data
once the encryption handshake completed. Thus, a man-in-the-middle
with the ability to inject data into the TCP connection could stuff
some cleartext data into the start of a supposedly encryption-protected
database session.
This could probably be abused to inject faked responses to the
client's first few queries, although other details of libpq's behavior
make that harder than it sounds. A different line of attack is to
exfiltrate the client's password, or other sensitive data that might
be sent early in the session. That has been shown to be possible with
a server vulnerable to CVE-2021-23214.
To fix, throw a protocol-violation error if the internal buffer
is not empty after the encryption handshake.
Our thanks to Jacob Champion for reporting this problem.
Security: CVE-2021-23222
---
doc/src/sgml/protocol.sgml | 28 ++++++++++++++++++++++++++++
src/interfaces/libpq/fe-connect.c | 26 ++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index e26619e1b53d..b692648fca47 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1471,6 +1471,20 @@ SELCT 1/0;<!-- this typo is intentional -->
and proceed without requesting <acronym>SSL</acronym>.
</para>
+ <para>
+ When <acronym>SSL</acronym> encryption can be performed, the server
+ is expected to send only the single <literal>S</literal> byte and then
+ wait for the frontend to initiate an <acronym>SSL</acronym> handshake.
+ If additional bytes are available to read at this point, it likely
+ means that a man-in-the-middle is attempting to perform a
+ buffer-stuffing attack
+ (<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>).
+ Frontends should be coded either to read exactly one byte from the
+ socket before turning the socket over to their SSL library, or to
+ treat it as a protocol violation if they find they have read additional
+ bytes.
+ </para>
+
<para>
An initial SSLRequest can also be used in a connection that is being
opened to send a CancelRequest message.
@@ -1532,6 +1546,20 @@ SELCT 1/0;<!-- this typo is intentional -->
encryption.
</para>
+ <para>
+ When <acronym>GSSAPI</acronym> encryption can be performed, the server
+ is expected to send only the single <literal>G</literal> byte and then
+ wait for the frontend to initiate a <acronym>GSSAPI</acronym> handshake.
+ If additional bytes are available to read at this point, it likely
+ means that a man-in-the-middle is attempting to perform a
+ buffer-stuffing attack
+ (<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>).
+ Frontends should be coded either to read exactly one byte from the
+ socket before turning the socket over to their GSSAPI library, or to
+ treat it as a protocol violation if they find they have read additional
+ bytes.
+ </para>
+
<para>
An initial GSSENCRequest can also be used in a connection that is being
opened to send a CancelRequest message.
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index f80f4e98d8e0..57aee9518308 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -3076,6 +3076,19 @@ PQconnectPoll(PGconn *conn)
pollres = pqsecure_open_client(conn);
if (pollres == PGRES_POLLING_OK)
{
+ /*
+ * At this point we should have no data already buffered.
+ * If we do, it was received before we performed the SSL
+ * handshake, so it wasn't encrypted and indeed may have
+ * been injected by a man-in-the-middle.
+ */
+ if (conn->inCursor != conn->inEnd)
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("received unencrypted data after SSL response\n"));
+ goto error_return;
+ }
+
/* SSL handshake done, ready to send startup packet */
conn->status = CONNECTION_MADE;
return PGRES_POLLING_WRITING;
@@ -3175,6 +3188,19 @@ PQconnectPoll(PGconn *conn)
pollres = pqsecure_open_gss(conn);
if (pollres == PGRES_POLLING_OK)
{
+ /*
+ * At this point we should have no data already buffered.
+ * If we do, it was received before we performed the GSS
+ * handshake, so it wasn't encrypted and indeed may have
+ * been injected by a man-in-the-middle.
+ */
+ if (conn->inCursor != conn->inEnd)
+ {
+ appendPQExpBufferStr(&conn->errorMessage,
+ libpq_gettext("received unencrypted data after GSSAPI encryption response\n"));
+ goto error_return;
+ }
+
/* All set for startup packet */
conn->status = CONNECTION_MADE;
return PGRES_POLLING_WRITING;

View File

@ -32,7 +32,7 @@ Summary: PostgreSQL client programs
Name: postgresql Name: postgresql
%global majorversion 13 %global majorversion 13
Version: %{majorversion}.3 Version: %{majorversion}.3
Release: 4 Release: 5
# The PostgreSQL license is very similar to other MIT licenses, but the OSI # The PostgreSQL license is very similar to other MIT licenses, but the OSI
# recognizes it as an independent license, so we do as well. # recognizes it as an independent license, so we do as well.
@ -76,6 +76,8 @@ Patch8: postgresql-external-libpq.patch
Patch9: postgresql-server-pg_config.patch Patch9: postgresql-server-pg_config.patch
Patch10: postgresql-no-libecpg.patch Patch10: postgresql-no-libecpg.patch
Patch11: postgresql-datalayout-mismatch-on-s390.patch Patch11: postgresql-datalayout-mismatch-on-s390.patch
Patch12: CVE-2021-23214.patch
Patch13: CVE-2021-23222.patch
BuildRequires: gcc BuildRequires: gcc
BuildRequires: perl(ExtUtils::MakeMaker) glibc-devel bison flex gawk BuildRequires: perl(ExtUtils::MakeMaker) glibc-devel bison flex gawk
@ -348,6 +350,8 @@ goal of accelerating analytics queries.
%endif %endif
%patch9 -p1 %patch9 -p1
%patch11 -p1 %patch11 -p1
%patch12 -p1
%patch13 -p1
# We used to run autoconf here, but there's no longer any real need to, # We used to run autoconf here, but there's no longer any real need to,
# since Postgres ships with a reasonably modern configure script. # since Postgres ships with a reasonably modern configure script.
@ -1234,6 +1238,9 @@ make -C postgresql-setup-%{setup_version} check
%changelog %changelog
* Fri Mar 11 2022 wangkai <wangkai385@huawei.com> - 13.3-5
- Fix CVE-2021-23214 CVE-2021-23222
* Tue Jan 18 2022 lvxiaoqian<xiaoqian@nj.iscas.ac.cn> - 13.3-4 * Tue Jan 18 2022 lvxiaoqian<xiaoqian@nj.iscas.ac.cn> - 13.3-4
- Disable spinlocks on RISC-V 64-bit (riscv64) - Disable spinlocks on RISC-V 64-bit (riscv64)
- Disable LLVM/Clang for riscv64 (fails tests) - Disable LLVM/Clang for riscv64 (fails tests)