mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 18:20:07 +01:00
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.
This commit is contained in:
parent
27ac666fea
commit
edfea7d590
2 changed files with 47 additions and 3 deletions
|
@ -1432,6 +1432,7 @@ void cleanup_items(Item *item)
|
|||
db database name or an empty string. If empty,
|
||||
the current database of the connection is used
|
||||
tbl_name name of the table to dump
|
||||
tbl_len its length
|
||||
|
||||
NOTES
|
||||
This function is written to handle one specific command only.
|
||||
|
@ -1442,7 +1443,7 @@ void cleanup_items(Item *item)
|
|||
*/
|
||||
|
||||
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_LIST* table_list;
|
||||
|
@ -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");
|
||||
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)
|
||||
my_casedn_str(files_charset_info, tbl_name);
|
||||
remove_escape(table_list->table_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))
|
||||
goto err;
|
||||
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)))
|
||||
{
|
||||
my_error(ER_GET_ERRNO, MYF(0), my_errno);
|
||||
|
@ -1838,7 +1844,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
}
|
||||
tbl_name= strmake(db, packet + 1, db_len)+1;
|
||||
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;
|
||||
}
|
||||
case COM_CHANGE_USER:
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -17024,6 +17061,7 @@ static struct my_tests_st my_tests[]= {
|
|||
{ "test_bug20023", test_bug20023 },
|
||||
{ "test_bug45010", test_bug45010 },
|
||||
{ "test_bug53371", test_bug53371 },
|
||||
{ "test_bug53907", test_bug53907 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue