[MDEV-19650] Privilege bug on MariaDB 10.4 Created: 2019-05-30  Updated: 2023-11-27  Resolved: 2020-05-08

Status: Closed
Project: MariaDB Server
Component/s: Authentication and Privilege System
Affects Version/s: 10.4.5
Fix Version/s: 10.4.13

Type: Bug Priority: Blocker
Reporter: Mathieu REHO Assignee: Oleksandr Byelkin
Resolution: Fixed Votes: 2
Labels: definer, permissions, privileges, root
Environment:

Ubuntu 18.04.2 Server (amd64)


Attachments: PNG File Screenshot_28.png    
Issue Links:
Blocks
Duplicate
is duplicated by MDEV-21486 Implement option for mysql_install_db... Closed
is duplicated by MDEV-21487 Implement option for mysql_upgrade th... Closed
Relates
relates to MDEV-21486 Implement option for mysql_install_db... Closed
relates to MDEV-22478 Bad error ER_VIEW_INVALID returned up... Open
relates to MDEV-22486 mysql_secure_installation cannot work... Open
relates to MDEV-23373 Document mariadb.sys user Closed
relates to MDEV-21487 Implement option for mysql_upgrade th... Closed
relates to MDEV-22477 mysql_upgrade fails with sql_notes=OFF Open
relates to MDEV-24568 MariaDB Documentation need to be upda... Closed

 Description   

When changing the "root" username to another value for more security, I'm loosing ability to see any users on my phpMyAdmin.

When trying to access to the "mysql.user" table, I get the error "#1449 - The user specified as a definer ('root'@'localhost') does not exist" that was NOT appearing on MariaDB 10.3.

This bug is appearing when changing the "root" username after a fresh install, or after an upgrade from a previous version.



 Comments   
Comment by Elena Stepanova [ 2019-05-30 ]

That's right. In 10.4 mysql.user has been converted into a view, which has root@localhost for a definer. So, if you renamed root@localhost, the definer no longer exists.
I'll assign it to serg to provide thoughts on this.
Meanwhile, I suppose you can fix the view by re-creating it with your new account as a definer. Do SHOW CREATE VIEW mysql.user, copy the definition and run is as CREATE OR REPLACE ... DEFINER=... VIEW ....

Comment by Pramod Mahto [ 2019-07-18 ]

mysql  Ver 15.1 Distrib 10.4.6-MariaDB, for Linux (x86_64) using readline 5.1
 
Connection id:          8
Current database:
Current user:           root@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server:                 MariaDB
Server version:         10.4.6-MariaDB MariaDB Server
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    latin1
Db     characterset:    latin1
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:            /var/lib/mysql/mysql.sock
Uptime:                 28 min 34 sec
 
Threads: 7  Questions: 12  Slow queries: 0  Opens: 19  Flush tables: 1  Open tables: 13  Queries per second avg: 0.007
--------------
 
MariaDB [(none)]>  rename user 'root'@'localhost' to 'dbaadmin'@'localhost';
Query OK, 0 rows affected (0.098 sec)
 
MariaDB [(none)]> select user,host from mysql.user;
ERROR 1449 (HY000): The user specified as a definer ('root'@'localhost') does not exist

Comment by Manjot Singh (Inactive) [ 2019-07-18 ]

IMO, this view should be moved to sys schema in future versions. (if and when we get sys schema)

Comment by Sergei Golubchik [ 2019-08-05 ]

Since 10.4, a root@localhost user must exist for mysql.user to be readable.

If you've renamed root@localhost for more security, you can create a new root@localhost user, for example, like this:

CREATE USER root@localhost ACCOUNT LOCK;
GRANT SELECT ON mysql.global_priv TO root@localhost;

That is you'll have an account that can only select from mysql.global_priv and that nobody can login into.

Comment by Alexander Keremidarski [ 2019-12-20 ]

That root@localhust must exist is incompatible change in 10.4, but is not documented as such. In fact it does not seem to be documented anywhere at all.
https://mariadb.com/kb/en/library/mysqluser-table/ does not mention it.
https://mariadb.com/kb/en/library/authentication-from-mariadb-104/ does not mention it either.
https://mariadb.com/kb/en/library/changes-improvements-in-mariadb-104/ - no single word about that.

Comment by Elena Stepanova [ 2019-12-20 ]

Re-opened for documenting

Comment by Alexander Keremidarski [ 2019-12-21 ]

Serg's explanation is wrong. With such minimal privileges for root@localhost mysql_upgrade fails with errors when running mysql_fix_privilege_tables like:

...

Phase 4/7: Running 'mysql_fix_privilege_tables'
ERROR 1356 (HY000) at line 16: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 68: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 177: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 190: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 325: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 398: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 403: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 412: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ERROR 1356 (HY000) at line 435: View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
FATAL ERROR: Upgrade failed

So root@localhost also needs UPDATE_priv on mysql.global_priv table because there are several

UPDATE user ...

statements in mysql_fix_privilege_tables.

Comment by Mathieu REHO [ 2019-12-22 ]

@Alexander Keremidarski The fact that we dont't use the "root" username anymore in his original functions, an other user who have every privilege would be used to make the upgrade, like this :

$> mysql_upgrade -u myAdminUser -p

So I think that "root" doesn't need more privileges, since we can't login with it using @Sergei Golubchik's solution : `ACCOUNT LOCK`.

Comment by Sergei Golubchik [ 2019-12-27 ]

If it's a question of upgrades, perhaps mysql_upgrade can automatically create a minimal root@localhost if there isn't one?

salle, will that work for you?

Comment by Manjot Singh (Inactive) [ 2019-12-27 ]

Could a system user that can never be logged in (account lock) or have its grants changed fixed this? perhaps something like "dbo@localhost".

This would solve this problem going forward and allow flexibility for system defined views, triggers, routines etc for future features, such as sys_schema etc.

Comment by Oleksandr Byelkin [ 2020-01-15 ]

yes, it can be a solution (scripts should correctly remove root user)

Comment by Sergei Golubchik [ 2020-01-23 ]

May be it could be easier to create a dummy root@localhost user as I described above

Comment by Oleksandr Byelkin [ 2020-02-17 ]

salle If one remove root, it is natural, that scripts where root is hardcoded, fails. IMHO if one remove something important one should imagine what he is doing.

IMHO serg way is the best, we can detect absence right of root for some views/tables, but can not (or it is very difficult and I have not found universal way) to detect that single user (could be many) which user replaced root with, to repair the view and 2 geo-data related procedures.

Comment by Oleksandr Byelkin [ 2020-02-18 ]

I am trying to implement solution very similar to mysql one (with special user), so one will need to just run upgrade script to fix problem of absent root.

Comment by Oleksandr Byelkin [ 2020-05-04 ]

commit 15a750f2501b5ea8a5bc09c7047b8cef7e92d6ab (HEAD > bb-10.4MDEV-19650, origin/bb-10.4-MDEV-19650)
Author: Oleksandr Byelkin <sanja@mariadb.com>
Date: Wed Feb 19 17:50:30 2020 +0100

MDEV-19650: Privilege bug on MariaDB 10.4

Also fixes:
MDEV-21487: Implement option for mysql_upgrade that allows root@localhost to be replaced
MDEV-21486: Implement option for mysql_install_db that allows root@localhost to be replaced

Add user mariadb.sys to be definer of user view
(and has right on underlying table global_priv for
required operation over global_priv
(SELECT,UPDATE,DELETE))

Also changed definer of gis functions in case of creation,
but they work with any definer so upgrade script do not try
to push this change.

Comment by Sergei Golubchik [ 2020-05-05 ]

ok to push

Comment by Oleksandr Byelkin [ 2020-05-05 ]

For documentation sake :

A new user was added : mariadb.sys (script of creation new database or upgrade will create it).
mysql.user view belong now to it and executes with definer priveleges (SELECT,UPDATE,DELETE) which allow to remove root user without consequences.

Comment by Elena Stepanova [ 2020-05-06 ]

main.upgrade_MDEV-19650 doesn't restore PROXY privilege for root, that's what makes perfschema.column_privilege test fail later. Something like this should fix it:

diff -u -r /data/src/bb-10.4-MDEV-19650/mysql-test/main/upgrade_MDEV-19650.result main/upgrade_MDEV-19650.result
--- /data/src/bb-10.4-MDEV-19650/mysql-test/main/upgrade_MDEV-19650.result	2020-05-05 21:28:40.733008297 +0300
+++ main/upgrade_MDEV-19650.result	2020-05-06 15:28:30.482277576 +0300
@@ -3,6 +3,7 @@
 use mysqltest1;
 create table save_global_priv as select * from mysql.global_priv;
 create table save_tables_priv as select * from mysql.tables_priv;
+create table save_proxies_priv as select * from mysql.proxies_priv;
 create table mysql.save_proc like mysql.proc;
 insert into mysql.save_proc select * from mysql.proc;
 set @save_sql_mode= @@sql_mode;
@@ -145,6 +146,7 @@
 mtr.test_suppressions                              OK
 mysqltest1
 mysqltest1.save_global_priv                        OK
+mysqltest1.save_proxies_priv                       OK
 mysqltest1.save_tables_priv                        OK
 performance_schema
 test
@@ -190,9 +192,11 @@
 # restore environment
 delete from global_priv;
 delete from tables_priv;
+delete from proxies_priv;
 delete from proc;
 insert into mysql.global_priv select * from mysqltest1.save_global_priv;
 insert into mysql.tables_priv select * from mysqltest1.save_tables_priv;
+insert into mysql.proxies_priv select * from mysqltest1.save_proxies_priv;
 rename table proc to bad_proc;
 rename table save_proc to proc;
 drop table bad_proc;
diff -u -r /data/src/bb-10.4-MDEV-19650/mysql-test/main/upgrade_MDEV-19650.test main/upgrade_MDEV-19650.test
--- /data/src/bb-10.4-MDEV-19650/mysql-test/main/upgrade_MDEV-19650.test	2020-05-05 21:28:40.733008297 +0300
+++ main/upgrade_MDEV-19650.test	2020-05-06 15:27:45.034838619 +0300
@@ -6,6 +6,7 @@
 use mysqltest1;
 create table save_global_priv as select * from mysql.global_priv;
 create table save_tables_priv as select * from mysql.tables_priv;
+create table save_proxies_priv as select * from mysql.proxies_priv;
 create table mysql.save_proc like mysql.proc;
 insert into mysql.save_proc select * from mysql.proc;
 set @save_sql_mode= @@sql_mode;
@@ -138,9 +139,11 @@
 
 delete from global_priv;
 delete from tables_priv;
+delete from proxies_priv;
 delete from proc;
 insert into mysql.global_priv select * from mysqltest1.save_global_priv;
 insert into mysql.tables_priv select * from mysqltest1.save_tables_priv;
+insert into mysql.proxies_priv select * from mysqltest1.save_proxies_priv;
 rename table proc to bad_proc;
 rename table save_proc to proc;
 drop table bad_proc;

Generated at Thu Feb 08 08:53:18 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.