Bug #53371 Parent directory entry ("..") can be abused to bypass table level grants.
Submitted: 3 May 2010 12:40 Modified: 14 Oct 2010 14:54
Reporter: Davi Arnaut (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: General Severity:S2 (Serious)
Version:5.0 and up OS:Any
Assigned to: Georgi Kodinov

[3 May 2010 12:40] Davi Arnaut
Description:
The COM_FIELD_LIST command can be used (eg: via mysql_list_fields) to open any table in the data directory, bypassing almost all forms of checks for privileges and table level grants.

How to repeat:
=== modified file 'tests/mysql_client_test.c'
--- tests/mysql_client_test.c   2009-11-03 00:52:57 +0000
+++ tests/mysql_client_test.c   2010-05-03 12:33:16 +0000
@@ -18049,6 +18049,31 @@ static void test_bug44495()
   DBUG_VOID_RETURN;
 }
 
+
+static void test_list_fields_bug()
+{
+  int rc;
+  MYSQL_RES *result;
+
+  rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+
+  rc= mysql_query(mysql, "CREATE DATABASE db1");
+  myquery(rc);
+
+  rc= mysql_query(mysql, "GRANT SELECT ON db1.* to 'testbug'@localhost");
+  myquery(rc);
+
+  rc= mysql_change_user(mysql, "testbug", NULL, "db1");
+  myquery(rc);
+
+  rc= mysql_query(mysql, "SHOW COLUMNS FROM client_test_db.t1");
+  DIE_UNLESS(rc);
+  DIE_UNLESS(mysql_errno(mysql) == 1142);
+
+  result= mysql_list_fields(mysql, "#mysql50#/../client_test_db/t1", NULL);
+  DIE_IF(result);
+}
+
 /*
   Read and parse arguments and MySQL options from my.cnf
 */
@@ -18130,6 +18155,7 @@ and you are welcome to modify and redist
 
 
 static struct my_tests_st my_tests[]= {
+  { "test_list_fields_bug", test_list_fields_bug },
   { "disable_general_log", disable_general_log },
   { "test_view_sp_list_fields", test_view_sp_list_fields },
   { "client_query", client_query },

Suggested fix:
Check the table name (eg: via check_table_name()) supplied by the user.
[3 May 2010 13:48] Georgi Kodinov
Can't get the problem as listed in 5.0-bugteam (probably due to #mysql50# prefix)
[3 May 2010 14:25] Georgi Kodinov
No 5.0 counterpart : changing the version to 5.1 and up
[3 May 2010 14:48] Davi Arnaut
Same problem on 5.0, just remove the #mysql50# and problem should be the same.
[3 May 2010 14:50] Georgi Kodinov
Verified as described in 5.0-bugteam with the following test case : 
 61 static void test_bug53371()
 62 {
 63   int rc;
 64   MYSQL_RES *result;
 65   static char query[200];
 66 
 67   myheader("test_bug53371");
 68 
 69   rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
 70 
 71   rc= mysql_query(mysql, "CREATE DATABASE db1");
 72   myquery(rc);
 73 
 74   rc= mysql_query(mysql, "GRANT SELECT ON db1.* to 'testbug'@localhost");
 75   myquery(rc);
 76 
 77   rc= mysql_change_user(mysql, "testbug", NULL, "db1");
 78   myquery(rc);
 79   
 80   rc= mysql_query(mysql, "SHOW COLUMNS FROM client_test_db.t1");
 81   if (rc)
 82   { 
 83     sprintf(query, "DROP DATABASE IF EXISTS db1");
 84     mysql_query(mysql, query);
 85     DIE_UNLESS(rc);
 86   }
 87   if (mysql_errno(mysql) == 1142)
 88   {
 89     sprintf(query, "DROP DATABASE IF EXISTS db1");
 90     mysql_query(mysql, query);
 91     DIE_UNLESS(mysql_errno(mysql) == 1142);
 92   }
 93 
 94   result= mysql_list_fields(mysql, "../client_test_db/t1", NULL);
 95   fprintf (stdout, "result=%p\n", result);
 96   if (result)
 97   {
 98     sprintf(query, "DROP DATABASE IF EXISTS db1");
 99     mysql_query(mysql, query);
100     DIE_IF(result);
101   }
102 
103   mysql_change_user(mysql, opt_user, opt_password, current_db);
104   sprintf(query, "DROP DATABASE IF EXISTS db1");
105   mysql_query(mysql, query);
106   sprintf(query, "DROP user 'testbug'@localhost");
107   mysql_query(mysql, query);
108 }
[4 May 2010 8:00] Georgi Kodinov
In 5.1 it's even worse : 

mysql> GRANT SELECT ON db1.* to 'testbug'@localhost;
--------------
GRANT SELECT ON db1.* to 'testbug'@localhost
--------------

Query OK, 0 rows affected (0.00 sec)

mysql> create database db2;
--------------
create database db2
--------------

Query OK, 1 row affected (0.00 sec)

mysql> use db2;
Database changed

mysql> create table tb2 (a int);
--------------
create table tb2 (a int)
--------------

Query OK, 0 rows affected (0.01 sec)

$ ../client/mysql --socket=var/tmp/mysqld.1.sock -v -v -v -u testbug db1
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.1.47-debug-log Source distribution

testbug> desc db2.tb2;
--------------
desc db2.tb2
--------------

ERROR 1142 (42000): SELECT command denied to user 'testbug'@'localhost' for table 'tb2'
testbug> desc `../db2/tb2`;
--------------
desc `../db2/tb2`
--------------

+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a     | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

testbug> select * from `../db2/tb2`;
--------------
select * from `../db2/tb2`
--------------

Empty set (0.00 sec)
[4 May 2010 11:37] Georgi Kodinov
Commit comment to be :
Bug #53371: COM_FIELD_LIST can be abused to bypass table level grants.

This is the 5.1 merge and extension of the fix.
The server was happily accepting paths in table name in all places a table
name is accepted (e.g. a SELECT). This allowed all users that have some 
privilege over some database to read all tables in all databases in all
mysql server instances that the server file system has access to.
Fixed by :
1. making sure no path elements are allowed in quoted table name when
constructing the path (note that the path symbols are still valid in table names
when they're properly escaped by the server).
2. checking the #mysql50# prefixed names the same way they're checked for
path elements in mysql-5.0.
[5 May 2010 13:34] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/107532

2862 Sunanda Menon	2010-05-05
      ------------------------------------------------------------
      revno: 2861
      committer: Georgi Kodinov <joro@sun.com>
      branch nick: B53371-5.0-bugteam
      timestamp: Mon 2010-05-03 18:16:51 +0300
      message:
        Bug #53371: COM_FIELD_LIST can be abused to bypass table level grants.
        
        The server was not checking the supplied to COM_FIELD_LIST table name
        for validity and compliance to acceptable table names standards.
        Fixed by checking the table name for compliance similar to how it's 
        normally checked by the parser and returning an error message if 
        it's not compliant.
[5 May 2010 15:21] Bugs System
Pushed into 5.1.47 (revid:joro@sun.com-20100505145753-ivlt4hclbrjy8eye) (version source revid:joro@sun.com-20100504140328-srxf3c088j2twnq6) (merge vers: 5.1.47) (pib:16)
[7 May 2010 8:16] Lenz Grimmer
This is now tracked as CVE-2010-1848 on http://cve.mitre.org/
[11 May 2010 16:19] Paul Dubois
Noted in 5.1.47 changelog.

COM_FIELD_LIST could be abused to bypass table level privileges.
[11 May 2010 16:42] Paul Dubois
Revised changelog entry:

The server failed to check the table name argument of a
COM_FIELD_LIST command packet for validity and compliance to
acceptable table name standards. This could be exploited to bypass
almost all forms of checks for privileges and table level grants by
providing a specially crafted table name argument to COM_FIELD_LIST.

In MySQL 5.0 and above, this allowed an authenticated user with
SELECT privileges on one table to obtain the field definitions of any
table in all other databases and potentially of other MySQL instances
accessible from the server's file system.

Additionally, for MySQL version 5.1 and above, an authenticated user
with DELETE or SELECT privileges on one table could delete or read
content from any other table in all databases on this server, and
potentially of other MySQL instances accessible from the server's
file system. 

Setting report to Need Merge pending further pushes.
[18 May 2010 23:12] Paul Dubois
Noted in 5.0.91 changelog.
[28 May 2010 6:03] Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100524190136-egaq7e8zgkwb9aqi) (version source revid:alik@sun.com-20100512070920-xgpmqeytp0gc183c) (pib:16)
[28 May 2010 6:32] Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20100524190941-nuudpx60if25wsvx) (version source revid:alik@sun.com-20100507093037-7cykrx1n73v0tetc) (merge vers: 6.0.14-alpha) (pib:16)
[28 May 2010 6:59] Bugs System
Pushed into 5.5.5-m3 (revid:alik@sun.com-20100524185725-c8k5q7v60i5nix3t) (version source revid:alexey.kopytov@sun.com-20100508220335-xsvmtj21h4yeu8mf) (merge vers: 5.5.5-m3) (pib:16)
[29 May 2010 2:35] Paul Dubois
Noted in 5.5.5, 6.0.14 changelogs.
[2 Jun 2010 8:48] Bugs System
Pushed into 5.1.48 (revid:georgi.kodinov@oracle.com-20100602084411-2yu607bslbmgufl3) (version source revid:georgi.kodinov@oracle.com-20100601114824-nhjv6docksomzm4f) (merge vers: 5.1.48) (pib:16)
[3 Jun 2010 23:22] Paul Dubois
Already fixed in 5.1.x.
[17 Jun 2010 6:12] Bugs System
Pushed into 5.5.5-m3 (revid:alexey.kopytov@sun.com-20100615145247-8bj0vmuqlotbqsn9) (version source revid:georgi.kodinov@oracle.com-20100601123137-l8svn3xfxtp0y8nk) (merge vers: 5.5.5-m3) (pib:16)
[17 Jun 2010 6:15] Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100615150216-cubqoyn1fj9b6a2p) (version source revid:alik@sun.com-20100607075151-xjus8wzgjv3g9ok0) (pib:16)
[17 Jun 2010 12:07] Bugs System
Pushed into 5.1.47-ndb-7.0.16 (revid:martin.skold@mysql.com-20100617114014-bva0dy24yyd67697) (version source revid:martin.skold@mysql.com-20100616204905-jxjg342w35ks9vfy) (merge vers: 5.1.47-ndb-7.0.16) (pib:16)
[17 Jun 2010 12:53] Bugs System
Pushed into 5.1.47-ndb-6.2.19 (revid:martin.skold@mysql.com-20100617115448-idrbic6gbki37h1c) (version source revid:martin.skold@mysql.com-20100615090726-jotpykke96le59w5) (merge vers: 5.1.47-ndb-6.2.19) (pib:16)
[17 Jun 2010 13:34] Bugs System
Pushed into 5.1.47-ndb-6.3.35 (revid:martin.skold@mysql.com-20100617114611-61aqbb52j752y116) (version source revid:martin.skold@mysql.com-20100616120453-jh7wr05z1vf7r8pm) (merge vers: 5.1.47-ndb-6.3.35) (pib:16)
[6 Jul 2010 19:04] Paul Dubois
Noted in 5.1.46sp1 changelog.
[8 Jul 2010 18:53] Bugs System
Pushed into 5.1.49 (revid:sunanda.menon@sun.com-20100708184626-16el4v8gjjci6m1r) (version source revid:sunanda.menon@sun.com-20100708184626-16el4v8gjjci6m1r) (merge vers: 5.1.49) (pib:16)
[4 Aug 2010 7:49] Bugs System
Pushed into mysql-trunk 5.5.6-m3 (revid:alik@sun.com-20100731131027-1n61gseejyxsqk5d) (version source revid:alik@sun.com-20100731074942-o840woifuqioxxe4) (merge vers: 5.5.6-m3) (pib:18)
[4 Aug 2010 8:09] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 8:25] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804081533-c1d3rbipo9e8rt1s) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 9:04] Bugs System
Pushed into mysql-next-mr (revid:alik@ibmvm-20100804081630-ntapn8bf9pko9vj3) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (pib:20)
[4 Aug 2010 22:54] Paul Dubois
Already fixed in 5.1.x, 5.5.x.
Bug does not appear in any released 5.6.x version.
[14 Oct 2010 8:36] Bugs System
Pushed into mysql-5.1-telco-7.0 5.1.51-ndb-7.0.20 (revid:martin.skold@mysql.com-20101014082627-jrmy9xbfbtrebw3c) (version source revid:martin.skold@mysql.com-20101014082627-jrmy9xbfbtrebw3c) (merge vers: 5.1.51-ndb-7.0.20) (pib:21)
[14 Oct 2010 8:51] Bugs System
Pushed into mysql-5.1-telco-6.3 5.1.51-ndb-6.3.39 (revid:martin.skold@mysql.com-20101014083757-5qo48b86d69zjvzj) (version source revid:martin.skold@mysql.com-20101014083757-5qo48b86d69zjvzj) (merge vers: 5.1.51-ndb-6.3.39) (pib:21)
[14 Oct 2010 9:06] Bugs System
Pushed into mysql-5.1-telco-6.2 5.1.51-ndb-6.2.19 (revid:martin.skold@mysql.com-20101014084420-y54ecj85j5we27oa) (version source revid:martin.skold@mysql.com-20101014084420-y54ecj85j5we27oa) (merge vers: 5.1.51-ndb-6.2.19) (pib:21)
[14 Oct 2010 14:54] Jon Stephens
Already documented as noted; no new changelog entries required. setting back to Closed state.