Bug #53748 INDEX/DATA DIRECTORY realpath(3) race allows access to server data dir
Submitted: 18 May 2010 12:30 Modified: 27 May 2010 20:20
Reporter: Matt McCutchen Email Updates:
Status: Verified Impact on me:
Category:MySQL Server: MyISAM storage engine Severity:S3 (Non-critical)
Version:5.1.46 OS:Linux (Fedora 12)
Assigned to: CPU Architecture:Any
Tags: Security

[18 May 2010 12:30] Matt McCutchen
The server tries to prevent use of the INDEX/DATA DIRECTORY options to access tables inside the server data dir (http://bugs.mysql.com/bug.php?id=39277#c197641, first item under "Using symbolic links you cannot").  However, a user with shell access can defeat this check by exploiting the race in the use of realpath(3) to canonicalize the INDEX/DATA DIRECTORY path.  A directory in the path can be replaced with a symlink after realpath(3) has processed it so that the returned path points into the server data dir even though it appears not to.

I will attach a kit of scripts to demonstrate the attack.  In my tests using Fedora 12's mysql-5.1.46-1.fc12.x86_64 on a Dell Latitude D620, the attack has succeeded in gaining access to the mysql.user table on most of the attempts.

How to repeat:
Follow the instructions in the demonstration kit.

Suggested fix:
Retract the claim that symlinks cannot be used to access tables in the server data dir, and consider enabling the skip-symbolic-links configuration option by default.  (skip-symbolic-links is the default in Fedora rawhide since January, see https://bugzilla.redhat.com/show_bug.cgi?id=553652 .)
[18 May 2010 12:31] Matt McCutchen
Demonstration kit

Attachment: mysql-symlink-race.tar.bz2 (application/x-bzip2, text), 5.96 KiB.

[26 May 2010 6:36] Sveta Smirnova
Thank you for the report.

But fix for bug #39277 didn't go to 5.1 ("[24 Nov 2008 15:56] Ingo Strüwing ...Note that this will be fixed in 6.0 as it was rated too much of a "corner case" and too less of a security problem to be included into 5.1.")

Have you tried version 5.5.4?
[26 May 2010 17:06] Matt McCutchen
Apparently the Fedora version of MySQL 5.1 that I tested does include the fix for bug #39277.  See:


I will test 5.5.4.
[26 May 2010 17:43] Sveta Smirnova
Thank you for the update.

We can not guarantee how third-party backports will work, therefore I will wait information of testing in your environment of version 5.5.4. Please use our binaries.
[26 May 2010 20:27] Matt McCutchen
I tested the 5.5.4 binary (http://dev.mysql.com/downloads/mirror.php?id=386832).  I just had to replace user-schema.sql with the updated schema for MySQL 5.5.4, and then the attack worked.
[26 May 2010 20:28] Matt McCutchen
User table schema file for MySQL 5.5.4

Attachment: user-schema-5.5.4.sql (application/octet-stream, text), 2.81 KiB.

[27 May 2010 17:39] Sveta Smirnova
Thank you for the feedback.

In my case it does not get information from user table, but crashes server with:

Program terminated with signal 11, Segmentation fault.
#0  0x000000342923c2a4 in realpath@@GLIBC_2.3 () from /lib64/libc.so.6
(gdb) bt
#0  0x000000342923c2a4 in realpath@@GLIBC_2.3 () from /lib64/libc.so.6
#1  0x00000000009fb8e8 in my_realpath (to=0x48c4d650 "pÖÄH", filename=0x48c4d450 "./test/user.MYI", MyFlags=0) at /users/ssmirnova/blade12/src/mysql-next-mr/mysys/my_symlink.c:132
#2  0x000000000098683a in mi_open (name=0x15ba02d0 "./test/user", mode=2, open_flags=66) at /users/ssmirnova/blade12/src/mysql-next-mr/storage/myisam/mi_open.c:97
#3  0x000000000095d45e in ha_myisam::open (this=0x15be4438, name=0x15ba02d0 "./test/user", mode=2, test_if_locked=2) at /users/ssmirnova/blade12/src/mysql-next-mr/storage/myisam/ha_myisam.cc:706
#4  0x000000000071e106 in handler::ha_open (this=0x15be4438, table_arg=0x15be63a8, name=0x15ba02d0 "./test/user", mode=2, test_if_locked=2)
    at /users/ssmirnova/blade12/src/mysql-next-mr/sql/handler.cc:2105
#5  0x000000000065d4f2 in open_table_from_share (thd=0x15b88c58, share=0x15b9ff38, alias=0x15be0460 "user", db_stat=39, prgflag=44, ha_open_flags=0, outparam=0x15be63a8, is_create_table=false)
    at /users/ssmirnova/blade12/src/mysql-next-mr/sql/table.cc:1929
#6  0x0000000000562297 in open_table (thd=0x15b88c58, table_list=0x48c4e990, mem_root=0x48c4e110, ot_ctx=0x48c4e150, flags=2048) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_base.cc:2912
#7  0x000000000056496e in open_and_process_table (thd=0x15b88c58, lex=0x15b8a4d0, tables=0x48c4e990, counter=0x48c4e2bc, flags=2048, prelocking_strategy=0x48c4e240, has_prelocking_list=false, 
    ot_ctx=0x48c4e150, new_frm_mem=0x48c4e110) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_base.cc:4245
#8  0x00000000005654a6 in open_tables (thd=0x15b88c58, start=0x48c4e280, counter=0x48c4e2bc, flags=2048, prelocking_strategy=0x48c4e240) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_base.cc:4645
#9  0x000000000056f819 in open_tables (thd=0x15b88c58, tables=0x48c4e280, counter=0x48c4e2bc, flags=2048) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_base.h:345
#10 0x0000000000566406 in open_normal_and_derived_tables (thd=0x15b88c58, tables=0x48c4e990, flags=2048) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_base.cc:5262
#11 0x00000000006102b6 in mysqld_list_fields (thd=0x15b88c58, table_list=0x48c4e990, wild=0x15be0470 "") at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_show.cc:837
#12 0x00000000005af1ce in dispatch_command (command=COM_FIELD_LIST, thd=0x15b88c58, packet=0x15bbb19e "", packet_length=5) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_parse.cc:1204
#13 0x00000000005adeef in do_command (thd=0x15b88c58) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_parse.cc:774
#14 0x000000000068ebce in do_handle_one_connection (thd_arg=0x15b88c58) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_connect.cc:1188
#15 0x000000000068ea7a in handle_one_connection (arg=0x15b88c58) at /users/ssmirnova/blade12/src/mysql-next-mr/sql/sql_connect.cc:1127
#16 0x0000003429e061b5 in start_thread () from /lib64/libpthread.so.0
#17 0x00000034292cd39d in clone () from /lib64/libc.so.6
#18 0x0000000000000000 in ?? ()
[27 May 2010 20:20] Matt McCutchen
That's weird.  realpath should never crash unless the mysql server has corrupted memory or passed it a bad pointer, but I don't see how playing with symlinks would cause either of those.

Where in realpath does the crash occur?  If the server is run under valgrind, does the crash still occur, and do any memory errors occur up to that point?  (The timings in the attack script would need to be increased, of course.)
[31 Dec 2014 13:27] Daniël van Eeden
Is this bug only affecting MyISAM and 5.1? Or might it also affect 5.6/5.7 and InnoDB?