Commit b2d40809 authored by Ramil Kalimullin's avatar Ramil Kalimullin

Fix for bug #53907: Table dump command can be abused to dump arbitrary tables.

Problem: one with SELECT privilege on some table may dump other table
performing COM_TABLE_DUMP command due to missed check of the table name.

Fix: check the table name.


sql/sql_parse.cc:
  Fix for bug #53907: Table dump command can be abused to dump arbitrary tables.
    - check given table name performing COM_TABLE_DUMP command.
tests/mysql_client_test.c:
  Fix for bug #53907: Table dump command can be abused to dump arbitrary tables.
    - test case.
parent ba4710d0
...@@ -1432,6 +1432,7 @@ void cleanup_items(Item *item) ...@@ -1432,6 +1432,7 @@ void cleanup_items(Item *item)
db database name or an empty string. If empty, db database name or an empty string. If empty,
the current database of the connection is used the current database of the connection is used
tbl_name name of the table to dump tbl_name name of the table to dump
tbl_len its length
NOTES NOTES
This function is written to handle one specific command only. This function is written to handle one specific command only.
...@@ -1442,7 +1443,7 @@ void cleanup_items(Item *item) ...@@ -1442,7 +1443,7 @@ void cleanup_items(Item *item)
*/ */
static static
int mysql_table_dump(THD* thd, char* db, char* tbl_name) int mysql_table_dump(THD* thd, char* db, char* tbl_name, uint tbl_len)
{ {
TABLE* table; TABLE* table;
TABLE_LIST* table_list; TABLE_LIST* table_list;
...@@ -1461,6 +1462,11 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name) ...@@ -1461,6 +1462,11 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name)
my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL"); my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL");
goto err; goto err;
} }
if (!tbl_name || check_table_name(tbl_name, tbl_len))
{
my_error(ER_WRONG_TABLE_NAME , MYF(0), tbl_name ? tbl_name : "NULL");
goto err;
}
if (lower_case_table_names) if (lower_case_table_names)
my_casedn_str(files_charset_info, tbl_name); my_casedn_str(files_charset_info, tbl_name);
remove_escape(table_list->table_name); remove_escape(table_list->table_name);
...@@ -1471,7 +1477,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name) ...@@ -1471,7 +1477,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name)
if (check_one_table_access(thd, SELECT_ACL, table_list)) if (check_one_table_access(thd, SELECT_ACL, table_list))
goto err; goto err;
thd->free_list = 0; thd->free_list = 0;
thd->set_query(tbl_name, (uint) strlen(tbl_name)); thd->set_query(tbl_name, tbl_len);
if ((error = mysqld_dump_create_info(thd, table_list, -1))) if ((error = mysqld_dump_create_info(thd, table_list, -1)))
{ {
my_error(ER_GET_ERRNO, MYF(0), my_errno); my_error(ER_GET_ERRNO, MYF(0), my_errno);
...@@ -1838,7 +1844,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1838,7 +1844,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
} }
tbl_name= strmake(db, packet + 1, db_len)+1; tbl_name= strmake(db, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len); strmake(tbl_name, packet + db_len + 2, tbl_len);
mysql_table_dump(thd, db, tbl_name); mysql_table_dump(thd, db, tbl_name, tbl_len);
break; break;
} }
case COM_CHANGE_USER: case COM_CHANGE_USER:
......
...@@ -16720,6 +16720,43 @@ static void test_bug53371() ...@@ -16720,6 +16720,43 @@ static void test_bug53371()
} }
static void test_bug53907()
{
int rc;
char buf[] = "\x4test\x14../client_test_db/t1";
myheader("test_bug53907");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
rc= mysql_query(mysql, "DROP DATABASE IF EXISTS bug53907");
myquery(rc);
rc= mysql_query(mysql, "DROP USER 'testbug'@localhost");
rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
myquery(rc);
rc= mysql_query(mysql, "CREATE DATABASE bug53907");
myquery(rc);
rc= mysql_query(mysql, "GRANT SELECT ON bug53907.* to 'testbug'@localhost");
myquery(rc);
rc= mysql_change_user(mysql, "testbug", NULL, "bug53907");
myquery(rc);
rc= simple_command(mysql, COM_TABLE_DUMP, buf, sizeof(buf), 0);
DIE_UNLESS(mysql_errno(mysql) == 1103); /* ER_WRONG_TABLE_NAME */
rc= mysql_change_user(mysql, opt_user, opt_password, current_db);
myquery(rc);
rc= mysql_query(mysql, "DROP TABLE t1");
myquery(rc);
rc= mysql_query(mysql, "DROP DATABASE bug53907");
myquery(rc);
rc= mysql_query(mysql, "DROP USER 'testbug'@localhost");
myquery(rc);
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -17024,6 +17061,7 @@ static struct my_tests_st my_tests[]= { ...@@ -17024,6 +17061,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug20023", test_bug20023 }, { "test_bug20023", test_bug20023 },
{ "test_bug45010", test_bug45010 }, { "test_bug45010", test_bug45010 },
{ "test_bug53371", test_bug53371 }, { "test_bug53371", test_bug53371 },
{ "test_bug53907", test_bug53907 },
{ 0, 0 } { 0, 0 }
}; };
......
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