From 1bc309bbf635347e558552eaafe39d84dc7b0960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Thu, 22 Feb 2024 11:24:44 +0100 Subject: [PATCH] Fix buffer over-read on concurrent SHA2 auths During an full 'caching_sha2_password' auth, it's possible that the pass has been updated in 'GloMyAuth'. If this possibility is not taking into account buffer over-read could take place and valid auth attempts denied. --- lib/MySQL_Protocol.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/MySQL_Protocol.cpp b/lib/MySQL_Protocol.cpp index 6691f9d3f..aa5d247d2 100644 --- a/lib/MySQL_Protocol.cpp +++ b/lib/MySQL_Protocol.cpp @@ -2483,11 +2483,26 @@ __do_auth: ret = true; } } else if (auth_plugin_id == AUTH_MYSQL_CACHING_SHA2_PASSWORD) { // caching_sha2_password - PPHR_6auth2(ret, vars1); - if (ret == true) { - if ((*myds)->switching_auth_stage == 0) { - const unsigned char fast_auth_success = '\3'; - generate_one_byte_pkt(fast_auth_success); + // Checking 'switching_auth_stage' is required case due to a potential concurrent update + // of pass in 'GloMyAuth'. When the pass found is clear-text it's assumed that full-auth + // is never required and that we are in the first auth stage, because of this, the pass + // received by the client is assumed to be hashed (first auth data received). Yet, during + // during a 'full-auth' the pass stored in 'GloMyAuth' could have been updated either by + // user action or by another concurrent connection that called 'set_clear_text_pass' on + // completion. In this case, we would have received a 'clear-text' pass form 'GloMyAuth' + // but we since we would be in the final auth stage, the pass sent by client should also + // be 'clear-text' (encrypt-pass). + if ((*myds)->switching_auth_stage == 5) { + if (strcmp(vars1.password, reinterpret_cast(vars1.pass)) == 0) { + ret = true; + } + } else { + PPHR_6auth2(ret, vars1); + if (ret == true) { + if ((*myds)->switching_auth_stage == 0) { + const unsigned char fast_auth_success = '\3'; + generate_one_byte_pkt(fast_auth_success); + } } } } else {