mysql 能否一句 sql 验证加盐的密码?

2015-05-27 09:40:35 +08:00
 jookr

mysql能否一句sql验证加盐的密码?

table
uid username password salt
1 admin ce7ba70a8a7bdf9b6cc10beeff2b3e03 qwe123

正常流程需要三步
表单提交的用户名$username和 密码$psw

步骤1先查出盐$salt
select salt from table where username = '$username'
步骤2然后加密
$password = md5($psw.$salt);
步骤3最后再查是否有符合条件的数据
select * from table where username='' and password='$password'
有结果就说明密码正确
没结果就说明密码错误或者没这个用户名的账号

请问以上三步能否用mysql的子查询或者什么高级方法一句话就能验证结果呢?

谢谢

8302 次点击
所在节点    MySQL
78 条回复
loading
2015-05-27 14:21:52 +08:00
@BuilderQiu 嗯,感谢提醒!
loading
2015-05-27 14:25:26 +08:00
@BuilderQiu 方便告知用那个密码所在地吗?
我去清理掉,那个密码好久没用了。
enjoyforfun囧gmail.com
loading
2015-05-27 14:30:27 +08:00
@BuilderQiu 取到数据库的盐,和知道我统一的盐,对于暴力破解似乎没什么不同!
那每个用户对一个盐有什么好处呢?
难道就是防止被脱裤时被大家知道来源?

个人认为,用可逆算法存密码和明文一样令人讨厌!
下次简单密码还是加域名区分吧,不然都不知道哪个站掉的。
akstrom
2015-05-27 14:36:20 +08:00
06年做的用户密码体系,md5("用户名"+"_"+"用户密码"+"_"+"系统码"),用户名唯一,系统码一套系统一个随机的N位字符,有想的那么复杂吗?
dallaslu
2015-05-27 14:36:39 +08:00
@stiekel 关于 md5 这段,我突然想到:

如果「浏览器端对密码进行md5」被普遍采用,一旦 md5 值被截取,那将势必「影响到用户在其它场合中的密码安全」。因为密码作为明文输入 md5 函数做参,得到的摘要是一样的。所以,要想各种场合密码互不影响,则要保证:

每一个应用,各自采用不同的 md5 加密次数,你两遍我三遍,猪八戒三十六遍、孙悟空七十二便,以保证网络中传输的 md5 值不被用做其他场合上。

所以,与其这样,不如也在客户端「加盐」,只一遍 md5 就不会影响到其他场合了。再进一步,如果每次会话都由服务器生成一个随机数,作为「胡椒」加到明文后面做出哈西摘要拿去验证,那么,「别人拿到这个md5」也因为再次请求时随机数不同,而不能「直接在应用中登陆」了,岂不更妙。具体实现上,可以参考 hmac。
wy315700
2015-05-27 14:37:25 +08:00
@loading 统一的盐,两个用户密码一样的时候,hash也会一样,暴力破解只需要一套就行了,保留破解结果,可以直接查表了

不同的盐,要对每个用户进行暴力破解
loading
2015-05-27 14:40:40 +08:00
@wy315700 哦,对! 如果一样,那么弱密码的概率就很高了,我没想过这个问题。
我一般会把用户名也一起算,有空再好好看看各位的方法。
wy315700
2015-05-27 14:41:04 +08:00
@dallaslu 你这样如何检验密码正确性,每次提交的MD5都不一样。
dallaslu
2015-05-27 14:51:48 +08:00
@wy315700 hmac 里服务端生成的随机数,才是其关键吧!这样不用传输敏感的密码原文,即可完成对密码的验证。

如果只是因为盐与密码原文拼接后有碰撞,而采用 hmac,我觉得大可不必,因为:

1. 盐由服务器管理,每用户唯一,对于单个用户来说,因为盐是固定的(如 ef),所以不存在相似密码与盐拼接后碰撞的问题(abc 永远不会通过验证,盐不可变更);

2. 盐在生成时,可以技术手段保证位数相同,不给掌握密码前半部分的攻击者以瞎蒙之机;

3. 在用盐计算哈希值时,可以用明文与盐的哈希值拼接,然后再取哈希值。
quix
2015-05-27 14:58:38 +08:00
@stiekel 就是为了防止监听..才有了 SSL / TLS ,这是真正能确安全的方案, 而且无需你写一行代码... md5这种方法属于耍小聪明... 只能在一定程度上保护一点点信息而已.
dallaslu
2015-05-27 15:00:14 +08:00
引用 @wy315700
「你这样如何检验密码正确性,每次提交的MD5都不一样。」

服务器也用这个随机数,和之前存储的用户密钥放在一起,用相同的算法计算结果,与客户端相同,则认为其是授权用户。所以,在上面我也说这要求客户端也实现加密算法,从而不适用传统 Web 应用。
https://en.wikipedia.org/wiki/Hash-based_message_authentication_code
jsq2627
2015-05-27 15:02:53 +08:00
@wy315700
@zhicheng

用 HMAC 代替手写 hash+salt 算法并没有什么明显的安全优势。
用 PBKDF2 代替手写 hash+salt 算法是安全的。

这里举例说明:
假定攻击者已经取得了完整的数据库权限,但是没法看到代码实现。
攻击者想要获取用户 foo 的明文密码,下面分别讨论针对几种种密码存储方式攻击方式:

1. 密码明文存储
直接从数据库读出来,最不安全,大家都知道。

2. 不加盐 hash
攻击者知道 hash。但是不知道用什么哈希算法生成的 hash,可能是 md5(password),可能是 md5(sha1(password))。攻击者可以利用已知的彩虹表查出 hash 可能对应的明文,分别去尝试登录。如果不是复杂的哈希算法,都有对应的现成彩虹表可查。

3. HMAC
攻击者知道 hash 和 salt。接下来和 2 是类似的,只不过哈希算法在 2 的基础上套了一层 HMAC,变成了这样 hash = HMAC(originalHash, salt)。因为 salt 是随机的,需要自己针对这个 salt 生成彩虹表,没法利用现成的彩虹表。

4. 加盐 hash
攻击者知道 hash 和 salt。和 3 类似,区别就是,在 3 里 hash = HMAC(originalHash, salt),在这里 hash = myFunc(originalHash, salt),攻击者需要想办法知道 myFunc 是什么,这个在不看代码的情况下是很难推出的。

5. PBKDF2
攻击者知道 hash 和 salt。同上,这次换成 hash = PBKDF2(password, salt)。注意 PBKDF2 算法的第一个参数直接就是 password,不需要先计算 originalHash。与 3 相比,攻击者无需推算 originalHash 是怎么得出的,可以直接计算针对此 salt 的彩虹表。但关键的地方来了,PBKDF2 是一个非常慢的算法,这个算法内部会进行多次 HMAC 的迭代,如果指定的迭代次数足够大,通常计算一次哈希值需要 500ms 以上,这时计算足够大的彩虹表是非常困难的。

对上面各种方式的安全性从低到高来个排序,大概是这样:
1<2<3=4<5

3 的难点在于 HMAC 算法通常也不是很快,计算彩虹表成本较高,但是只要有足够时间和设备还是可以计算出来的。4 的难点在于没法知道 myFunc 是什么,攻击具有不确定性,但通常低水平开发者写出的 myFunc 很简单,比如 md5($originalHash . $salt) 这样,这是非常容易猜出来的。所以上面给 3 和 4 画了个等号,两种方式可比性不强,安全性相当。

PBKDF2 算法是可以指定迭代次数的,只要有需要,完全可以把每个哈希值的计算时间调到 10s 以上,大大增加了彩虹表的计算难度。
quix
2015-05-27 15:02:57 +08:00
@stiekel 对于未加密的 http连接, 真的要截数据包, 完全可以截你的 session id, 这样你整个安全验证系统都形同虚设, 你在客户端怎么md5都没用...
wy315700
2015-05-27 15:03:36 +08:00
@dallaslu 你这么做有个问题诶,密码必须明文存,PPTP就是这么做的
jsq2627
2015-05-27 15:07:22 +08:00
此外 HMAC 原本的设计就不是用于密码保存的,它是用于带身份验证的完整性校验的。HMAC 的输入应该是 hash 和 key,而不是 hash 和 salt。key 和 salt 的区别是 key 应该是保密的,由传送接受双方预共享,私下保存。salt 是存在数据库的,对攻击者是公开的。


https://news.ycombinator.com/item?id=1998198
这里有一个很好的解释
dallaslu
2015-05-27 15:10:58 +08:00
@wy315700 昂……是的啊。所以说,在安全策略不允许明文存储密码的前提下,客户端要实现对应的加密算法才行呢。
BuilderQiu
2015-05-27 15:11:22 +08:00
@loading

没注意具体出处。重要处不用这个密码即可。
dallaslu
2015-05-27 15:17:32 +08:00
@jsq2627 那这样是正确的用法吗:HMAC(myFunc(originalHash, salt), randomString)
jsq2627
2015-05-27 15:18:41 +08:00
client / server 之间的通信安全,TLS / HTTPS 算是实现起来成本最低,最安全的一种方式。
为了节省一张 SSL 证书的钱,各位也真拼。。。
gamexg
2015-05-27 15:22:27 +08:00
好奇怪的思路,为什么要查询2次?
直接把用户的密码和盐都取出来程序比较就可以了啊...

数据库密码部分建议增加一个密码加密版本,类似与这样保存“密码加密版本$盐$加密后的密码”。

当前使用的加密算法出现缺陷时可以随时部署新的版本的加密算法。在用户登录时发现是旧版本的加密算法,直接使用用户登录提供的密码用新的算法加密保存到数据库即可无痛升级。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/194013

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX