Fix CVE-2021-23214 CVE-2021-23222

(cherry picked from commit d5fdead57cae48009ebe19bd033b3344ef50d182)
This commit is contained in:
wk333 2022-03-11 17:36:45 +08:00 committed by openeuler-sync-bot
parent 78658b2211
commit 8b854d6b61
3 changed files with 178 additions and 1 deletions

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

@ -0,0 +1,90 @@
From 9ae0f1112954989e955b4b29e4580216eccfcee4 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 | 13 +++++++++++++
src/include/libpq/libpq.h | 1 +
3 files changed, 26 insertions(+)
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 4452ea4228cb..31bedac24912 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1199,6 +1199,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 586d6a7d3b96..661b2d037f2a 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -2061,6 +2061,19 @@ ProcessStartupPacket(Port *port, bool SSLdone)
if (SSLok == 'S' && secure_open_server(port) == -1)
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 */
return ProcessStartupPacket(port, true);
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
index fd2dd5853ccf..d3cf746de39f 100644
--- a/src/include/libpq/libpq.h
+++ b/src/include/libpq/libpq.h
@@ -70,6 +70,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);
/*

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

@ -0,0 +1,82 @@
From e65d9c8cd15a86207f1da387a9c917c93c14ea11 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 | 14 ++++++++++++++
src/interfaces/libpq/fe-connect.c | 13 +++++++++++++
2 files changed, 27 insertions(+)
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 3a269640fcd6..6a2d4a14fce5 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1348,6 +1348,20 @@
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.
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 18c09472bed4..03b7cd60d391 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2719,6 +2719,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;

View File

@ -4,7 +4,7 @@
Name: postgresql
Version: 10.5
Release: 22
Release: 23
Summary: PostgreSQL client programs
License: PostgreSQL
URL: http://www.postgresql.org/
@ -45,6 +45,8 @@ Patch6015: CVE-2020-25695.patch
Patch6016: CVE-2020-25696.patch
Patch6017: CVE-2021-20229.patch
Patch6018: CVE-2021-32028.patch
Patch6019: CVE-2021-23214.patch
Patch6020: CVE-2021-23222.patch
BuildRequires: gcc perl(ExtUtils::MakeMaker) glibc-devel bison flex gawk perl(ExtUtils::Embed)
BuildRequires: perl-devel perl-generators readline-devel zlib-devel systemd systemd-devel
@ -435,6 +437,9 @@ find_lang_bins pltcl.lst pltcl
%attr(-,postgres,postgres) %{_libdir}/pgsql/test
%changelog
* Fri Mar 11 2022 wangkai <wangkai385@huawei.com> - 10.5-23
- Fix CVE-2021-23214 CVE-2021-23222
* Wed Oct 20 2021 bzhaoop <bzhaojyathousandy@gmail.com> - 10.5.22
- Fix CVE-2021-32028