0x00 引言 MySQL数据库的身份验证方式经过逐步改进,从其发展历程可以看出安全性逐渐增强。在MySQL-4.1之前的版本存在易受到暴力破解(CVE-2000-0981)的安全风险。著名的内网嗅探工具cain具备破解MySQL数据库哈希值的功能,可以猜解出明文密码。在MySQL-4.1之后,猜解哈希变得更加困难,但只要投入足够的精力,仍然有可能成功,cain和hashcat等工具都提供了相应支持。在MySQL-5.1之后的版本中,曾经存在一个身份验证漏洞(CVE-2012-2122),只需用户名即可利用该漏洞登录数据库。
0x01 身份验证交互过程 MySQL 3.20 – 4.0 版本的身份验证过程:
服务器向客户端发送一个8字节长度的随机字符串(scramble),即盐;客户端通过将盐与密码的哈希值进行异或(XOR)运算,得到一个32位哈希值,并将其作为种子生成一个8字节字符串发送给服务器;服务器使用存储在mysql.user表中的密码,重复上述计算过程,并将其与客户端发送的8字节字符串进行比较,得出结果。
MySQL 4.1 – 5.7 版本的身份验证过程:
1 [0a] protocol version #协议
string[NUL] server version
4 connection id #wireshark中的Thread ID
string[8] auth-plugin-data-part-1 # salt的前8字节
1 [00] filler
2 capability flags (lower 2 bytes)
if more data in the packet:
1 character set
2 status flags
2 capability flags (upper 2 bytes)
if capabilities & CLIENT_PLUGIN_AUTH {
1 length of auth-plugin-data
} else {
1 [00]
}
string[10] reserved (all [00]) #字符串一般以[00]结束
if capabilities & CLIENT_SECURE_CONNECTION {
string[$len] auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8)) #salt剩余12字节
if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL] auth-plugin name
}
服务器向客户端发送一个盐(salt);客户端使用该盐对密码进行加密,并将加密后的密码与用户名一起发送给服务器;服务器使用mysql.user表中的哈希值与客户端发送的密码哈希进行比较,如果相同则认证成功。需要注意的是,上述过程适用于MySQL 4.1及以后的版本。
MySQL 5.7以上版本的身份验证过程:
借用一张MySQL-8.04的图,从MySQL 5.7开始,密码加密开始使用SHA256(password)。服务器向客户端发送一个20字节的盐;客户端读取服务器的公钥,该公钥事先导入给客户端;客户端计算密码与盐的哈希值,并通过服务器的公钥进行加密,然后发送给服务器;服务器使用RSA私钥进行解密,并通过盐和密码的哈希值进行比较认证。由于引入了非对称加密方式的安全机制,嗅探MySQL流量中的哈希值并进行碰撞的攻击方法变得更加困难。作为攻击者,必须获得服务器的公钥才能进行交互。
参考文献:参考文献