Zak*_*ria 120 passwords hash client-side
当我想建立一个登录系统时,我总是将给定密码的MD5与服务器端用户表中的值进行比较.
然而,我的一个朋友告诉我,一个"清晰"的密码可能会被网络软件嗅到.
所以我的问题是:在客户端散列密码是个好主意吗?它比在服务器端散列更好吗?
Dir*_*irk 108
基本上,你的朋友是对的.但是,简单地散列在客户端的密码只刚刚超过其提交的纯文本服务器更好.能够收听您的纯文本密码的人当然也能够收听散列密码,并使用这些捕获的哈希来对您的服务器进行身份验证.
对于这个问题,更安全的身份验证协议通常会跳过许多箍,以确保这种重放攻击通常不会起作用,通常是允许客户端选择一堆随机位,这些位随密码一起被散列,并且还明确提交给服务器.
在服务器上:
在客户端:
由于服务器知道自己的随机信息以及客户端的随机位(它将它们作为明文),它可以执行基本相同的转换.该协议确保在此对话中的任何人都可以使用该信息稍后使用所记录的信息进行错误验证(除非使用非常弱的算法......),只要双方每次都生成不同的"噪声位",进行握手.
编辑所有这一切都是容易出错和繁琐而且有点难以做到(阅读:安全).如果有可能,可以考虑使用已经被懂行的人写的认证协议的实现(不像我!以上仅仅是从一本书我前一段时间阅读的记忆.)你真的不想要这个自己平时写.
小智 57
首先,这样做不提高应用程序的安全性(假设它是一个Web应用程序).
使用SSL(或者实际上是TLS,通常称为SSL),它并不是真的很贵(衡量你用来寻找解决方法的时间并用最低工资乘以它,购买证书几乎总能获胜).
为什么这很简单.TLS解决了一个问题(当与购买的证书一起使用,而非自签名时)在密码学方面相当大:我如何知道我正在与之交谈的服务器是我认为我正在与之交谈的服务器?TLS证书是一种说法:"我,您的浏览器信任的证书颁发机构,证明[url]上的网站有这个公钥,带有相应的私钥,只有服务器知道的(私钥),看看我在整个文档上签了我的签名,如果有人改了你就可以看到".
没有TLS,任何加密都变得毫无意义,因为如果我坐在你旁边的咖啡店,我可以让你的笔记本电脑/智能手机认为我是服务器和MiTM(中间人)你.使用TLS,您的笔记本电脑/智能手机会尖叫"UNTRUSTED CONNECTION",因为我没有与您的网站匹配的证书颁发机构签名证书.(加密与身份验证).
免责声明:用户倾向于点击这些警告:"不受信任的连接?什么?我只想要我的小猫照片!添加例外 点击 确认 点击 YAY!小猫!"
但是,如果你真的不想购买证书,仍然要实现客户端javascript哈希(并使用standford库(SJCL),不要实施CRYPTO自己).
为什么?密码重用!我可以在没有HTTPS的情况下窃取您的会话cookie(这允许我假装您的服务器,我是你)(参见firesheep).但是,如果你在登录页面添加一个javascript,在发送之前,哈希你的密码(使用SHA256,甚至更好,使用SHA256,向他们发送你生成的公钥,然后加密密码,你不能使用盐用此),然后将散列/加密的密码发送到服务器.使用salt重写服务器上的哈希并将其与存储在数据库中的哈希进行比较(存储密码如下:
(SHA256(SHA256(password)+salt))
Run Code Online (Sandbox Code Playgroud)
(将盐保存为数据库中的明文)).并发送您的密码,如下所示:
RSA_With_Public_Key(SHA256(password))
Run Code Online (Sandbox Code Playgroud)
并检查您的密码,如下所示:
if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok
Run Code Online (Sandbox Code Playgroud)
因为,如果有人嗅探你的客户,他们将能够作为你的客户端登录(会话劫持),但他们永远不会看到明文密码(除非他们改变你的javascript,但是,星巴克黑客可能不知道如何/有兴趣在这.)所以他们将获得访问您的webapp,但不能访问他们的电子邮件/脸书/等.(您的用户可能会使用相同的密码).(电子邮件地址将是他们的登录名,或者将在他们的webapp上的个人资料/设置中找到).
dim*_*414 23
您可能不必担心这一点 - 正如Dirk所提到的那样,即使您使用恶意用户在网络上散列密码并看到散列被发送,也可以简单地自己发送相同的散列.
它稍微好一些,因为它可以防止恶意用户知道密码是什么,但由于他们仍然可以登录(或可能重建原始密码),这没有那么有用.
通常,如果您担心用户的密码和数据的安全性(并且您应该这样做!),您将需要使用安全的SSL服务器.如果出于某种原因这不是你的问题,你也可以不去烦恼; 这只是通过默默无闻的安全.
编辑2014年8月: Google正在越来越强烈地推动网站在任何地方切换到HTTPS,因为保护通信本身是防止网络嗅探攻击的唯一方法.混淆传输数据的尝试只会阻碍而不是阻止专用攻击者,并且会给开发人员带来危险的虚假安全感.
Kid*_*rla 11
实际上我不同意客户端哈希在这种情况下更安全.我认为它不太安全.
在数据库中存储密码哈希而不是真实密码(甚至是加密密码)的全部意义在于,在数学上不可能从哈希中获取原始密码(尽管理论上可以获得冲突)散列输入,其难度取决于散列算法的安全强度).这里可能的攻击媒介是,如果潜在的攻击者以某种方式破坏了您的密码存储数据库,他/她仍然无法获得您的用户的原始密码.
如果您的身份验证机制发送密码哈希值,那么在此安全漏洞情况下,攻击者无需知道真实密码 - 他们只是发送他们拥有的哈希值,而且他们可以访问特定用户帐户,通过扩展,您的整个系统.这完全打败了存储散列密码的重点!
真正安全的方法是向客户端发送一次性公钥,以便加密密码,然后在服务器端解密并重新哈希.
顺便说一下,这类问题可能会在Security StackExchange上得到更多专家的回应.
请注意,保护密码免受第三方侵害并不是全部。
一旦涉及隐私(现在什么时候不涉及?),您就不想知道密码。你不能滥用或泄露你没有什么有,所以你和你的客户可以睡得更好,如果你从来没有看到他们的明文密码。
因此,散列/加密客户端是有道理的。
最近 GitHub 和 Twitter 都宣布将密码存储在内部日志中。我在 bug 报告和其他日志中无意中发生过这种情况,这些日志进入了 splunk 等。对于 twitter 来说,如果特朗普的密码在日志中,那么管理员“看到”可能会是一件大事,而对于其他网站来说,可能不会如此这是一件大事,因为管理员不会有太多用处。不管怎样,作为管理员,我们不喜欢看到密码。
所以问题是,为了安全起见,哈希是否应该在客户端进行,但是我们如何在密码最终被服务器端哈希和比较之前保护密码,这样它就不会以某种方式被记录。
加密并不是一个坏主意,因为开发人员至少必须跳过一些麻烦,如果您发现密码进入日志,您可以更改加密密钥,销毁原始数据,然后该数据就变得毫无用处。最好每晚轮换一下钥匙,这样可以大大减少窗户的数量。
您还可以对用户记录中的哈希值进行哈希处理。泄露的密码将是经过哈希处理的纯文本密码。服务器将存储散列的散列版本。当然,哈希值会成为密码,但除非您有过目不忘的记忆力,否则您不会记住 60 个字符的 bcyrpt。用用户名加盐。如果您可以在登录过程中收集有关用户的信息(同时不暴露用户记录的存在),您也可以使用它来创建一个无法在站点之间共享的更强大的哈希值。中间没有人能够在站点之间剪切和粘贴捕获的哈希值。
与未提交回服务器的 cookie 结合使用,您可能会发现一些东西。在第一个请求时,使用密钥向客户端提交 cookie,然后确保 cookie 不会返回到登录服务,这样它被记录的机会很小。将密钥存储在会话存储中,然后在登录后或会话过期时立即删除它......这需要 JWT 人员的状态,但也许只需使用 nosql 服务即可。
因此,管理员在 splunk 或错误报告工具中遇到了这些散列和加密的密码之一。这对他们来说应该是没有用的,因为他们再也找不到加密密钥了,即使他们找到了,他们也必须暴力破解哈希值。此外,最终用户没有沿线发送任何明文,因此中间的任何人至少都会遇到困难,并且您不能只是跳到另一个站点并登录。
| 归档时间: |
|
| 查看次数: |
72668 次 |
| 最近记录: |