diff options
author | Changqing Li <changqing.li@windriver.com> | 2021-12-23 13:42:23 +0800 |
---|---|---|
committer | Khem Raj <raj.khem@gmail.com> | 2021-12-23 00:21:30 -0800 |
commit | 8e57fb9b1e4da504ceeaadcff2fe38555a47b6b6 (patch) | |
tree | 45e0ccd1aaa4d4382d7fca6afb09c2643ec64da4 /meta-oe | |
parent | 5f17cabf1a577f202dd7edcb8323600fdff178b3 (diff) | |
download | meta-openembedded-8e57fb9b1e4da504ceeaadcff2fe38555a47b6b6.tar.gz |
postgresql: fix CVE-2021-23214,CVE-2021-23222
Signed-off-by: Changqing Li <changqing.li@windriver.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'meta-oe')
3 files changed, 249 insertions, 0 deletions
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2021-23214.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2021-23214.patch new file mode 100644 index 000000000..58bf81062 --- /dev/null +++ b/meta-oe/recipes-dbs/postgresql/files/CVE-2021-23214.patch | |||
@@ -0,0 +1,116 @@ | |||
1 | From 24c2b9e42edb6d2f4ef2cead3b0aa1d6196adfce Mon Sep 17 00:00:00 2001 | ||
2 | From: Tom Lane <tgl@sss.pgh.pa.us> | ||
3 | Date: Mon, 8 Nov 2021 11:01:43 -0500 | ||
4 | Subject: [PATCH 2/2] Reject extraneous data after SSL or GSS encryption | ||
5 | handshake. | ||
6 | |||
7 | The server collects up to a bufferload of data whenever it reads data | ||
8 | from the client socket. When SSL or GSS encryption is requested | ||
9 | during startup, any additional data received with the initial | ||
10 | request message remained in the buffer, and would be treated as | ||
11 | already-decrypted data once the encryption handshake completed. | ||
12 | Thus, a man-in-the-middle with the ability to inject data into the | ||
13 | TCP connection could stuff some cleartext data into the start of | ||
14 | a supposedly encryption-protected database session. | ||
15 | |||
16 | This could be abused to send faked SQL commands to the server, | ||
17 | although that would only work if the server did not demand any | ||
18 | authentication data. (However, a server relying on SSL certificate | ||
19 | authentication might well not do so.) | ||
20 | |||
21 | To fix, throw a protocol-violation error if the internal buffer | ||
22 | is not empty after the encryption handshake. | ||
23 | |||
24 | Our thanks to Jacob Champion for reporting this problem. | ||
25 | |||
26 | Security: CVE-2021-23214 | ||
27 | |||
28 | Upstream-Status: Backport[https://github.com/postgres/postgres/commit/28e24125541545483093819efae9bca603441951] | ||
29 | CVE: CVE-2021-23214 | ||
30 | |||
31 | Signed-off-by: Changqing Li <changqing.li@windriver.com> | ||
32 | |||
33 | --- | ||
34 | src/backend/libpq/pqcomm.c | 11 +++++++++++ | ||
35 | src/backend/postmaster/postmaster.c | 23 ++++++++++++++++++++++- | ||
36 | src/include/libpq/libpq.h | 1 + | ||
37 | 3 files changed, 34 insertions(+), 1 deletion(-) | ||
38 | |||
39 | diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c | ||
40 | index ee2cd86..4dd1c02 100644 | ||
41 | --- a/src/backend/libpq/pqcomm.c | ||
42 | +++ b/src/backend/libpq/pqcomm.c | ||
43 | @@ -1183,6 +1183,17 @@ pq_getstring(StringInfo s) | ||
44 | } | ||
45 | } | ||
46 | |||
47 | +/* ------------------------------- | ||
48 | + * pq_buffer_has_data - is any buffered data available to read? | ||
49 | + * | ||
50 | + * This will *not* attempt to read more data. | ||
51 | + * -------------------------------- | ||
52 | + */ | ||
53 | +bool | ||
54 | +pq_buffer_has_data(void) | ||
55 | +{ | ||
56 | + return (PqRecvPointer < PqRecvLength); | ||
57 | +} | ||
58 | |||
59 | /* -------------------------------- | ||
60 | * pq_startmsgread - begin reading a message from the client. | ||
61 | diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c | ||
62 | index 5775fc0..1fcc3f8 100644 | ||
63 | --- a/src/backend/postmaster/postmaster.c | ||
64 | +++ b/src/backend/postmaster/postmaster.c | ||
65 | @@ -2049,6 +2049,17 @@ retry1: | ||
66 | return STATUS_ERROR; | ||
67 | #endif | ||
68 | |||
69 | + /* | ||
70 | + * At this point we should have no data already buffered. If we do, | ||
71 | + * it was received before we performed the SSL handshake, so it wasn't | ||
72 | + * encrypted and indeed may have been injected by a man-in-the-middle. | ||
73 | + * We report this case to the client. | ||
74 | + */ | ||
75 | + if (pq_buffer_has_data()) | ||
76 | + ereport(FATAL, | ||
77 | + (errcode(ERRCODE_PROTOCOL_VIOLATION), | ||
78 | + errmsg("received unencrypted data after SSL request"), | ||
79 | + errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack."))); | ||
80 | /* | ||
81 | * regular startup packet, cancel, etc packet should follow, but not | ||
82 | * another SSL negotiation request, and a GSS request should only | ||
83 | @@ -2080,7 +2091,17 @@ retry1: | ||
84 | if (GSSok == 'G' && secure_open_gssapi(port) == -1) | ||
85 | return STATUS_ERROR; | ||
86 | #endif | ||
87 | - | ||
88 | + /* | ||
89 | + * At this point we should have no data already buffered. If we do, | ||
90 | + * it was received before we performed the GSS handshake, so it wasn't | ||
91 | + * encrypted and indeed may have been injected by a man-in-the-middle. | ||
92 | + * We report this case to the client. | ||
93 | + */ | ||
94 | + if (pq_buffer_has_data()) | ||
95 | + ereport(FATAL, | ||
96 | + (errcode(ERRCODE_PROTOCOL_VIOLATION), | ||
97 | + errmsg("received unencrypted data after GSSAPI encryption request"), | ||
98 | + errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack."))); | ||
99 | /* | ||
100 | * regular startup packet, cancel, etc packet should follow, but not | ||
101 | * another GSS negotiation request, and an SSL request should only | ||
102 | diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h | ||
103 | index b115247..9969692 100644 | ||
104 | --- a/src/include/libpq/libpq.h | ||
105 | +++ b/src/include/libpq/libpq.h | ||
106 | @@ -73,6 +73,7 @@ extern int pq_getbyte(void); | ||
107 | extern int pq_peekbyte(void); | ||
108 | extern int pq_getbyte_if_available(unsigned char *c); | ||
109 | extern int pq_putbytes(const char *s, size_t len); | ||
110 | +extern bool pq_buffer_has_data(void); | ||
111 | |||
112 | /* | ||
113 | * prototypes for functions in be-secure.c | ||
114 | -- | ||
115 | 2.17.1 | ||
116 | |||
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2021-23222.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2021-23222.patch new file mode 100644 index 000000000..42b78539b --- /dev/null +++ b/meta-oe/recipes-dbs/postgresql/files/CVE-2021-23222.patch | |||
@@ -0,0 +1,131 @@ | |||
1 | From 79125ead2a6a234086844bb42f06d49603fe6ca0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Tom Lane <tgl@sss.pgh.pa.us> | ||
3 | Date: Mon, 8 Nov 2021 11:14:56 -0500 | ||
4 | Subject: [PATCH 1/2] libpq: reject extraneous data after SSL or GSS encryption | ||
5 | handshake. | ||
6 | |||
7 | libpq collects up to a bufferload of data whenever it reads data from | ||
8 | the socket. When SSL or GSS encryption is requested during startup, | ||
9 | any additional data received with the server's yes-or-no reply | ||
10 | remained in the buffer, and would be treated as already-decrypted data | ||
11 | once the encryption handshake completed. Thus, a man-in-the-middle | ||
12 | with the ability to inject data into the TCP connection could stuff | ||
13 | some cleartext data into the start of a supposedly encryption-protected | ||
14 | database session. | ||
15 | |||
16 | This could probably be abused to inject faked responses to the | ||
17 | client's first few queries, although other details of libpq's behavior | ||
18 | make that harder than it sounds. A different line of attack is to | ||
19 | exfiltrate the client's password, or other sensitive data that might | ||
20 | be sent early in the session. That has been shown to be possible with | ||
21 | a server vulnerable to CVE-2021-23214. | ||
22 | |||
23 | To fix, throw a protocol-violation error if the internal buffer | ||
24 | is not empty after the encryption handshake. | ||
25 | |||
26 | Our thanks to Jacob Champion for reporting this problem. | ||
27 | |||
28 | Security: CVE-2021-23222 | ||
29 | |||
30 | Upstream-Status: Backport[https://github.com/postgres/postgres/commit/160c0258802d10b0600d7671b1bbea55d8e17d45] | ||
31 | CVE: CVE-2021-23222 | ||
32 | |||
33 | Signed-off-by: Changqing Li <changqing.li@windriver.com> | ||
34 | --- | ||
35 | doc/src/sgml/protocol.sgml | 28 ++++++++++++++++++++++++++++ | ||
36 | src/interfaces/libpq/fe-connect.c | 26 ++++++++++++++++++++++++++ | ||
37 | 2 files changed, 54 insertions(+) | ||
38 | |||
39 | diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml | ||
40 | index e26619e1b5..b692648fca 100644 | ||
41 | --- a/doc/src/sgml/protocol.sgml | ||
42 | +++ b/doc/src/sgml/protocol.sgml | ||
43 | @@ -1471,6 +1471,20 @@ SELCT 1/0;<!-- this typo is intentional --> | ||
44 | and proceed without requesting <acronym>SSL</acronym>. | ||
45 | </para> | ||
46 | |||
47 | + <para> | ||
48 | + When <acronym>SSL</acronym> encryption can be performed, the server | ||
49 | + is expected to send only the single <literal>S</literal> byte and then | ||
50 | + wait for the frontend to initiate an <acronym>SSL</acronym> handshake. | ||
51 | + If additional bytes are available to read at this point, it likely | ||
52 | + means that a man-in-the-middle is attempting to perform a | ||
53 | + buffer-stuffing attack | ||
54 | + (<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>). | ||
55 | + Frontends should be coded either to read exactly one byte from the | ||
56 | + socket before turning the socket over to their SSL library, or to | ||
57 | + treat it as a protocol violation if they find they have read additional | ||
58 | + bytes. | ||
59 | + </para> | ||
60 | + | ||
61 | <para> | ||
62 | An initial SSLRequest can also be used in a connection that is being | ||
63 | opened to send a CancelRequest message. | ||
64 | @@ -1532,6 +1546,20 @@ SELCT 1/0;<!-- this typo is intentional --> | ||
65 | encryption. | ||
66 | </para> | ||
67 | |||
68 | + <para> | ||
69 | + When <acronym>GSSAPI</acronym> encryption can be performed, the server | ||
70 | + is expected to send only the single <literal>G</literal> byte and then | ||
71 | + wait for the frontend to initiate a <acronym>GSSAPI</acronym> handshake. | ||
72 | + If additional bytes are available to read at this point, it likely | ||
73 | + means that a man-in-the-middle is attempting to perform a | ||
74 | + buffer-stuffing attack | ||
75 | + (<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>). | ||
76 | + Frontends should be coded either to read exactly one byte from the | ||
77 | + socket before turning the socket over to their GSSAPI library, or to | ||
78 | + treat it as a protocol violation if they find they have read additional | ||
79 | + bytes. | ||
80 | + </para> | ||
81 | + | ||
82 | <para> | ||
83 | An initial GSSENCRequest can also be used in a connection that is being | ||
84 | opened to send a CancelRequest message. | ||
85 | diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c | ||
86 | index f80f4e98d8..57aee95183 100644 | ||
87 | --- a/src/interfaces/libpq/fe-connect.c | ||
88 | +++ b/src/interfaces/libpq/fe-connect.c | ||
89 | @@ -3076,6 +3076,19 @@ keep_going: /* We will come back to here until there is | ||
90 | pollres = pqsecure_open_client(conn); | ||
91 | if (pollres == PGRES_POLLING_OK) | ||
92 | { | ||
93 | + /* | ||
94 | + * At this point we should have no data already buffered. | ||
95 | + * If we do, it was received before we performed the SSL | ||
96 | + * handshake, so it wasn't encrypted and indeed may have | ||
97 | + * been injected by a man-in-the-middle. | ||
98 | + */ | ||
99 | + if (conn->inCursor != conn->inEnd) | ||
100 | + { | ||
101 | + appendPQExpBufferStr(&conn->errorMessage, | ||
102 | + libpq_gettext("received unencrypted data after SSL response\n")); | ||
103 | + goto error_return; | ||
104 | + } | ||
105 | + | ||
106 | /* SSL handshake done, ready to send startup packet */ | ||
107 | conn->status = CONNECTION_MADE; | ||
108 | return PGRES_POLLING_WRITING; | ||
109 | @@ -3175,6 +3188,19 @@ keep_going: /* We will come back to here until there is | ||
110 | pollres = pqsecure_open_gss(conn); | ||
111 | if (pollres == PGRES_POLLING_OK) | ||
112 | { | ||
113 | + /* | ||
114 | + * At this point we should have no data already buffered. | ||
115 | + * If we do, it was received before we performed the GSS | ||
116 | + * handshake, so it wasn't encrypted and indeed may have | ||
117 | + * been injected by a man-in-the-middle. | ||
118 | + */ | ||
119 | + if (conn->inCursor != conn->inEnd) | ||
120 | + { | ||
121 | + appendPQExpBufferStr(&conn->errorMessage, | ||
122 | + libpq_gettext("received unencrypted data after GSSAPI encryption response\n")); | ||
123 | + goto error_return; | ||
124 | + } | ||
125 | + | ||
126 | /* All set for startup packet */ | ||
127 | conn->status = CONNECTION_MADE; | ||
128 | return PGRES_POLLING_WRITING; | ||
129 | -- | ||
130 | 2.17.1 | ||
131 | |||
diff --git a/meta-oe/recipes-dbs/postgresql/postgresql_13.4.bb b/meta-oe/recipes-dbs/postgresql/postgresql_13.4.bb index f63d23dbe..2ed0fa49b 100644 --- a/meta-oe/recipes-dbs/postgresql/postgresql_13.4.bb +++ b/meta-oe/recipes-dbs/postgresql/postgresql_13.4.bb | |||
@@ -7,6 +7,8 @@ SRC_URI += "\ | |||
7 | file://0001-Add-support-for-RISC-V.patch \ | 7 | file://0001-Add-support-for-RISC-V.patch \ |
8 | file://0001-Improve-reproducibility.patch \ | 8 | file://0001-Improve-reproducibility.patch \ |
9 | file://0001-configure.in-bypass-autoconf-2.69-version-check.patch \ | 9 | file://0001-configure.in-bypass-autoconf-2.69-version-check.patch \ |
10 | file://CVE-2021-23214.patch \ | ||
11 | file://CVE-2021-23222.patch \ | ||
10 | " | 12 | " |
11 | 13 | ||
12 | SRC_URI[sha256sum] = "ea93e10390245f1ce461a54eb5f99a48d8cabd3a08ce4d652ec2169a357bc0cd" | 14 | SRC_URI[sha256sum] = "ea93e10390245f1ce461a54eb5f99a48d8cabd3a08ce4d652ec2169a357bc0cd" |