当我要放置一个登录系统时,我总是将给定密码的MD5与服务器端的users表中的值进行比较。
但是,我的一个朋友告诉我,网络软件可能会嗅到“清除”密码。
所以我的问题是:在客户端哈希密码是否是一个好主意?它比在服务器端对其进行哈希处理更好吗?
当我要放置一个登录系统时,我总是将给定密码的MD5与服务器端的users表中的值进行比较。
但是,我的一个朋友告诉我,网络软件可能会嗅到“清除”密码。
所以我的问题是:在客户端哈希密码是否是一个好主意?它比在服务器端对其进行哈希处理更好吗?
Answers:
基本上,您的朋友是对的。但是,简单地散列在客户端的密码只刚刚超过其提交的纯文本服务器更好。可以侦听您的纯文本密码的人当然也可以侦听哈希密码,并使用自己捕获的这些哈希值对您的服务器进行身份验证。
为此,通常通过允许客户端选择一堆随机位(随密码一起散列),以确保更可靠的身份验证协议通常无法跳过,从而确保这种重播攻击不起作用。 ,并且还明确地提交给服务器。
在服务器上:
在客户端上:
由于服务器知道自己的随机信息以及客户端的随机位(以明文形式获取它们),因此它可以执行基本相同的转换。该协议可确保,只要双方双方每次均产生不同的“噪声位”,那么在此对话中收听的任何人都无法稍后使用该信息来对记录的信息进行错误的身份验证(除非使用了非常弱的算法...),握手。
编辑所有这些都是容易出错和乏味的,并且很难正确处理(阅读:安全)。如果可能,请考虑使用已经由博学多才的人编写的身份验证协议实现(与我不同!上面的内容仅是我一段时间前读过的一本书的记忆。)您真的不想通常自己写这个。
首先,这样做不提高应用程序的安全性(假设它是一个Web应用程序)。
使用SSL(或实际上称为TLS,通常称为SSL),它并不昂贵(测量找到它的方法并用最低工资乘以它的时间,购买证书几乎总是会赢)。
为什么这样做很简单。TLS解决了一个在密码学上相当大的问题(当与购买的证书一起使用时,而不是自签名):我怎么知道我正在与之交谈的服务器就是我认为与之交谈的服务器?TLS证书是一种表达方式:“我,您的浏览器信任的证书颁发机构,证明[url]上的网站具有此公钥以及相应的私钥,只有服务器知道该私钥,我在整个文档上签名,如果有人对其进行了更改,您可以看到”。
没有TLS,任何加密都变得毫无意义,因为如果我在咖啡店里坐在你旁边,我可以让你的笔记本电脑/智能手机认为我是服务器,而MiTM(中间人)就是你。使用TLS,您的笔记本电脑/智能手机会发出“ UNTRUSTED CONNECTION”的消息,因为我没有与您的站点匹配的证书颁发机构签名的证书。(加密与身份验证)。
免责声明:用户倾向于通过以下警告右击:“不可信的连接?是什么?我只想要我的小猫的照片!添加例外 单击“ 确认”, 单击 “ 确定!小猫!”。
但是,如果您真的不想购买证书,请仍然执行客户端javascript哈希(并使用standford库(SJCL),永远不要实现自己的加密)。
为什么?密码重用!我可以轻松地窃取您的会话cookie(这使我可以假装成您的服务器)而无需HTTPS(请参阅firesheep)。但是,如果您在登录页面上添加了JavaScript,然后在发送前对密码进行哈希处理(使用SHA256,或者甚至更好的方法是使用SHA256,将生成的公钥发送给他们,然后使用该密码加密哈希值,则不能使用salt ),然后将哈希/加密的密码发送到服务器。用盐重新哈希服务器上的哈希,并将其与数据库中存储的哈希进行比较(存储密码,如下所示:
(SHA256(SHA256(password)+salt))
(也将盐在数据库中另存为纯文本)。然后像这样发送您的密码:
RSA_With_Public_Key(SHA256(password))
然后像这样检查您的密码:
if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok
因为,如果有人在监听您的客户端,他们将能够以您的客户端身份登录(会话劫持),但他们永远不会看到纯文本密码(除非他们更改了您的JavaScript,但是,星巴克黑客可能不会知道如何做/感兴趣)这样,他们就可以访问您的Web应用,但不能访问他们的email / facebook / etc。(您的用户可能会使用相同的密码)。(电子邮件地址可以是他们的登录名,也可以在您的Web应用程序的个人资料/设置中找到)。
您可能不必担心这一点-正如Dirk所述,即使您对密码进行哈希处理,恶意用户也可能会在网络上看到哈希发送,并且可以自己发送相同的哈希。
这是略好,因为它可以防止恶意用户知道密码是什么,但因为他们仍然可以登录(或潜在重构原始密码),这是不是有帮助。
通常,如果您担心用户密码和数据的安全性(应该注意!),则需要使用安全的SSL服务器。如果无论出于何种原因您都不必担心,则最好不要去理会哈希。只是默默无闻的安全感。
2014年8月修改: Google越来越强烈地要求网站在任何地方都切换到HTTPS,因为保护通信本身是防止网络嗅探攻击的唯一方法。试图混淆传输的数据只会阻碍而不是阻止专门的攻击者,并且可能给开发人员带来危险的错误安全感。
x
用户密码和访问单个服务,那么您的观点就是客户端哈希只会“稍微好一点” 。如果考虑集体效应,我会说这是“好得多”。因为它阻止建立用于在多个服务之间强行加盐哈希的密码的大型查询数据库。海事组织。请参阅AWS Cognito在客户端中执行的操作以供参考。
实际上,我不同意客户端哈希在这种情况下更安全。我认为它不太安全。
与真实密码(甚至是加密密码)相比,在数据库中存储密码散列的全部目的是,从数学上讲不可能从散列中获得原始密码(尽管从理论上讲,有可能获得冲突)哈希输入,其难度取决于哈希算法的安全强度)。这里可能的攻击媒介是,如果潜在的攻击者以某种方式破坏了您的密码存储数据库,他/她仍然将无法获得用户的原始密码。
如果您的身份验证机制发送了密码的哈希值,那么在这种安全漏洞情况下,攻击者无需知道真实的密码-他们只需发送自己拥有的哈希值即可,并且可以访问特定用户的帐户,进而扩展您的整个系统。这完全解决了首先存储哈希密码的问题!
这样做的真正安全方法是向客户端发送一次性的公钥,以便客户端对密码进行加密,然后在服务器端将其解密并重新哈希。
顺便说一句,这种问题可能会在Security StackExchange上获得更多专家的回应。
请注意,保护密码不受第三方侵害并不是全部。
一旦涉及到隐私(这些天是什么时候(不是)?),您不想知道密码。你不能滥用或泄露你没有什么有,所以你和你的客户可以睡得更好,如果你从来没有看到他们的明文密码。
因此,对客户端进行哈希/加密是有意义的。
x
用户密钥n
。如果每个服务在离开客户端之前都唯一地对密码进行哈希处理,那么跨服务密码的大型数据库将变得小得多。检查您的AWS登录流量,查看其作用。我亲爱的沃森,很有可能。
我最近在这方面做了很多工作,IRL客户端散列/ 对称加密有两个问题,但确实扼杀了这个想法:1.您必须将盐返还给服务器SOMEHOW ...并进行加密在客户端,您将需要密码...这会达到目的。2.您公开了散列实现(这不是一个巨大的交易,因为大多数站点使用3或4个散列算法之一),这使攻击更容易(因为只需要尝试一个而不是n)即可。
我最终要去做的是使用OpenPGP.js或类似的方法在客户端上进行非对称加密...这依赖于客户端上导入的或客户端生成的密钥以及发送它的公共密钥的服务器。只能将客户端的公钥发送回服务器。这可以防止MIM攻击,并且与设备一样安全(我目前默认将客户端的私钥存储在localStore中,这是一个演示)。
这样做的主要优点是,我不必再将用户数据存储在服务器/数据存储中,甚至不必在服务器/数据存储中未加密的内存中存储(并且服务器的私钥在物理上是分开的)
这样做的基础是为人们提供一种在HTTPS受到限制的地方(例如伊朗/北朝鲜)等进行安全通信的方法,并且这只是一个有趣的实验。
我是最早想到这个的FAR,http://www.mailvelope.com/使用它
如果有人可以看到您连接上的数据,那么身份验证将无法保存您。相反,我将针对超级机密内容执行以下操作。
密码在发送到服务器之前会先在客户端进行伪装。(服务器存储从浏览器发送的该哈希值的另一个哈希值和加盐值)。
因此,中间人攻击可能允许他们发送与他们相同的哈希值来登录,但是用户密码未知。这将阻止他们尝试使用具有相同凭据的其他服务登录其他地方。
用户数据也在浏览器端被加密。
嗯,所以中间人攻击将获得加密的数据,但是如果没有用于登录的实际密码,就无法解密该数据。(用户登录时存储在浏览器中DOM中的用户密码)。因此,真实用户将看到解密的内容,而中间人则看不到。这也意味着任何国家安全局或其他机构将无法请求您/公司/托管提供商解密此数据,因为它们也将无法解密。
我的博客http://glynrob.com/javascript/client-side-hashing-and-encryption/中有这两种方法的一些小示例。
最近,GitHub和Twitter都宣布将密码存储在内部日志中。我已经在错误报告和其他日志中无意间发生了这种情况,这些日志已经进入splunk等。对于Twitter,如果特朗普的密码在该日志中,对于管理员来说“看”可能是一件大事,而对于其他网站则可能不是这很重要,因为管理员不会有太多用处。不管是管理员,我们都不希望看到密码。
因此,问题实际上是,散列是否应该在客户端进行以确保安全性,但是我们如何才能在密码最终被散列并由服务器端进行比较之前保护密码,以免以某种方式记录该密码。
加密不是一个坏主意,因为开发人员至少必须跳过一些麻烦,而且如果您发现密码进入了日志,则只需更改加密密钥,销毁原始密钥,数据就变得无用。最好还是每晚旋转一次按键,这样可以大大减少窗户。
您还可以在用户记录中对哈希值进行哈希处理。泄漏的密码将是哈希纯文本密码。服务器将存储哈希的哈希版本。当然,哈希值已成为密码,但是除非您有照片存储空间,否则您将不会记住60字符的bcyrpt。盐与用户名。如果您可以在登录过程中收集有关用户的一些信息(而不会暴露用户记录的存在),则可以添加一些内容,同时创建一个更健壮的哈希,无法在站点之间共享。中间没有人能够在站点之间剪切和粘贴捕获的哈希。
与无法提交回服务器的cookie结合使用,您可能会遇到麻烦。第一次请求时,请使用密钥将cookie提交给客户端,然后确保cookie不会返回登录服务,以免被记录。将密钥存储在会话存储区中,然后在登录发生或会话过期时立即将其删除...这需要JWT家伙使用状态,但可能仅使用nosql服务。
因此,管理员在splunk或错误报告工具中遇到了这些哈希密码和加密密码之一。对于他们来说,这应该是没有用的,因为他们再也找不到加密密钥了,即使他们找到了加密密钥,也必须蛮力地哈希。另外,最终用户没有沿线发送任何明文,因此中间的任何人至少都很难过,并且您不能只是跳到另一个站点并登录。