COMMAND
MySQL
SYSTEMS AFFECTED
Systems running MySQL
PROBLEM
Sandu Mihai posted following that may occur if you were using
MySQL. Basicly, it's a configuration problem, but still may give
unprivileged user those rights you woudn't want to. When you use
a certain mysql configuration it is possible to create files on
the system as root with rw-rw-rw. Many MySQL users have included
user root from localhost without password in their config. If on
such a system you issue:
mysql -u root test
you not only will have access to the database but you'll be able
to create a file on the system with the root ownership and
rw-rw-rw useing the SELECT .. INTO OUTFILE statement. The file
you wish to create must NOT EXIST. Otherwise mysql will give you
a "file already exists" error. To be more precise. MySQL will
create the file specified as OUTFILE with rw-rw-rw and with the
current user as owner. The exploit is as follows:
mysql -u root test
CREATE TABLE ll ( a CHAR(10) );
INSERT INTO aa (a) VALUES ("+ +");
SELECT * FROM aa INTO OUTFILE "/root/.rhosts";
The above exploit works for sites with rexec,rsh enabled (ssh is
too smart and won't let you in if you have .rhosts 666, the same
for authorized_keys). If someone could fool MySQL into makeing
the file 600 then this is quite a serious threat. This was tested
under Mysql Ver 6.5 Distrib 3.20.29.
SOLUTION
This is a configuration problem. It can be easily solved by adding
a password and/or changing the file_priv column to 'N' for this
user in the user table in the mysql database. Nonetheless is
advisable for people running mySQL to check their configuration
for any users with file_priv that should not have it. Ben Laurie
posted following patch that fixes this problem (on FreeBSD at
least), if you add "MYSQL_USER=someuser; export MYSQL_USER" to
safe_mysqld:
--- mysqld.cc.orig Tue Mar 31 19:27:53 1998
+++ mysqld.cc Tue Mar 31 19:35:59 1998
@@ -57,6 +57,8 @@
#define SET_RLIMIT_NOFILE
#endif
+#include <pwd.h>
+
#define MAX_RETRY 10 // Test accept this many times
#define CONNECT_TIMEOUT 3 // Don't wait long for connect
@@ -291,6 +293,33 @@
}
}
+static void set_user()
+{
+ struct passwd *ent;
+ char *user;
+
+// don't bother if we aren't superuser
+ if(geteuid())
+ return;
+
+ if(!(user = getenv("MYSQL_USER")))
+ return;
+
+ if(!(ent = getpwnam(user)))
+ {
+ perror("getpwnam");
+ application_end();
+ unireg_abort(1);
+ }
+
+ if(setuid(ent->pw_uid) == -1)
+ {
+ perror("setuid");
+ application_end();
+ unireg_abort(1);
+ }
+}
+
static void server_init(void)
{
@@ -336,6 +365,9 @@
application_end();
unireg_abort(1);
}
+
+ set_user();
+
VOID(listen(ip_sock,(int) back_log));
}