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 运行看看!