Bug#7391 - Multi-table UPDATE security regression
Add in missing privilege checks. Tests for the privileges. mysql-test/r/grant.result: Bug#7391 - Multi-table UPDATE security regression Tests column, table and db level access mysql-test/t/grant.test: Bug#7391 - Multi-table UPDATE security regression Tests column, table and db level access sql/sql_update.cc: Bug#7391 - Multi-table UPDATE security regression Add in missing privilege checks.
This commit is contained in:
parent
6d7937c078
commit
4f9a0a06a8
@ -156,3 +156,67 @@ select host,db,user,select_priv,insert_priv from mysql.db where db="db6123";
|
||||
host db user select_priv insert_priv
|
||||
delete from mysql.user where user='test6123';
|
||||
drop database db6123;
|
||||
create database mysqltest_1;
|
||||
create database mysqltest_2;
|
||||
create table mysqltest_1.t1 select 1 a, 2 q;
|
||||
create table mysqltest_1.t2 select 1 b, 2 r;
|
||||
create table mysqltest_2.t1 select 1 c, 2 s;
|
||||
create table mysqltest_2.t2 select 1 d, 2 t;
|
||||
grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost;
|
||||
grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost;
|
||||
grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost;
|
||||
grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
|
||||
show grants for mysqltest_3@localhost;
|
||||
Grants for mysqltest_3@localhost
|
||||
GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost'
|
||||
GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost'
|
||||
GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost'
|
||||
GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost'
|
||||
GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost'
|
||||
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
|
||||
UPDATE command denied to user: 'mysqltest_3@localhost' for column 'q' in table 't1'
|
||||
update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1;
|
||||
select command denied to user: 'mysqltest_3@localhost' for table 't1'
|
||||
update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1;
|
||||
UPDATE command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
|
||||
update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2;
|
||||
SELECT command denied to user: 'mysqltest_3@localhost' for column 's' in table 't1'
|
||||
update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10;
|
||||
update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20;
|
||||
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
|
||||
a q b r
|
||||
10 2 1 2
|
||||
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
|
||||
c s d t
|
||||
1 2 10 2
|
||||
revoke all on mysqltest_1.t1 from mysqltest_3@localhost;
|
||||
revoke all on mysqltest_1.t2 from mysqltest_3@localhost;
|
||||
revoke all on mysqltest_2.t1 from mysqltest_3@localhost;
|
||||
revoke all on mysqltest_2.t2 from mysqltest_3@localhost;
|
||||
grant all on mysqltest_2.* to mysqltest_3@localhost;
|
||||
grant select on *.* to mysqltest_3@localhost;
|
||||
flush privileges;
|
||||
use mysqltest_1;
|
||||
update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600;
|
||||
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
|
||||
UPDATE command denied to user: 'mysqltest_3@localhost' for column 'a' in table 't1'
|
||||
use mysqltest_2;
|
||||
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
|
||||
Access denied for user: 'mysqltest_3@localhost' to database 'mysqltest_1'
|
||||
update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200;
|
||||
Access denied for user: 'mysqltest_3@localhost' to database 'mysqltest_1'
|
||||
update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200;
|
||||
Access denied for user: 'mysqltest_3@localhost' to database 'mysqltest_1'
|
||||
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
|
||||
a q b r
|
||||
10 2 1 2
|
||||
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
|
||||
c s d t
|
||||
500 2 600 2
|
||||
delete from mysql.user where user='mysqltest_3';
|
||||
delete from mysql.db where user="mysqltest_3";
|
||||
delete from mysql.tables_priv where user="mysqltest_3";
|
||||
delete from mysql.columns_priv where user="mysqltest_3";
|
||||
flush privileges;
|
||||
drop database mysqltest_1;
|
||||
drop database mysqltest_2;
|
||||
|
@ -2,6 +2,8 @@
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
connect (master,localhost,root,,);
|
||||
connection master;
|
||||
#
|
||||
# Test that SSL options works properly
|
||||
#
|
||||
@ -114,3 +116,73 @@ grant usage on db6123.* to test6123 identified by 'magic123';
|
||||
select host,db,user,select_priv,insert_priv from mysql.db where db="db6123";
|
||||
delete from mysql.user where user='test6123';
|
||||
drop database db6123;
|
||||
|
||||
#
|
||||
# Bug#7391: Cross-database multi-table UPDATE security problem
|
||||
#
|
||||
create database mysqltest_1;
|
||||
create database mysqltest_2;
|
||||
create table mysqltest_1.t1 select 1 a, 2 q;
|
||||
create table mysqltest_1.t2 select 1 b, 2 r;
|
||||
create table mysqltest_2.t1 select 1 c, 2 s;
|
||||
create table mysqltest_2.t2 select 1 d, 2 t;
|
||||
|
||||
#test the column privileges
|
||||
grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost;
|
||||
grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost;
|
||||
grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost;
|
||||
grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost;
|
||||
connect (conn1,localhost,mysqltest_3,,);
|
||||
connection conn1;
|
||||
show grants for mysqltest_3@localhost;
|
||||
--error 1143
|
||||
update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1;
|
||||
--error 1142
|
||||
update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1;
|
||||
--error 1143
|
||||
update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1;
|
||||
--error 1143
|
||||
update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2;
|
||||
#the following two should work
|
||||
update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10;
|
||||
update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20;
|
||||
connection master;
|
||||
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
|
||||
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
|
||||
revoke all on mysqltest_1.t1 from mysqltest_3@localhost;
|
||||
revoke all on mysqltest_1.t2 from mysqltest_3@localhost;
|
||||
revoke all on mysqltest_2.t1 from mysqltest_3@localhost;
|
||||
revoke all on mysqltest_2.t2 from mysqltest_3@localhost;
|
||||
|
||||
#test the db/table level privileges
|
||||
grant all on mysqltest_2.* to mysqltest_3@localhost;
|
||||
grant select on *.* to mysqltest_3@localhost;
|
||||
flush privileges;
|
||||
disconnect conn1;
|
||||
connect (conn2,localhost,mysqltest_3,,);
|
||||
connection conn2;
|
||||
use mysqltest_1;
|
||||
update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600;
|
||||
# the following failed before, should fail now.
|
||||
--error 1143
|
||||
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
|
||||
use mysqltest_2;
|
||||
#the following used to succeed, it must fail now.
|
||||
--error 1044
|
||||
update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200;
|
||||
--error 1044
|
||||
update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200;
|
||||
--error 1044
|
||||
update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200;
|
||||
#lets see the result
|
||||
connection master;
|
||||
select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2;
|
||||
select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2;
|
||||
|
||||
delete from mysql.user where user='mysqltest_3';
|
||||
delete from mysql.db where user="mysqltest_3";
|
||||
delete from mysql.tables_priv where user="mysqltest_3";
|
||||
delete from mysql.columns_priv where user="mysqltest_3";
|
||||
flush privileges;
|
||||
drop database mysqltest_1;
|
||||
drop database mysqltest_2;
|
||||
|
@ -465,21 +465,34 @@ int mysql_multi_update(THD *thd,
|
||||
*/
|
||||
for (tl= table_list ; tl ; tl=tl->next)
|
||||
{
|
||||
TABLE_LIST *save= tl->next;
|
||||
TABLE *table= tl->table;
|
||||
uint wants;
|
||||
tl->next= 0;
|
||||
if (update_map & table->map)
|
||||
{
|
||||
DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
|
||||
tl->lock_type= thd->lex.lock_option;
|
||||
tl->updating= 1;
|
||||
wants= UPDATE_ACL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias));
|
||||
tl->lock_type= TL_READ;
|
||||
tl->updating= 0;
|
||||
wants= SELECT_ACL;
|
||||
}
|
||||
if (!using_lock_tables)
|
||||
tl->table->reginfo.lock_type= tl->lock_type;
|
||||
|
||||
if (check_access(thd, wants, tl->db, &tl->grant.privilege, 0, 0) ||
|
||||
(grant_option && check_grant(thd, wants, tl, 0, 0)))
|
||||
{
|
||||
tl->next= save;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
tl->next= save;
|
||||
}
|
||||
|
||||
/* Relock the tables with the correct modes */
|
||||
@ -541,6 +554,13 @@ int mysql_multi_update(THD *thd,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If we have no WHERE clause, make it true otherwise the Select
|
||||
examines the privileges
|
||||
*/
|
||||
if (!conds)
|
||||
conds= new Item_int("1", 1LL, 1);
|
||||
|
||||
if (!(result=new multi_update(thd, table_list, fields, values,
|
||||
handle_duplicates)))
|
||||
DBUG_RETURN(-1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user