Commit bfc71e63 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-3915 COM_CHANGE_USER allows fast password brute-forcing

  
allow only three failed change_user per connection.
successful change_user do NOT reset the counter

tests/mysql_client_test.c:
  make --error to work for --change_user errors
parent 8127e631
......@@ -3908,7 +3908,10 @@ void do_change_user(struct st_command *command)
cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str))
die("change user failed: %s", mysql_error(mysql));
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), &ds_res);
else
handle_no_error(command);
dynstr_free(&ds_user);
dynstr_free(&ds_passwd);
......
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: NO)
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: NO)
ERROR 28000: Access denied for user 'foo'@'localhost' (using password: NO)
ERROR 08S01: Unknown command
ERROR 08S01: Unknown command
......@@ -847,9 +847,9 @@ a int(11) YES NULL
b varchar(255) YES NULL
c datetime YES NULL
drop table t1;
mysqltest: At line 1: change user failed: Unknown database 'inexistent'
mysqltest: At line 1: change user failed: Access denied for user 'inexistent'@'localhost' (using password: NO)
mysqltest: At line 1: change user failed: Access denied for user 'root'@'localhost' (using password: YES)
mysqltest: At line 1: query 'change_user root,,inexistent' failed: 1049: Unknown database 'inexistent'
mysqltest: At line 1: query 'change_user inexistent,,test' failed: 1045: Access denied for user 'inexistent'@'localhost' (using password: NO)
mysqltest: At line 1: query 'change_user root,inexistent,test' failed: 1045: Access denied for user 'root'@'localhost' (using password: YES)
REPLACED_FILE1.txt
file1.txt
file2.txt
......
source include/not_embedded.inc;
#
# MDEV-3915 COM_CHANGE_USER allows fast password brute-forcing
#
# only three failed change_user per connection.
# successful change_user do NOT reset the counter
#
connect (test,localhost,root,,);
connection test;
--error 1045
change_user foo,bar;
--error 1045
change_user foo;
change_user;
--error 1045
change_user foo,bar;
--error 1047
change_user foo,bar;
--error 1047
change_user;
disconnect test;
connection default;
......@@ -675,6 +675,7 @@ THD::THD()
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
examined_row_count(0),
global_read_lock(0),
failed_com_change_user(0),
is_fatal_error(0),
transaction_rollback_request(0),
is_fatal_sub_stmt_error(0),
......
......@@ -1865,6 +1865,7 @@ public:
bool no_errors, password;
bool extra_port; /* If extra connection */
uint8 failed_com_change_user;
/**
Set to TRUE if execution of the current compound statement
can not continue. In particular, disables activation of
......
......@@ -1144,6 +1144,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint save_db_length= thd->db_length;
char *save_db= thd->db;
int rc;
USER_CONN *save_user_connect= thd->user_connect;
Security_context save_security_ctx= *thd->security_ctx;
CHARSET_INFO *save_character_set_client=
......@@ -1157,7 +1158,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->security_ctx->user= 0;
thd->user_connect= 0;
if (acl_authenticate(thd, 0, packet_length))
/*
to limit COM_CHANGE_USER ability to brute-force passwords,
we only allow three unsuccessful COM_CHANGE_USER per connection.
*/
if (thd->failed_com_change_user >= 3)
{
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
rc= 1;
}
else
rc= acl_authenticate(thd, 0, packet_length);
if (rc)
{
/* Free user if allocated by acl_authenticate */
x_free(thd->security_ctx->user);
......@@ -1170,6 +1183,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->variables.collation_connection= save_collation_connection;
thd->variables.character_set_results= save_character_set_results;
thd->update_charset();
thd->failed_com_change_user++;
my_sleep(1000000);
}
else
{
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment