Bug#480292: CVE-2008-2079: mysql allows local users to bypass certain privilege checks
tags 480292 +patch quit Here's a patch I'm building for an Etch update to address the problem. It's pretty close to the same one used in the first fix to this bug, except that it adds a call to realpath() to resolve all components of the path, and fixes the argument passing so as not to throw the resolved forms away. -- Devin \ aqua(at)devin.com, IRC:Requiem; http://www.devin.com Carraway \ 1024D/E9ABFCD2: 13E7 199E DD1E 65F0 8905 2E43 5395 CA0D E9AB FCD2 #! /bin/sh /usr/share/dpatch/dpatch-run ## 97_SECURITY_CVE-2008-2079.dpatch by [EMAIL PROTECTED] ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Fix for CVE-2008-2079: Some access checks could be bypassed by local ## DP: users creating tables with chosen data or index directory arguments ## DP: later reused by subsequently created tables. @DPATCH@ diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/mysql_priv.h mysql-dfsg-5.0-5.0.32/sql/mysql_priv.h --- mysql-dfsg-5.0-5.0.32.orig/sql/mysql_priv.h 2008-07-06 13:09:21.0 -0700 +++ mysql-dfsg-5.0-5.0.32/sql/mysql_priv.h 2008-07-06 13:13:21.0 -0700 @@ -1193,6 +1193,7 @@ extern time_t start_time; extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], + mysql_unpacked_real_data_home[], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; #define mysql_tmpdir (my_tmpdir(mysql_tmpdir_list)) extern MY_TMPDIR mysql_tmpdir_list; diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/mysqld.cc mysql-dfsg-5.0-5.0.32/sql/mysqld.cc --- mysql-dfsg-5.0-5.0.32.orig/sql/mysqld.cc2006-12-20 03:14:10.0 -0800 +++ mysql-dfsg-5.0-5.0.32/sql/mysqld.cc 2008-07-06 13:13:21.0 -0700 @@ -437,14 +437,13 @@ char mysql_real_data_home[FN_REFLEN], language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *opt_init_file, *opt_tc_log_file, + mysql_unpacked_real_data_home[FN_REFLEN], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; - +char *mysql_data_home= mysql_real_data_home; const key_map key_map_empty(0); key_map key_map_full(0);// Will be initialized later const char *opt_date_time_formats[3]; - -char *mysql_data_home= mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]; char *mysqld_unix_port, *opt_mysql_tmpdir; const char **errmesg; /* Error messages */ @@ -7356,6 +7355,9 @@ pos[1]= 0; } convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); + (void) fn_format(buff, mysql_real_data_home, , , + (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); + (void) unpack_dirname(mysql_unpacked_real_data_home, buff); convert_dirname(language,language,NullS); (void) my_load_path(mysql_home,mysql_home,); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/sql_parse.cc mysql-dfsg-5.0-5.0.32/sql/sql_parse.cc --- mysql-dfsg-5.0-5.0.32.orig/sql/sql_parse.cc 2008-07-06 13:09:21.0 -0700 +++ mysql-dfsg-5.0-5.0.32/sql/sql_parse.cc 2008-07-06 13:18:30.0 -0700 @@ -76,6 +76,7 @@ static void remove_escape(char *name); static bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); +static bool test_if_data_home_dir(const char *dir); static bool check_show_create_table_access(THD *thd, TABLE_LIST *table); const char *any_db=*any*;// Special symbol for check_access @@ -2890,6 +2891,20 @@ #ifndef HAVE_READLINK lex-create_info.data_file_name=lex-create_info.index_file_name=0; #else + +if (test_if_data_home_dir(lex-create_info.data_file_name)) +{ + my_error(ER_WRONG_ARGUMENTS,MYF(0),DATA DIRECORY); + res= -1; + break; +} +if (test_if_data_home_dir(lex-create_info.index_file_name)) +{ + my_error(ER_WRONG_ARGUMENTS,MYF(0),INDEX DIRECORY); + res= -1; + break; +} + /* Fix names if symlinked tables */ if (append_file_to_dir(thd, lex-create_info.data_file_name, create_table-table_name) || @@ -7664,3 +7679,50 @@ return TRUE; } + + +/* + Check if path does not contain mysql data home directory + + SYNOPSIS +test_if_data_home_dir() +dir directory +conv_home_dir converted data home directory +home_dir_lenconverted data home directory length + + RETURN VALUES +0 ok +1 error +*/ + +static bool test_if_data_home_dir(const char *dir) +{ + char path[FN_REFLEN], conv_path[PATH_MAX+1], real_path[PATH_MAX+1]; + uint dir_len, home_dir_len= strlen(mysql_unpacked_real_data_home); + DBUG_ENTER(test_if_data_home_dir); + + if (!dir) +DBUG_RETURN(0); + + (void) fn_format(path, dir, , , + (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); + if (!realpath(path, real_path)) +DBUG_RETURN(1); + dir_len=
Bug#480292: CVE-2008-2079: mysql allows local users to bypass certain privilege checks
On Fri, Jul 04, 2008 at 02:56:00PM +0200, Tomas Hoger wrote: Looks like upstream patch is incomplete. Have you already notified upstream about the problem? Not yet -- I still need to hand verify it against a pristine upstream; it's reproducible with 5.0.51a from Sid, but the implementation of the path check has changed significantly from the original patch. I'll look into that once I get a workable fix out for etch. In terms of exploitability, this allows any user with permissions to create tables in a db the ability to read from, write to and delete tables from any other database within the same mysql instance. Can you possibly explain this a little closer? MySQL should not allow you to overwrite existing tables via DATA/INDEX DIRECTORY directives. So you can only get access to tables created in the future, if you can predict their names. Or have you managed to escalate privileges to already existing tables using this flaw? Sorry, I was taking the temporal part of the attack as read -- yes, the attack is still based on creating the hostile tables before the victim database does. -- Devin \ aqua(at)devin.com, IRC:Requiem; http://www.devin.com Carraway \ 1024D/E9ABFCD2: 13E7 199E DD1E 65F0 8905 2E43 5395 CA0D E9AB FCD2 signature.asc Description: Digital signature
Bug#480292: CVE-2008-2079: mysql allows local users to bypass certain privilege checks
Hi Devin! Looks like upstream patch is incomplete. Have you already notified upstream about the problem? In terms of exploitability, this allows any user with permissions to create tables in a db the ability to read from, write to and delete tables from any other database within the same mysql instance. Can you possibly explain this a little closer? MySQL should not allow you to overwrite existing tables via DATA/INDEX DIRECTORY directives. So you can only get access to tables created in the future, if you can predict their names. Or have you managed to escalate privileges to already existing tables using this flaw? Thanks! -- Tomas Hoger -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#480292: CVE-2008-2079: mysql allows local users to bypass certain privilege checks
reopen 480292 quit I don't believe that the patch applied to address this bug was sufficient. In preparing the stable update I initially applied it, before finding two things: First, fn_format() only calls readlink() once on the entire path, not on any component thereof; hence it will only actually detect when the last component of a path was a symlink. Exploiting this merely requires adding another path component below the symlink path -- for example: $ ls -l /tmp/foo lrwxrwxrwx 1 aqua 1000 14 Jul 3 05:36 /tmp/foo - /var/lib/mysql mysql use test1 ; Database changed mysql create table t (a int) data directory '/tmp/foo' ; ERROR 1210 (HY000): Incorrect arguments to DATA DIRECORY mysql create table t (a int) data directory '/tmp/foo/mysql' ; Query OK, 0 rows affected (0.02 sec) $ ls -l /var/lib/mysql/mysql/t.MYD -rw-rw 1 mysql mysql 0 Jul 3 07:27 /var/lib/mysql/mysql/t.MYD Second, even if fn_format() did fully resolve symlinks in the path, its output is actually ignored; this is an except from 92_SECURITY_CVE-2008-2079.dpatch in mysql-dfsg-5.0 5.0.51a-9: +static bool test_if_data_home_dir(const char *dir) +{ [...] + (void) fn_format(path, dir, , , + (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); + dir_len= unpack_dirname(conv_path, dir); [...] +else if (!memcmp(conv_path, mysql_unpacked_real_data_home, home_dir_len)) + DBUG_RETURN(1); fn_format reads the potentially hostile 'dir' and writes the marginally readlink()'ed result to 'path'. But unpack_dirname is passed 'dir' again, not 'path', so it's the origianl string which is used in the subsequent comparison. In terms of exploitability, this allows any user with permissions to create tables in a db the ability to read from, write to and delete tables from any other database within the same mysql instance. -- Devin \ aqua(at)devin.com, IRC:Requiem; http://www.devin.com Carraway \ 1024D/E9ABFCD2: 13E7 199E DD1E 65F0 8905 2E43 5395 CA0D E9AB FCD2 signature.asc Description: Digital signature
Bug#480292: CVE-2008-2079: mysql allows local users to bypass certain privilege checks
Package: mysql-server-5.0 Severity: grave Tags: security Justification: user security hole Hi The following CVE(0) has been issued against mysql. CVE-2008-2079: MySQL 4.1.x before 4.1.24, 5.0.x before 5.0.60, 5.1.x before 5.1.24, and 6.0.x before 6.0.5 allows local users to bypass certain privilege checks by calling CREATE TABLE on a MyISAM table with modified (1) DATA DIRECTORY or (2) INDEX DIRECTORY arguments that are within the MySQL home data directory, which can point to tables that are created in the future. Please mention the CVE id in your changelog, if you fix the issue by an upload. The mysql bugreport can be found here(1). Cheers Steffen (0): http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-2079 (1): http://bugs.mysql.com/bug.php?id=32167 -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]