From f644f6ecd53a62fbd6880cd1fc1049177089b1ff Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Wed, 17 Nov 2021 19:26:11 +0900 Subject: [PATCH] Reject extraneous data after SSL encryption handshake. In the server side implementation of SSL negotiation (pool_ssl_negotiate_serverclient()), it was possible for a man-in-the-middle attacker to inject arbitrary SQL commands. This is possible if Pgpool-II is configured to use cert authentication or hostssl + trust. This resembles PostgreSQL's CVE-2021-23214. Similarly, in the client side implementation of SSL negotiation (pool_ssl_negotiate_clientserver()), it was possible for a man-in-the-middle attacker to inject arbitrary responses. This is possible if PostgreSQL is using trust authentication with a clientcert requirement. It is not possible with cert authentication because Pgpool-II does not implement the cert authentication between Pgpool-II To fix these reject extraneous data in the read buffer after SSL encryption handshake. and PostgreSQL. This resembles PostgreSQL's CVE-2021-23222. --- src/utils/pool_ssl.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/utils/pool_ssl.c b/src/utils/pool_ssl.c index 85c86e012..86bb99fb8 100644 --- a/src/utils/pool_ssl.c +++ b/src/utils/pool_ssl.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2020 PgPool Global Development Group + * Copyright (c) 2003-2021 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -123,6 +123,20 @@ pool_ssl_negotiate_clientserver(POOL_CONNECTION * cp) switch (server_response) { case 'S': + + /* + * At this point the server read buffer must be empty. Otherwise it + * is possible that a man-in-the-middle attack is ongoing. + * So we immediately close the communication channel. + */ + if (!pool_read_buffer_is_empty(cp)) + { + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("received unencrypted data after SSL request"), + errdetail("This could be an evidence of an attempted man-in-the-middle attacck."))); + } + SSL_set_fd(cp->ssl, cp->fd); SSL_RETURN_VOID_IF((SSL_connect(cp->ssl) < 0), "SSL_connect"); @@ -165,6 +179,19 @@ pool_ssl_negotiate_serverclient(POOL_CONNECTION * cp) /* write back an "SSL accept" response */ pool_write_and_flush(cp, "S", 1); + /* + * At this point the frontend read buffer must be empty. Otherwise it + * is possible that a man-in-the-middle attack is ongoing. + * So we immediately close the communication channel. + */ + if (!pool_read_buffer_is_empty(cp)) + { + 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 attacck."))); + } + SSL_set_fd(cp->ssl, cp->fd); SSL_RETURN_VOID_IF((SSL_accept(cp->ssl) < 0), "SSL_accept"); cp->ssl_active = 1; -- 2.39.5