欢迎投稿

今日深度:

MySQL安全攻防实战指南之体系结构篇(1)(6)

身份验证协议4.1版本之前的基本密码弱点

4.1版本之前的MySQL,无需知道密码,只要知道密码的hash值包含在mysql.user表中)就能通过身份验证——这意味着,攻击者根本无需编写密码杂凑值的破解程序,因为修改标准MySQL客户端让它接受密码杂凑而非密码要容易多了。当然,用户倾向于多处使用同一个密码,尤其是root密码,所以破解任何一个密码的杂凑值,就极有可能在多个地方派上用场。

3.23.11版本之前的身份验证算法

3.23.11版本之前的MySQL的身份验证机制中有一个严重的缺陷,即攻击者仅仅使用杂凑后的密码的单个字符就能通过身份验证。其实杂凑后的字符串由32个字符中的某些字符构成的,所以攻击者只需进行少量猜测就能登录。

3.23.54版本之前的CHANGE_USER

对于3.23.54版本之前的MySQL来说,如果用户可以进行身份验证,它就有机会提交一个超长字符串(来触发缓冲区溢出)或者单字节字符串的CHANGE_USER命令来提权。

4.1.1、4.1.2和5.0.0版本中的身份验证算法

通过提交一个精心制作的身份验证数据分组,对于攻击者而言,就有可能绕过在4.1.0到4.1.2以及5.0早期构建版的MySQL中的密码身份验证机制。下面的代码取自sql_parse.cpp文件的check_connection代码:

/*

旧版本的客户端发送以null结束的字符串作为密码;新客户端使用尺寸(1字节)+字符串(并非以null作为终止符)作为密码。 因此如果是空密码的话,两者都会发送'\0'。

*/

uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
*passwd++ : strlen(passwd);

0x8000是在客户端的能力标志中规定的,用户可以指定所选的passwd_len字段。对于该攻击,我们选择0x14 (20),这是我们预期的SHA1杂凑长度。

现在要执行多道检测以保证用户是从授权连接的主机上进行身份验证。通过这些检测后,我们到达:

/* 检查密码:它应该为空或者是正确的 */
if (passwd_len == acl_user_tmp->salt_len)
{
if (acl_user_tmp->salt_len == 0 ||
acl_user_tmp->salt_len == SCRAMBLE_LENGTH &&
check_scramble(passwd, thd->scramble, acl_user_tmp->salt) == 0 ||
check_scramble_323(passwd, thd->scramble,
(ulong *) acl_user_tmp->salt) == 0)
{
acl_user= acl_user_tmp;
res= 0;
}
}

Check_scramble函数失败,但是在check_scramble_323函数之内我们看到:

my_bool
check_scramble_323(const char *scrambled, const char *message,
ulong *hash_pass)
{
struct rand_struct rand_st;
ulong hash_message[2];
char buff[16],*to,extra;
const char *pos;

hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
hash_pass[1] ^ hash_message[1]);
to=buff;
for (pos=scrambled ; *pos ; pos++)
*to++=(char) (floor(my_rnd(&rand_st)*31)+64);
extra=(char) (floor(my_rnd(&rand_st)*31));
to=buff;
while (*scrambled)
{
if (*scrambled++ != (char) (*to++ ^ extra))
return 1;                                 /* 密码错误 */
}
return 0;
}

现在,用户已经规定了一个他想要的杂凑字符串,本例为一个零长度的字符串。最后的循环对杂凑字符串与MySQL已知正确响应字符串进行逐字符比较,直到杂凑字符串中的所有字符都比较完为止。由于在杂凑字符串中根本没有要比对的字符,所以函数会立即返回0,即允许用户使用零长度字符串通过身份验证。

这个缺陷的利用方法相当简单,但是我们还是必须要编写一个定制的MySQL客户端才行。除了使用零长度字符串绕过身份验证外,还可以使用长杂凑字符串来溢出基于堆栈的缓冲区。我们可以使用伪随机数发生器my_rnd)函数输出的字符来溢出该缓冲区。字符的范围介于0x40到0x5f之间。对于一些平台来说,执行任意代码是可能的,但是该漏洞利用非常复杂,并且需要进行暴力破解,或者知道一个密码杂凑值。

为了进行这些攻击,攻击者必须知道或者能猜出用户的名称,所以重命名MySQL的root帐户不失为一个有效的预防措施。此外,有关账户还必须能够从攻击者的主机进行访问,所以应用基于IP地址的登录限制也能减轻这些漏洞所带来的危害。


www.htsjk.Com true http://www.htsjk.com/shujukuaq/16813.html NewsArticle 身份验证协议4.1版本之前的基本密码弱点 4.1版本之前的MySQL,无需知道密码,只要知道密码的hash值包含在mysql.user表中)就能通过身份验证——这意味着,...
评论暂时关闭