COMMAND
MySQL
SYSTEMS AFFECTED
All versions are vulnerable on all platforms.
PROBLEM
Robert van der Meulen found following. Below you find a security
advisory Robert wrote concerning a vulnerability found in all
mysql server versions, including the latest one.
There exists a vulnerability in the password checking routines in
the latest versions of the MySQL server, that allows any user on
a host that is allowed to connect to the server, to skip password
authentication, and access databases. For the exploit to work, a
valid username for the mysql server is needed, and this username
must have access to the database server, when connecting from the
attacking host.
A snippet of code from the mysql code, explaining password
authentication:
>From mysql-3.22.26a/sql/password.c:
/* password checking routines */
/*****************************************************************************
The main idea is that no password are sent between client & server on
connection and that no password are saved in mysql in a decodable form.
On connection a random string is generated and sent to the client.
The client generates a new string with a random generator inited with
the hash values from the password and the sent string.
This 'check' string is sent to the server where it is compared with
a string generated from the stored hash_value of the password and the
random string.
<cut>
*****************************************************************************/
The problem is, that in the comparison between the 'check' string,
and the string generated from the hash_value of the password and
the random string, the following code is used (from
mysql-3.22.26a/sql/password.c):
while (*scrambled)
{
if (*scrambled++ != (char) (*to++ ^ extra))
return 1; /* Wrong password */
}
'scrambled' represents the 'check' value, and (*to++ ^ extra)
walks trough the hash_value. Suppose a client would send a
_single_ character to the server as the 'check' string. Of
course the server should notice the check string is not the same
length as the check string needed, and give a password error.
Because no such checks are done, when a check string of length 1
is passed to the server, only one character is compared. So the
only thing that remains to know if we want to peek in someone's
MySQL database, is a technique to find out the first character of
the server-side check string.
The string that's used for the comparison is generated using some
random data, so two following authenticate-actions will probably
use different check-strings. After looking at the algorithm,
generating the check string, it becomes clear that there are
actually only 32 possibilities for each character. In practice,
this means that if you connect, sending one single character as
the check string, you will be in in about 32 tries maximum.
Hosts in the access list (by default any host, on a lot of
distributions and servers) can connect to the MySQL server,
without a password, and access (often sensitive) data _as long as
the attacker has a valid username for the database server_. This
vulnerability also incorporates a MySQL DoS attack, as the
attacker can shutdown database servers and delete data, if she
logs in with the MySQL management account.
Robert has an exploit available, but to defer script kiddies he
will not release it (yet). If above explanation is understood, an
exploit should be easy enough...
SOLUTION
The official patch to fix this follows:
*** /my/monty/master/mysql-3.23.10-alpha/sql/sql_parse.cc Sun Jan 30 10:42:42 2000
--- ./sql_parse.cc Wed Feb 9 16:05:49 2000
***************
*** 17,22 ****
--- 17,24 ----
#include <m_ctype.h>
#include <thr_alarm.h>
+ #define SCRAMBLE_LENGTH 8
+
extern int yyparse(void);
extern "C" pthread_mutex_t THR_LOCK_keycache;
***************
*** 188,195 ****
end=strmov(buff,server_version)+1;
int4store((uchar*) end,thd->thread_id);
end+=4;
! memcpy(end,thd->scramble,9);
! end+=9;
#ifdef HAVE_COMPRESS
client_flags |= CLIENT_COMPRESS;
#endif /* HAVE_COMPRESS */
--- 190,197 ----
end=strmov(buff,server_version)+1;
int4store((uchar*) end,thd->thread_id);
end+=4;
! memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1);
! end+=SCRAMBLE_LENGTH +1;
#ifdef HAVE_COMPRESS
client_flags |= CLIENT_COMPRESS;
#endif /* HAVE_COMPRESS */
***************
*** 268,273 ****
--- 270,277 ----
char *user= (char*) net->read_pos+5;
char *passwd= strend(user)+1;
char *db=0;
+ if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
+ return ER_HANDSHAKE_ERROR;
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
db=strend(passwd)+1;
if (thd->client_capabilities & CLIENT_INTERACTIVE)
MySQL 3.22.32 fixes a couple of possible security holes in MySQL
3.22 including this one. 3.23.x is also out.
For FreeBSD do one of the following:
1) Upgrade your entire ports collection and rebuild the
mysql322-server port.
2) Reinstall a new package obtained from:
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-3-stable/databases/mysql-server-3.22.32.tgz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-4-current/databases/mysql-server-3.22.32.tgz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-4-current/databases/mysql-server-3.22.32.tgz
3) download a new port skeleton for the mysql322-server port
from:
http://www.freebsd.org/ports/
and use it to rebuild the port.
4) Use the portcheckout utility to automate option (3) above.
The portcheckout port is available in
/usr/ports/devel/portcheckout or the package can be
obtained from:
ftp://ftp.freebsd.org/pub/FreeBSD/ports/packages/devel/portcheckout-2.0.tgz
For Turbo Linux see:
rpm -Fv ftp://ftp.turbolinux.com/pub/updates/6.0/security/MySQL-3.22.32-1.i386.rpm
The source rpm can be downloaded here:
ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/MySQL-3.22.32-1.src.rpm
Note: You must rebuild and install the rpm if you choose to
download and install the srpm. Simply installing the srpm alone
WILL NOT CLOSE THE SECURITY HOLE.