Skip to content

Commit 7550af8

Browse files
committed
[MDEV-31585] Stop trusting or relying on client identifying information sent prior to the TLS handshake
The server has heretofore improperly mishandled—and TRUSTED—information sent in the plaintext login request packet sent prior to the TLS handshake. As a result of this, the client is *forced* to send excessive and exploitable identifying information in the pre-TLS-handshake plaintext login packet. That client-side vulnerability is CONC-654. This modifies the server to stop relying on any of the information in the pre-TLS-handshake plaintext login packet EXCEPT for the single bit that tells it that a TLS handshake will follow. It furthermore adds an "extended capability" bit to the server greeting packet, which informs the client that it is safe to send a bare-bones dummy packet containing ONLY the instruction that a TLS handshake will follow: /* Server does not mishandle information sent in the plaintext * login request packet sent prior to the TLS handshake. As a result, the * client can safely send an empty/dummy packet contianing no * identifying information. Indicates that MDEV-31585 has been fixed. * Since ??.?. */ #define MARIADB_CLIENT_CAN_SEND_DUMMY_HANDSHAKE_PACKET (1ULL << 37) All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.
1 parent e753804 commit 7550af8

File tree

3 files changed

+44
-22
lines changed

3 files changed

+44
-22
lines changed

include/mysql_com.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ enum enum_indicator_type
288288
/* Do not resend metadata for prepared statements, since 10.6*/
289289
#define MARIADB_CLIENT_CACHE_METADATA (1ULL << 36)
290290

291+
/* Server doesn't improperly read the pre-TLS dummy packet beyond the initial 2 bytes */
292+
#define CLIENT_CAN_SEND_DUMMY_HANDSHAKE_PACKET (1ULL << 37)
293+
291294
#ifdef HAVE_COMPRESS
292295
#define CAN_CLIENT_COMPRESS CLIENT_COMPRESS
293296
#else

libmariadb

sql/sql_acl.cc

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13259,6 +13259,7 @@ static bool send_server_handshake_packet(MPVIO_EXT *mpvio,
1325913259
thd->client_capabilities|= CLIENT_TRANSACTIONS;
1326013260

1326113261
thd->client_capabilities|= CAN_CLIENT_COMPRESS;
13262+
thd->client_capabilities|= CLIENT_CAN_SEND_DUMMY_HANDSHAKE_PACKET;
1326213263

1326313264
if (ssl_acceptor_fd)
1326413265
{
@@ -13752,30 +13753,19 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
1375213753
*/
1375313754
DBUG_ASSERT(net->read_pos[pkt_len] == 0);
1375413755

13755-
ulonglong client_capabilities= uint2korr(net->read_pos);
13756-
compile_time_assert(sizeof(client_capabilities) >= 8);
13757-
if (client_capabilities & CLIENT_PROTOCOL_41)
13756+
ushort first_two_bytes_of_client_capabilities= uint2korr(net->read_pos);
13757+
if (first_two_bytes_of_client_capabilities & CLIENT_SSL)
1375813758
{
13759-
if (pkt_len < 32)
13760-
DBUG_RETURN(packet_error);
13761-
client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
13762-
if (!(client_capabilities & CLIENT_MYSQL))
13763-
{
13764-
// it is client with mariadb extensions
13765-
ulonglong ext_client_capabilities=
13766-
(((ulonglong)uint4korr(net->read_pos + 28)) << 32);
13767-
client_capabilities|= ext_client_capabilities;
13768-
}
13769-
}
13770-
13771-
/* Disable those bits which are not supported by the client. */
13772-
compile_time_assert(sizeof(thd->client_capabilities) >= 8);
13773-
thd->client_capabilities&= client_capabilities;
13759+
/* Client wants to use TLS. This packet is really just a
13760+
* dummy which gets sent before the TLS handshake, in order
13761+
* to trigger the server (us) to start the TLS handshake.
13762+
*
13763+
* We should ignore everything else in this packet until
13764+
* after the TLS handshake.
13765+
*/
1377413766

13775-
DBUG_PRINT("info", ("client capabilities: %llu", thd->client_capabilities));
13776-
if (thd->client_capabilities & CLIENT_SSL)
13777-
{
1377813767
unsigned long errptr __attribute__((unused));
13768+
DBUG_PRINT("info", ("client capabilities have TLS/SSL bit set"));
1377913769

1378013770
/* Do the SSL layering. */
1378113771
if (!ssl_acceptor_fd)
@@ -13796,6 +13786,10 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
1379613786
DBUG_PRINT("info", ("Immediately following IO layer change: vio_type=%s",
1379713787
safe_vio_type_name(thd->net.vio)));
1379813788

13789+
/* Now we are using TLS. The client will resend its REAL
13790+
* handshake packet, containing complete credentials and
13791+
* capability information.
13792+
*/
1379913793
DBUG_PRINT("info", ("Reading user information over SSL layer"));
1380013794
pkt_len= my_net_read(net);
1380113795
if (unlikely(pkt_len == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE))
@@ -13804,8 +13798,33 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
1380413798
pkt_len));
1380513799
DBUG_RETURN(packet_error);
1380613800
}
13801+
13802+
/* Re-load the FIRST TWO BYTES of the client handshake packet */
13803+
first_two_bytes_of_client_capabilities = uint2korr(net->read_pos);
1380713804
}
1380813805

13806+
ulonglong client_capabilities= (ulonglong) first_two_bytes_of_client_capabilities;
13807+
compile_time_assert(sizeof(client_capabilities) >= 8);
13808+
13809+
DBUG_PRINT("info", ("client capabilities: %llu", thd->client_capabilities));
13810+
if (client_capabilities & CLIENT_PROTOCOL_41)
13811+
{
13812+
if (pkt_len < 32)
13813+
DBUG_RETURN(packet_error);
13814+
client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
13815+
if (!(client_capabilities & CLIENT_MYSQL))
13816+
{
13817+
// it is client with mariadb extensions
13818+
ulonglong ext_client_capabilities=
13819+
(((ulonglong)uint4korr(net->read_pos + 28)) << 32);
13820+
client_capabilities|= ext_client_capabilities;
13821+
}
13822+
}
13823+
13824+
/* Disable those bits which are not supported by the client. */
13825+
compile_time_assert(sizeof(thd->client_capabilities) >= 8);
13826+
thd->client_capabilities&= client_capabilities;
13827+
1380913828
if (client_capabilities & CLIENT_PROTOCOL_41)
1381013829
{
1381113830
thd->max_client_packet_length= uint4korr(net->read_pos+4);

0 commit comments

Comments
 (0)