|
Brought to you by:
Suppliers of:
|
|
|
| |
There is a vulnerability in the password checking routines of the latest MySQL server versions, which allows a remote attacker to skip the password authentication, and access local databases. For the exploit to work, a valid username for the MySQL server is needed, and this username must have remote access to the database server from the attacking host.
Hosts in the access list (note that all hosts are allowed access by default on many distributions) 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, by logging in with the MySQL management account. |
| |
Credit:
The information was provided by: Robert van der Meulen.
|
| |
Vulnerable systems:
All versions are vulnerable on all platforms
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 is 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 that generates 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 after a maximum of 32 tries.
Patch:
*** /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)
RPMs:
New RPMs should arrive shortly to http://www.mysql.org and all its mirrors.
|
|
|
|
|