Hi. While installing MySQL 3.22.29 and testing it out, I discovered a very serious bug in it's handling of the GRANT statement. I have decided to post this message at this time although a fixed distribution is not yet available at mysql.com. The reason for this is that the subject has been discussed on the MySQL mailing list, and that the cat is therefore already out of the bag. Many crackers out there are already aware of implications and how to exploit this bug. A temporary solution is suggested in this post, and a patch from TCX is attached at the bottom. Affected: Known: MySQL 3.22.27, 3.22.29, 3.23.8 Suspected: All MySQL versions since 3.22.11. Impact: Anyone with access to a running MySQL and GRANT privilege for any database or table in it, can change any MySQL-password he wishes, including the MySQL superuser's. Implications: If the malicious user has access to run processes on the machine where MySQL is running, he can hijack the entire database. If he does not have such access, he can DOS the server by setting the MySQL superuser's password to a random string. The 'test'-users installed by MySQL's install scripts have GRANT privileges for any database whose name begins with 'test', and can therefore be used to exploit this bug. The 'test' accounts by default have no passwords set, and no restrictions on where connects can come from. This makes all default-configured MySQL very vulnerable (anyone on the net can change your MySQL superuser password). Be aware, however, that _any_ user with a GRANT privilege (no matter on which database) in your MySQL installation can exploit this bug. You may be vulnerable even if you've removed the 'test' users. Story: I contacted the MySQL mailing list and reported this bug (the MySQL mailing list is the official place to report bugs). The first person from mysql.com I had a discussion with, said that this was the way it was supposed to work. GRANT privileges were, according to him, by definition global (even GRANTs for a single database were apparently global) and implied the possibility to change anyone's password. I almost bought his story and started thinking about changing to another RDBMS. Fortunately, Monty at TCX Datakonsult AB (the company that originally wrote MySQL) acknowledged that it was a real and serious bug. No one without UPDATE privilige on the mysql.user table should be able to set anyone's password. A fix has been made, and new releases will be available for download very soon. Recommendation: It is STRONGLY RECOMMENDED that anyone running MySQL 3.22.11 or later UPGRADE to the new versions as soon as they are available at www.mysql.com and it's mirrors. While waiting for the new versions to arrive, or for opportunity to install them 1) Revoke _all_ GRANT privileges from _all_ users in your MySQL system except root@localhost. This includes GRANTs in the mysql.db table. 2) Confirm that your root@localhost password has not been altered. For those of you using source distributions, I have received a patch for the problem from TCX. It is attached at the bottom of this message. Details: The bug is that the GRANT statement does not properly check privileges when you give it an IDENTIFIED BY-clause. You can therefore GRANT someone (including the MySQL superuser) a privilege you yourself possess, and set her/his password at the same time using IDENTIFIED BY. Which privilege you pass on does not matter. It is the side-effect of the IDENTIFIED BY that does the magic. This can be exploited regardless of your other permissions. You only need the GRANT privilege for _any_ table or database to exploit this bug. For someone having login access to the machine running MySQL, hijacking the database is trivial once the MySQL superuser password has been changed using the above method. For someone without login access, changing the superuser password can be a simple way of DOS:ing, or of extortion. In the default setup, MySQL prohibits access to the superuser account from any other hosts than localhost. Sites that allow superusers to connect from the net may be vulnerable to hijacking from malicious users without local access. Since the password-less 'test'-accounts created by MySQL installation scripts have GRANT privileges for any database whose name begins with 'test', they can be used to exploit this bug. Very nasty. Exploit: I will post an exploit as soon as the patched versions are available (which should be tomorrow). The Kiddiez should be forced to do at least _some_ work themselves. :-) /Viktor... ---------------------------------------------------------------------- *** /my/monty/master/mysql-3.23.8-alpha/sql/sql_parse.cc Fri Dec 31 13:53:03 1999 --- ./sql_parse.cc Mon Jan 10 21:53:59 2000 *************** *** 1222,1227 **** --- 1222,1246 ---- tables ? &tables->grant.privilege : 0, tables ? 0 : 1)) goto error; + + /* Check that the user isn't trying to change a password for another + user if he doesn't have UPDATE privilege to the MySQL database */ + + List_iterator user_list(lex->users_list); + LEX_USER *user; + while ((user=user_list++)) + { + if (user->password.str && + (strcmp(thd->user,user->user.str) || + user->host.str && my_strcasecmp(user->host.str, + thd->host ? thd->host : thd->ip))) + { + if (check_access(thd, UPDATE_ACL, "mysql",0,1)) + goto error; + break; // We are allowed to do changes + } + } + if (tables) { if (grant_option && check_grant(thd, ---------------------------------------------------------------------- --| Viktor Fougstedt, system administrator at dtek.chalmers.se |-- --| http://www.dtek.chalmers.se/~viktor/ |-- --| ...soon we'll be sliding down the razor blade of life. /Tom Lehrer |--