为什么 MySQL (5.x) 中的密码没有加盐?

nev*_*gqs 6 mysql

我正在使用连接到 MySQL 数据库 (5.x) 的旧应用程序。当我使用相同的密码为 MySQL 数据库创建两个不同的用户时,这些密码的哈希值是相同的。

是否有选项可以在 mysql.user 中启用密码加盐?

Mic*_*bot 8

不,没有。

如果这对您来说是一个主要问题,那么Percona有一个PAM 插件可用于 MySQL,如果您想针对外部事物而不是使用内部机制进行身份验证。MariaDB 有一个不同的解决方案

Oracle 也有一个专有的(非免费的)PAM 插件,供那些只想给钱的人使用。

虽然,除非您有某种合规性问题需要处理,否则 MySQL 身份验证协议的实用性使得这似乎不是问题。毕竟,您的数据库服务器通常不应在 Internet 上访问,如果可以,则应将其限制为可以连接的主机,并且应要求这些主机使用 SSL。

服务器本质上存储此表达式的输出:

CONCAT('*',UCASE(SHA1(UNHEX(SHA1('password')))));

mysql> select PASSWORD('password');
+-------------------------------------------+
| PASSWORD('password')                      |
+-------------------------------------------+
| *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
+-------------------------------------------+
1 row in set (0.00 sec)

mysql> select CONCAT('*',UCASE(SHA1(UNHEX(SHA1('password')))));
+--------------------------------------------------+
| CONCAT('*',UCASE(SHA1(UNHEX(SHA1('password'))))) |
+--------------------------------------------------+
| *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19        |
+--------------------------------------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

但这显然不仅仅是“如果散列一次很好,那么散列两次更好”的误导性尝试。它与身份验证协议的工作方式有关。

当客户端尝试进行身份验证时,服务器会发送一个 20 字节的随机质询字符串。

客户端获取该字符串,并计算

SHA1('password') XOR SHA1( "20-bytes random data from server"<concat>SHA1(SHA1('password')))
Run Code Online (Sandbox Code Playgroud)

所以客户端正在计算应该存储在密码列中的值(如果输入了正确的密码),将该值附加到 20 个随机字节,取整个事物的 SHA1,与密码的 SHA1 异或本身,并将其发送回服务器。

鉴于 XOR 的反函数也是 XOR,然后服务器可以接受响应,并且还计算了包括 20 个字节的字符串的 SHA1(),可以将其 XOR 回 SHA1('password'),然后 SHA1 () 那个值...

SHA1(client-response XOR SHA1(CONCAT("same random 20-bytes",mysql.user.password)))
Run Code Online (Sandbox Code Playgroud)

...输出将是存储在 mysql.user 表的密码列中的值。

所以在这个交换中,明文密码和密码字段中存储的内容都不会通过网络发送,只是一个 20 字节的随机挑战和一个 20 字节的响应,它本身就是两个散列值的异或,也不会可用于针对同一帐户或具有相同密码的另一个帐户的重放攻击,除非服务器发送相同的质询并且密码相同。

由于具有相同密码的两个客户端可以说“永远不会”收到相同的质询,因此它们很少会“永远”发送相同的响应以进行身份​​验证。

除非服务器将盐发送给客户端,否则我不容易看到这种交换是如何发生的。另一方面,如果服务器要将盐发送给客户端,则意味着盐必须存在于服务器上……如果盐存在于服务器上,并且我拥有一个已知密码/salt 组合,然后识别盐和我的密码与其密码哈希匹配的其他帐户,然后识别可以使用我的密码的其他帐户与当前方案下的情况一样微不足道。