1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-5849 MySQL bug#12602983 - User without privilege on routine can discover its existence by executing "select non_existing_func();" or by "call non_existing_proc()"

add or move privilege checks before existence checks
This commit is contained in:
Sergei Golubchik
2014-03-20 23:26:41 +01:00
parent 9ff0c9f730
commit 7b1b744f53
5 changed files with 99 additions and 15 deletions

View File

@ -44,7 +44,7 @@ f1(1)
call p1(); call p1();
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1' ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1'
call P1(); call P1();
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1' ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.P1'
select f1(1); select f1(1);
ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1' ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1'
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost;

View File

@ -617,3 +617,33 @@ SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
# Connection default # Connection default
DROP USER user2@localhost; DROP USER user2@localhost;
DROP DATABASE db1; DROP DATABASE db1;
#
# Test for bug#12602983 - User without privilege on routine can discover
# its existence by executing "select non_existing_func();" or by
# "call non_existing_proc()";
#
drop database if exists mysqltest_db;
create database mysqltest_db;
create function mysqltest_db.f1() returns int return 0;
create procedure mysqltest_db.p1() begin end;
# Create user with no privileges on mysqltest_db database.
create user bug12602983_user@localhost;
# Connect as user 'bug12602983_user@localhost'
# Attempt to execute routine on which user doesn't have privileges
# should result in the same 'access denied' error whether
# routine exists or not.
select mysqltest_db.f_does_not_exist();
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f_does_not_exist'
call mysqltest_db.p_does_not_exist();
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.p_does_not_exist'
select mysqltest_db.f1();
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f1'
call mysqltest_db.p1();
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.p1'
create view bug12602983_v1 as select mysqltest_db.f_does_not_exist();
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f_does_not_exist'
create view bug12602983_v1 as select mysqltest_db.f1();
ERROR 42000: execute command denied to user 'bug12602983_user'@'localhost' for routine 'mysqltest_db.f1'
# Connection 'default'.
drop user bug12602983_user@localhost;
drop database mysqltest_db;

View File

@ -995,6 +995,47 @@ disconnect con2;
DROP USER user2@localhost; DROP USER user2@localhost;
DROP DATABASE db1; DROP DATABASE db1;
--echo #
--echo # Test for bug#12602983 - User without privilege on routine can discover
--echo # its existence by executing "select non_existing_func();" or by
--echo # "call non_existing_proc()";
--echo #
--disable_warnings
drop database if exists mysqltest_db;
--enable_warnings
create database mysqltest_db;
create function mysqltest_db.f1() returns int return 0;
create procedure mysqltest_db.p1() begin end;
--echo # Create user with no privileges on mysqltest_db database.
create user bug12602983_user@localhost;
--echo # Connect as user 'bug12602983_user@localhost'
connect (conn1, localhost, bug12602983_user,,);
--echo # Attempt to execute routine on which user doesn't have privileges
--echo # should result in the same 'access denied' error whether
--echo # routine exists or not.
--error ER_PROCACCESS_DENIED_ERROR
select mysqltest_db.f_does_not_exist();
--error ER_PROCACCESS_DENIED_ERROR
call mysqltest_db.p_does_not_exist();
--error ER_PROCACCESS_DENIED_ERROR
select mysqltest_db.f1();
--error ER_PROCACCESS_DENIED_ERROR
call mysqltest_db.p1();
--error ER_PROCACCESS_DENIED_ERROR
create view bug12602983_v1 as select mysqltest_db.f_does_not_exist();
--error ER_PROCACCESS_DENIED_ERROR
create view bug12602983_v1 as select mysqltest_db.f1();
--echo # Connection 'default'.
connection default;
disconnect conn1;
drop user bug12602983_user@localhost;
drop database mysqltest_db;
# Wait till all disconnects are completed # Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc --source include/wait_until_count_sessions.inc

View File

@ -6741,22 +6741,18 @@ Item_func_sp::execute_impl(THD *thd)
{ {
bool err_status= TRUE; bool err_status= TRUE;
Sub_statement_state statement_state; Sub_statement_state statement_state;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Security_context *save_security_ctx= thd->security_ctx; Security_context *save_security_ctx= thd->security_ctx;
#endif
enum enum_sp_data_access access= enum enum_sp_data_access access=
(m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ? (m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess; SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
DBUG_ENTER("Item_func_sp::execute_impl"); DBUG_ENTER("Item_func_sp::execute_impl");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (context->security_ctx) if (context->security_ctx)
{ {
/* Set view definer security context */ /* Set view definer security context */
thd->security_ctx= context->security_ctx; thd->security_ctx= context->security_ctx;
} }
#endif
if (sp_check_access(thd)) if (sp_check_access(thd))
goto error; goto error;
@ -6784,9 +6780,7 @@ Item_func_sp::execute_impl(THD *thd)
thd->restore_sub_statement_state(&statement_state); thd->restore_sub_statement_state(&statement_state);
error: error:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
thd->security_ctx= save_security_ctx; thd->security_ctx= save_security_ctx;
#endif
DBUG_RETURN(err_status); DBUG_RETURN(err_status);
} }
@ -6857,11 +6851,9 @@ Item_func_sp::sp_check_access(THD *thd)
{ {
DBUG_ENTER("Item_func_sp::sp_check_access"); DBUG_ENTER("Item_func_sp::sp_check_access");
DBUG_ASSERT(m_sp); DBUG_ASSERT(m_sp);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_routine_access(thd, EXECUTE_ACL, if (check_routine_access(thd, EXECUTE_ACL,
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE)) m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
#endif
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
@ -6873,7 +6865,29 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
bool res; bool res;
DBUG_ENTER("Item_func_sp::fix_fields"); DBUG_ENTER("Item_func_sp::fix_fields");
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
/*
Checking privileges to execute the function while creating view and
executing the function of select.
*/
if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) ||
(thd->lex->sql_command == SQLCOM_CREATE_VIEW))
{
Security_context *save_security_ctx= thd->security_ctx;
if (context->security_ctx)
thd->security_ctx= context->security_ctx;
res= check_routine_access(thd, EXECUTE_ACL, m_name->m_db.str,
m_name->m_name.str, 0, FALSE);
thd->security_ctx= save_security_ctx;
if (res)
{
context->process_error(thd);
DBUG_RETURN(res);
}
}
/* /*
We must call init_result_field before Item_func::fix_fields() We must call init_result_field before Item_func::fix_fields()
to make m_sp and result_field members available to fix_length_and_dec(), to make m_sp and result_field members available to fix_length_and_dec(),

View File

@ -4642,6 +4642,10 @@ create_sp_error:
open_and_lock_tables(thd, all_tables, TRUE, 0)) open_and_lock_tables(thd, all_tables, TRUE, 0))
goto error; goto error;
if (check_routine_access(thd, EXECUTE_ACL, lex->spname->m_db.str,
lex->spname->m_name.str, TRUE, FALSE))
goto error;
/* /*
By this moment all needed SPs should be in cache so no need to look By this moment all needed SPs should be in cache so no need to look
into DB. into DB.
@ -4691,11 +4695,6 @@ create_sp_error:
thd->server_status|= SERVER_MORE_RESULTS_EXISTS; thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
} }
if (check_routine_access(thd, EXECUTE_ACL,
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
{
goto error;
}
select_limit= thd->variables.select_limit; select_limit= thd->variables.select_limit;
thd->variables.select_limit= HA_POS_ERROR; thd->variables.select_limit= HA_POS_ERROR;