MySQL Allows Password Bypass Reported Feburary 9, 2000 by Robert van der Meulen/Emphyrio and Willem Pinckaers
VERSIONS AFFECTED
MySQL 3.22.26a
and later, and possibly earlier versions
DESCRIPTION
The MySQL database server contains a vulnerability
within the password checking routines that allow a person to easily access restricted
databases.
To exploit this bug, a valid username is needed where that
user must have access to the database server.
The authentication concepts used in MySQL dictate that no passwords are sent between
client & server upon connection and that no passwords are stoerd within MySQL in any
decodable form.
Upon connection to the server, the server sends to the client where the client generates a
new string with a random generator initiated with the hash values from the password along
with the string received by the client.
This client-developed check string is then sent to the
server where it is compared with a string generated from the stored hash_value of the
password along with the random string.
The problem is that there are bugs in the code used to perform the comparison between the
check string and the string generated from the hash_value of the password and random
string,
Here is the code is used as extracted from
mysql-3.22.26a/sql/password.c :
while (*scrambled)
\{
if (*scrambled++ != (char) (*to++ ^ extra))
return 1; /* Wrong password */
\}
The value "scrambled" represents the check value while the code snipet (*to++
^ extra) parses the hash_value.
Now suppose a client sends a single character to the server
as the check string. With the code written the way it is, a single character string would
cause a comparison of only the first character of the actual password to the single
character check string. In other words, if you can determine the first character of the
server-side check string (based on the actual password) then an unauthorized user could
gain authentication.
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 that generates the check
string it is clear that there are actually only 32 possibilities for each character.
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 data as long as the attacker
has a valid username for the database server.
To correct this matter change the routine "check_scramble"
in the MySQL code file password.c so that performs a string length check BEFORE starting
the comparison routine.
This should be as easy as using the following code:
if (strlen(scrambled)!=strlen(to)) \{
return 1;
\}
while (*scrambled)
\{
if (*scrambled++ != (char) (*to++ ^ extra))
return 1; /* Wrong password */
\}
WARNING: This is NOT an official fix. You may use this as a temporary solution to
the problem, however no guarantees are expressed or implied. Alternatively, you may use
the patch snippet provided below:
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
#include
+ #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.
VENDOR RESPONSE
The developers of MySQL have been notified of this
issue, however no fix information was known at the time of this writing. CREDITS Discovered by Robert van der Meulen/Emphyrio and
Willem Pinckaers
|