我们专注服务于当下互联网基础设施建设与云计算、大数据时代的各种需求!

mysql 5.1.61以下版本身份认证bug修复

mysql 5.1.61以下版本身份认证可能存在密码不正确而通过认证。问题出现在/opt/src/Percona-Server-5.1.58/sql/password.c里面的memcmp函数返回结果。红色部分我已经标注,修复方法加上test进行测试返回即可。
my_bool
check_scramble(const char *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
SHA1_CONTEXT sha1_context;
uint8 buf[SHA1_HASH_SIZE];
uint8 hash_stage2_reassured[SHA1_HASH_SIZE];

mysql_sha1_reset(&sha1_context);
/* create key to encrypt scramble */
mysql_sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH);
mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
mysql_sha1_result(&sha1_context, buf);
/* encrypt scramble */
my_crypt((char *) buf, buf, (const uchar *) scramble_arg, SCRAMBLE_LENGTH);
/* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
mysql_sha1_reset(&sha1_context);
mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
mysql_sha1_result(&sha1_context, hash_stage2_reassured);

  return test(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE));
/*  return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);*/
}

修改了源码,然后直接cd /opt/src/Percona-Server-5.1.58 && make && make install即可

会直接替换mysqld文件。找个时间重启下mysql服务器即完成bug修复。
bug描述:http://bugs.mysql.com/bug.php?id=64884

注:

memcmp的返回值实际上是int,而my_bool实际上是char。那么在把int转换成char的时候,就有可能发生截断。比如,memcmp返回0×200,截断后变成了0,调用check_scramble函数的就误以为“password is correct“。

但是一般来说,memcmp的返回值都在[127,-128]之内。glibc的经SSE优化后的代码,不是如此。所以这个BUG只在特定的编译环境下才会触发:即编译MySQL的时候加了-fno-builtin,并且所使用的glibc是经SSE优化后的(一般系统自带的都是如此)。这里所说的glibc是指Linux的glibc,FreeBSD的libc不受影响

shell测试漏洞是否存在:

for i in `seq 1 1000`; do mysql -uroot -paaaa -h localhost 2>/dev/null; done


 用这个试试,能进去就说明中招了~~

C语言测试:
vim sk.c


#include <stdio.h>

 #include <stdlib.h>


 int main(void) {

         int one, two, ret;

         time_t start = time(0);

         time_t now;


         srand(getpid()*start);

         while (1) {

                 one = rand();

                 two = rand();

                 ret = memcmp(&one, &two, sizeof(int));

                 if (ret < -128 || ret > 127)

                         break;

                 time(&now);

                 if (now - start > 10) {

                         printf("Not triggered in 10 seconds, *probably* not vulnerable..\n");

                         return 1;

                 }

         }

         printf("Vulnerable! memcmp returned: %d\n", ret);

         return 0;

 }

gcc sk.c -o sk
运行看看!