Authentication bypass if auth_socket installed

Bug #1289599 reported by Vincent Kéravec on 2014-03-07
260
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Percona Server
Status tracked in 5.6
5.5
Critical
Sergei Glushchenko
5.6
Critical
Sergei Glushchenko

Bug Description

After installing the auth_socket plugin all local users might get root access to the mysql server.

How to replicate the bug:
install mysql with a clean database
Run the following query in the database
install plugin auth_socket soname "auth_socket.so";
update user set plugin='auth_socket' where user='root';
drop user 'root'@'::1';
drop user ''@'::localhost';
drop user ''@'localhost';
drop user ''@'localhost.localdomain';
drop user 'root'@'localhost.localdomain';
flush privileges;

You should now be able to login as root only when your unix username match root.
The problem is that with this setup a normal user without a mysql user can login to the database as root.

When running mysql from a user that should not have access to the database I get the following:
mysql> select user(),current_user();
+----------------+----------------+
| user() | current_user() |
+----------------+----------------+
| vike@localhost | root@127.0.0.1 |
+----------------+----------------+
1 row in set (0.00 sec)

There seems to be a bug with some variable not being initialised properly.
Here is what I got while trying to understand what is happening:

The system first try to login with the correct user and an empty password.
This fail so the system pick a random user (which is the root user in this case) and set the flag make_it_fail.
The system then check the next authentication plugin.
The test for auth plugin succeed since the username sent to MySQL is the same as the user logged on the server.
MySQL then go to give access to the server to this user with the authenticated_as still set by the previous failed login.

Here is a dump of mpvio in this case:
$55 = {<st_plugin_vio> = {
    read_packet = 0x6832f0 <server_mpvio_read_packet(MYSQL_PLUGIN_VIO*, uchar**)>,
    write_packet = 0x6797d0 <server_mpvio_write_packet(MYSQL_PLUGIN_VIO*, uchar const*, int)>,
    info = 0x678250 <server_mpvio_info(MYSQL_PLUGIN_VIO*, MYSQL_PLUGIN_VIO_INFO*)>},
auth_info = {user_name = 0x7f27a4004c40 "vike", user_name_length = 4,
    auth_string = 0x7f27a4004d90 "", auth_string_length = 0,
    authenticated_as = "root", '\000' <repeats 44 times>,
    external_user = '\000' <repeats 511 times>, password_used = 2,
    host_or_ip = 0xb73ab8 "localhost", host_or_ip_length = 9},
  acl_user = 0x7f27a4004c70, plugin = 0x21fdd60, db = {
    str = 0x7f27a4004c30 "", length = 0},
cached_client_reply = {plugin = 0x278f506 "mysql_native_password", pkt = 0x12e9628 "", pkt_len = 0},
cached_server_packet = { pkt = 0x7f27a4004a10 "#(?DyTvvmA<I9~4%[}#4", pkt_len = 21},
packets_read = 1,
packets_written = 1,
make_it_fail = true,
status = MPVIO_EXT::FAILURE,
client_capabilities = 8365701,
scramble = 0x2677184 "#(?DyTvvmA<I9~4%[}#4",
mem_root = 0x26786c0,
rand = 0x2675648,
thread_id = 14,
server_status = 0x2677114,
net = 0x2675270,
max_client_packet_length = 16777216,
ip = 0xbf65bf "",
host = 0xb73ab8 "localhost",
charset_adapter = 0x7f27c3d46710,
acl_user_plugin = {str = 0x7f27a4004de0 "auth_socket", length = 11},
vio_is_encrypted = 0}

The user is then connected to the server as root.

An easy fix is to define authenticated_as in auth_socket.c.

Related branches

lp:~sergei.glushchenko/percona-server/5.5-ps-bug1289599
Laurynas Biveinis: Approve on 2014-03-14
lp:~sergei.glushchenko/percona-server/5.6-ps-bug1289599
Laurynas Biveinis: Approve on 2014-03-14
description: updated

When trying to reproduce this bug in Oracle version of mysql the socket_auth function is not called and the user is denied access.
So this bug only affect percona software. This bugs exist in both version 5.5 and 5.6.

Seems easy to confirm:

[openxs@centos ~]$ mysql -uroot test
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.15-56 Percona Server (GPL), Release rel63.0, Revision 519

Copyright (c) 2009-2013 Percona LLC and/or its affiliates
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select user, host from mysql.user;
+------+-----------+
| user | host |
+------+-----------+
| root | 127.0.0.1 |
| root | ::1 |
| | centos |
| root | centos |
| | localhost |
| root | localhost |
+------+-----------+
6 rows in set (0.03 sec)

mysql> install plugin auth_socket soname "auth_socket.so";
Query OK, 0 rows affected (0.11 sec)

mysql> drop user 'root'@'::1';
Query OK, 0 rows affected (0.02 sec)

mysql> drop user ''@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql> update mysql.user set plugin='auth_socket' where user='root';
Query OK, 3 rows affected (0.04 sec)
Rows matched: 3 Changed: 3 Warnings: 0

mysql> select user, host from mysql.user;
+------+-----------+
| user | host |
+------+-----------+
| root | 127.0.0.1 |
| | centos |
| root | centos |
| root | localhost |
+------+-----------+
4 rows in set (0.01 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> exit
Bye
[openxs@centos ~]$ mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.15-56 Percona Server (GPL), Release rel63.0, Revision 519

Copyright (c) 2009-2013 Percona LLC and/or its affiliates
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select user(), current_user();
+------------------+----------------+
| user() | current_user() |
+------------------+----------------+
| openxs@localhost | root@centos |
+------------------+----------------+
1 row in set (0.00 sec)

This should never happen as far as I can see from http://dev.mysql.com/doc/mysql-security-excerpt/5.5/en/socket-authentication-plugin.html

Same with PS 5.5:

[openxs@centos p5.5]$ bin/mysql -uopenxs
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.5.36-34.0 Source distribution

Copyright (c) 2009-2014 Percona LLC and/or its affiliates
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select user(), current_user();
+------------------+----------------+
| user() | current_user() |
+------------------+----------------+
| openxs@localhost | root@centos |
+------------------+----------------+
1 row in set (0.00 sec)
...

Here is a version of auth_socket.c that set info->authenticated_as and mitigate this bug.

After changing auth_socket.so:

[vike@localhost auth]$ mysql
ERROR 1698 (28000): Access denied for user 'vike'@'localhost'
[vike@localhost auth]$ sudo mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.6.15-56 Percona Server (GPL), Release rel63.0, Revision 519

Copyright (c) 2009-2013 Percona LLC and/or its affiliates
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> quit
Bye

information type: Private Security → Private
information type: Private → Private Security

The make_it_fail flag comes from MariaDB https://mariadb.atlassian.net/browse/MDEV-3909, thus MariaDB might be affected.

summary: - Authentication bypass
+ Authentication bypass if auth_socket installed

I am able to reproduce with MariaDB 5.5 trunk.

One session

[vagrant@vagrant mysql]$ bin/mysql -uroot
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 2
Server version: 5.5.37-MariaDB Source distribution

Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show variables like 'version%';
+-------------------------+---------------------+
| Variable_name | Value |
+-------------------------+---------------------+
| version | 5.5.37-MariaDB |
| version_comment | Source distribution |
| version_compile_machine | i686 |
| version_compile_os | Linux |
+-------------------------+---------------------+
4 rows in set (0.00 sec)

MariaDB [(none)]> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [mysql]> select user, host from user;
+------+-----------------------+
| user | host |
+------+-----------------------+
| root | 127.0.0.1 |
| root | ::1 |
| | localhost |
| root | localhost |
| | vagrant.vagrantup.com |
| root | vagrant.vagrantup.com |
+------+-----------------------+
6 rows in set (0.00 sec)

MariaDB [mysql]> delete from user where host <> '127.0.0.1';
Query OK, 5 rows affected (0.00 sec)

MariaDB [mysql]> update mysql.user set plugin = 'unix_socket';
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0

MariaDB [mysql]> select user, host, plugin from user;
+------+-----------+-------------+
| user | host | plugin |
+------+-----------+-------------+
| root | 127.0.0.1 | unix_socket |
+------+-----------+-------------+
1 row in set (0.00 sec)

MariaDB [mysql]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [mysql]> INSTALL PLUGIN unix_socket SONAME 'auth_socket.so';
Query OK, 0 rows affected (0.40 sec)

Another session:

[vagrant@vagrant mysql]$ bin/mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.37-MariaDB Source distribution

Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> select user(), current_user();
+-------------------+----------------+
| user() | current_user() |
+-------------------+----------------+
| vagrant@localhost | root@127.0.0.1 |
+-------------------+----------------+
1 row in set (0.00 sec)

MariaDB [(none)]>

MDEV-3909 copy in our bug db is bug 1171941.

information type: Private Security → Public Security
To post a comment you must log in.
This report contains Public Security information  Edit
Everyone can see this security related information.

Other bug subscribers

Bug attachments