MySQL grants to create a stored procedure on performance_schema.*? - mysql

I understand why this is so locked down. If I were MySQL, I wouldn't want folks to (easily) shoot themselves in the foot on business critical/internal-use databases either. Nevertheless, it should support legitimate use cases.
Suppose I had a stored procedure:
delimiter //
CREATE DEFINER=CURRENT_USER() PROCEDURE performance_schema.sp_flush_hosts()
BEGIN
-- requires DROP privileges
TRUNCATE TABLE performance_schema.host_cache;
END
//
delimiter ;
for a user called root with ALL permissions on most databases.
In practice, MySQL seems to explicitly forbid this for performance_schema:
Because only a limited set of privileges apply to Performance Schema tables, attempts to use GRANT ALL as shorthand for granting privileges at the database or table leval fail with an error:
Fine. So let's grant some specific permissions:
mysql> GRANT CREATE ROUTINE on perforamnce_schema.host_cache to 'root'#'%';
ERROR 1144 (42000): Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used
In the same document (above), only: SELECT, UPDATE, DROP are singled out, but it does not say if those are the only available permissions. How would I grant permissions to create this routine? Is that even possible? Thanks.
Inspiration taken from this SO answer: Is there a way to effectively GRANT on either TRUNCATE or DROP TABLE in MySQL?

Perhaps:
Put your SP in your database. Or perhaps a generic database of "utilities".
Be "root" when you CREATE the SP, and declare it with SQL SECURITY DEFINER See https://dev.mysql.com/doc/refman/5.6/en/stored-objects-security.html#stored-objects-security-sql-security This provides a way to elevate the permissions just for the running of the SP. Normally, one would use SQL SECURITY INVOKER -- to use the permissions of the person CALLing the SP.

Related

Is there a way to effectively GRANT on either TRUNCATE or DROP TABLE in MySQL?

I recently tried this in MySQL 5.5.x:
GRANT
SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON crawler.*
TO 'my_user'#'localhost' WITH GRANT OPTION;
This results in an error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRUNCATE ON crawler.*
TO 'my_user'#'localhost' WITH GRANT OPTION' at line 2
This used to work before I added TRUNCATE, so after a bit of research I find that this is not supported in MySQL.
The reason for this is that TRUNCATE is classified as a DDL operation, and so it doesn't use DELETE internally, it uses DROP. Alright, so I'd like to restrict this user to dropping tables (in the event of a security breach, at least a malicious user would have to determine the names of tables and drop them individually).
However, it turns out I would need to grant this user the DROP privilege, which allows the user to drop whole databases too. Given that there is not a grant for individual tables, is there another way to do this? I suppose I could hand this off to another process with a different user, but it feels a bit cumbersome for such a small issue.
For the time being, I'll stick with DELETE, even though it is rather slow! (On my laptop it takes ~55 sec to delete 1.6M small rows, and a fraction of a second to truncate the same). However, I am all ears if there is a faster and secure alternative.
To grant DROP privilege on a specific table in a specific database to a specific user in MySQL, you can use a GRANT statement like this. (This assumes that table fi exists in database fee, and this is the table you want to allow the user 'fo'#'%' to be able to TRUNCATE):
GRANT DROP ON TABLE fee.fi TO 'fo'#'%'
To see that the user has privilege to truncate that specific table:
SHOW GRANTS FOR 'fo'#'%' ;
And connect as user 'fo'#'%' to test:
TRUNCATE TABLE fee.fi ;
(Obviously, the user also has the privilege to DROP that same table. But that's just the way it is in MySQL.)
As an alternative, to allow the user to perform only the TRUNCATE operation on that specific table, without granting the user DROP privilege on the table...
create a stored procedure that performs a TRUNCATE fee.fi; (That will probably need to be executed dynamically since it's DDL.) The procedure will need to be created with DEFINER privileges, and created by a user that has the required privileges.
Then you can grant execute on the procedure to the user:
GRANT EXECUTE ON fee.truncate_table_fee_fi TO 'fo'#'%';
Then user 'fo'#'%' can
CALL fee.truncate_table_fee_fi

How to grant execute on specific stored procedure to user

I have created some stored procedure on a specific schema.
In this stored procedure, I want to grant execute privilege.
So I wrote that :
GRANT EXECUTE ON PROCEDURE schema_name.proc_name TO 'user_name';
GRANT SELECT ON mysql.proc to 'user_name';
The problem is : My user can see every stored procedure.
I wish he could only see the procedure where he has the EXECUTE privilege.
Is there a way to achieve that ?
Thanks in advance.
Yes... this works as expected if you don't grant the user the SELECT privilege on the mysql.proc table, either directly or indirectly, such as with GRANT SELECT ON *.* TO ...
Without SELECT permission on this table, a user can only see the existence of stored procedures and stored functions where they have other permissions, like EXECUTE.
Under the hood, the lack of SELECT on mysql.proc also prevents the user from seeing the procedures they don't have access to via the information_schema.routines pseudo-table.
You shouldn't need to GRANT SELECT ON mysql.proc to enable the user to execute procedures or functions... and if you do, then that seems like the question.
Problem solved.
In fact, To be able to execute stored procedure within MySQLForExcel, we need to SET the DEFINER of each stored procedure that we want to be called by a MySQLForExcel user.
DELIMITER $$
DROP PROCEDURE IF EXISTS `procedure_name` $$
CREATE DEFINER=`user_mysqlforexcel` PROCEDURE `procedure_name`(param)
BEGIN
Do smth as usual
END $$
I found that here
Thank for the help.

Cursor in Mysql has other rights than user?

i have two databases, db1 and db2.
User man1 had all privileges to db1 but only executing provileges for all functions and procedures in db2.
Calling function db2.getValue from db1 is successful and returns correct values, also if call for db2.getValue is nested in a stored procedure.
Now i create a stored Procedure proc1 and within this procedure i use a cursor to fetch values (_val1, _val2,--) from a table in db1 and call db2.getValue(_val1).
Now somthing really strange happens:
The first loop from the cursor finish, but the value from db2.getValue is empty. At the end of this loop, the loop ends and stops.
Does anyone have a hint where the problem could be here? Calling db1.getValue(_val1) instead of db2.getValue(_val1) works fine.
Therefore my idea was that within the cursor, the privileges for db2 might be not the same?
Kind Regards Solick
Yes, by design, a cursor can behave differently than the same SELECT query might behave if it were executed by the user who called the procedure.
Stored programs and views are defined prior to use and, when referenced, execute within a security context that determines their privileges. These privileges are controlled by their DEFINER attribute, and, if there is one, their SQL SECURITY characteristic.
— http://dev.mysql.com/doc/refman/5.6/en/stored-programs-security.html
If you don't specify a DEFINER when you create a stored program (proc, function, trigger, or event) or a view, then the object, when accessed, runs with the privileges of the user who originally defined it, not the user who invoked it.
You have three options, here:
Verify or possibly modify the permissions of the current DEFINER user if appropriate; or,
Specify a different DEFINER user when defining the stored program or view... you can do this as long as you (the person creating the object) have the SUPER privilege, and users invoking (accessing) the object will temporarily have the rights of that DEFINER user instead; or,
Add SQL SECURITY INVOKER to the definition of procedures, functions, and views (though not triggers or events), causing the object to run with the privileges of the user who invoked it, instead of the definer, which is the default behavior.
To see the permissions the existing definer has, for example if you see DEFINER=`someguy`#`localhost`:
mysql> SHOW GRANTS FOR 'someguy'#'localhost';
You can find the current definer in the definition of the procedure, with SHOW CREATE PROCEDURE procedure_name;.

SUPER privilege(s) for this operation

I create my database and user navid in my shared server with cpanel (databases -> mySQL# Databases -> add new user),and then selected ALL PRIVILEGES for user navid.
I was importing mydatabase.sql when I was confronted with this error.
how do i fix the error? store procedure worked fine in localhost.
what is SUPER privilege?
Error
SQL query:
DELIMITER $$--
-- Procedures
--
CREATE DEFINER = `navid`#`%` PROCEDURE `d_answer` ( OUT `sp_out` INT( 11 ) , IN `sp_id` INT( 11 ) ) NO SQL BEGIN DELETE FROM `tblname` WHERE `a_id` = sp_id;
SET sp_out = ROW_COUNT( ) ;
END$$
MySQL said: Documentation
#1227 - Access denied; you need (at least one of) the SUPER privilege(s) for this operation
From the documentation (my emphasis):
The SUPER privilege enables an account to use CHANGE MASTER TO, KILL
or mysqladmin kill to kill threads belonging to other accounts (you
can always kill your own threads), PURGE BINARY LOGS, configuration
changes using SET GLOBAL to modify global system variables, the
mysqladmin debug command, enabling or disabling logging, performing
updates even if the read_only system variable is enabled, starting and
stopping replication on slave servers, specification of any account
in the DEFINER attribute of stored programs and views, and enables
you to connect (once) even if the connection limit controlled by the
max_connections system variable is reached.
Since you are already navid to the database, you do not need to set the DEFINER attribute in your stored procedure; adding this line is causing the error to show up. If you remove this statement, your procedure will be created and you won't get the permissions error.
You only need to set DEFINER if you are setting up the stored procedure for some other user, by default the stored procedure gets the same security context as the user that is creating it:
All stored programs (procedures, functions, and triggers) and views
can have a DEFINER attribute that names a MySQL account. If the
DEFINER attribute is omitted from a stored program or view definition,
the default account is the user who creates the object.
I got the problem too and fixed it thus in MySQL Workbench.
In my case it is because the "Send to SQL Editor > Create Statement" has extra stuff in there that prevents from being used without modification.
Something like this:
CREATE ALGORITHM=UNDEFINED DEFINER=schemax#localhost SQL
SECURITY DEFINER VIEW viewName AS SELECT ....
Change it to this:
CREATE VIEW viewName AS SELECT ....
Seems to work now, no need to update permissions.
**I am the only user of my database..
I had the same issue - on my local dev server it was fine but on my hosted server (through PHPMyAdmin) it gave me the above error.
Removing the definer attribute seemed to be the easiest way to fix the problem if you're happy with the definer being the current user.
just remove the DEFINER attribute and with it's value, example:
CREATE ALGORITHM=UNDEFINED SQL SECURITY DEFINER VIEW ...
Don't rely on default values, if emptying the definer field in phpMyAdmin or other programs won't solve, check the definer, should not be username#localhost unless explicitly needed, but username#%.

Is there a database tool which shows a list of sql commands I have permission for?

I talked to the developer of HeidiSQL about it and he told me I can query it by "show grants" command of sql, but i don't understand the result set coming from it.
show grants // I execute query here
GRANT USAGE ON . TO 'fsdb1user1'#'%' IDENTIFIED BY PASSWORD
'something'
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP,
REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON
fsdb1.* TO 'fsdb1user1'#'%'
mysql documentation says
SHOW GRANTS displays only the privileges granted explicitly to the
named account. Other privileges might be available to the account, but
they are not displayed. For example, if an anonymous account exists,
the named account might be able to use its privileges, but SHOW GRANTS
will not display them.
I think there might be some software somewhere trying some queries and checks grants that way.
It appears that this user is allowed to do a lot. Here is actually a good reference on all of these http://dev.mysql.com/doc/refman/5.1/en/grant.html#grant-privileges.
The user in question can run SELECT, UPDATE, and DELETE queries. They can CREATE tables and databases. They can DROP tables, databases, and views. They can create and alter INDEXes. They can ALTER table structures. They can use CREATE TEMPORARY TABLE. And finally, they can LOCK TABLES that they have SELECT privileges on. In this case, the user can do this on any table in this database (fsdb1) and from any host.