我正在寻找关于如何最好地控制对主要是脱机使用的HTML5应用程序的访问的建议/批评。
应用程序结合使用IndexedDB、本地和会话存储来存储数据,以便可以脱机使用。数据/页面通过HTTPS提供。
其目的是尽量减少如果平板电脑/个人电脑丢失/被盗时查看数据的风险。
目前,应用程序使用库对用户/密码进行加密,如果用户能够成功地对服务器进行身份验证,则将其保存到本地存储。如果应用程序随后脱机,则用户必须根据本地存储中加密的用户/密码对“本地”进行身份验证。
此外,如果用户能够成功地对服务器进行身份验证,则未加密的用户/密码存储在会话存储中。这样,应用程序就可以定期尝试重新建立与服务器的联系,并在不要求用户重新输入凭据的情况下“表面地”重新进行身份验证。
我知道许多关于客户端加密的错误性的帖子/讨论,请参考http://www.matasano.com/articles/javascript-cryptography/和http://rdist.root.org/2010/11/29/final-post-on-javascript-crypto/以及http://rdist.root.org/2010/11/29/final-post-on-javascript-crypto/+其他。然而,我不确定这些论点在这种情况下如何适用。
考虑到离线存储数据的需要,我正在寻找对这种方法的批评。如果有更好的方法,请详细说明。
谢谢
发布于 2014-04-24 08:05:31
身份验证与安全存储
首先,我将讨论一个重大的设计问题:您似乎是在处理这个问题,就好像它是关于authentication,的问题一样,在那里,(潜在的恶意)用户需要向您的应用程序证明她确实是有效的用户。但实际上,您正面临一个存储问题,因为如果计算机设备被盗,整个运行时环境(包含应用程序正在处理的所有敏感信息)都在攻击者手中。在javascript应用程序的情况下,离线数据和代码的分析甚至比一些二进制代码更舒适。
例如,如果我想攻击您的应用程序,我将首先查看会话存储(cookie?只需使用浏览器界面查找它们),并查看是否可以在那里找到用户名和密码。如果不是,我将遵循用于在本地存储中解密密码的代码(可能使用javascript调试器)。按照您描述应用程序的方式,这些函数似乎可以在不需要用户提供密钥的情况下对其进行解密。也许我可以通过将if(authenticateUser())更改为if(true)来注释用户的本地身份验证。
因此,您真正需要做的是用一个根本不存储在客户端的密钥加密所有敏感的本地数据。例如,每次用户访问您的应用程序时都请求用户提供解密密钥,使用该密钥解密本地存储的数据(并加密存储的每一个新数据),并在某个不活动的之后丢弃密钥。或者,每次用户访问您的应用程序并从那里检索解密密钥时,您都可以针对服务器对其进行身份验证,并在某个时间不活动后将其丢弃。
此时,javascript环境的选择确实会阻碍您的工作,因为您不能强迫运行时环境在您想要解密密钥时丢弃它。对于C应用程序来说,这已经够困难的了,因为您必须小心地将RAM交换到HDD上。取决于应用程序处理的信息是否敏感,可能在用户完成后要求用户关闭浏览器,并假设攻击者没有足够的动机从浏览器的交换RAM中查找密钥就足够了。
本地保存登录数据
因为它是您使用的最敏感的信息,所以您不应该将用户登录信息存储在客户端上。相反,只对服务器进行一次身份验证,并从服务器中检索身份验证令牌,以供以后的交互使用。这将与会话cookie基本相同,并在一段时间后过期(如果它根本不过期,它就和密码一样好)。
发布于 2014-05-29 21:04:46
我现在已经实现了一个解决方案,我将在下面描述,以防它对其他人有用。我理解这不是对我的问题的“回答”,即不提供评论,但考虑到应用程序必须“离线”工作,以及无缝重新认证的要求,我看不出@Perseids答案是如何实现的,尽管我很欣赏对话(来自@SilverlightFox和@Perseids)。
如果有一个解决方案,不存储用户的凭据‘离线’,同时满足我的问题概述的要求,我将热切地听到。
当应用程序“联机”和“脱机”时,应用程序必须能够对用户进行身份验证。对于“联机”应用程序,通常会采用会话令牌解决方案,即只将会话标识符存储在客户端(通常存储在cookie中),而不是用户的凭据。然而,用户的凭据必须存储在客户端上(也许有人会想出一个聪明的替代方案?)这样,可以在应用程序脱机时强制安全性,即允许用户在脱机时进行身份验证,并对IndexedDB数据进行解密/加密。为了使应用程序更加安全,用户的用户名和密码以加密形式存储。一些敏感的IndexedDB数据也以加密形式存储。因此,即使恶意用户获得具有应用程序缓存实例的计算机或平板电脑,他们也只能以加密形式查看用户名、密码和数据(前提是用户已注销或关闭浏览器)。
不幸的是,目前似乎没有任何保护HTML5脱机应用程序的“标准”协议。几乎所有文献都警告不要在客户端存储用户凭据或任何敏感数据。然而,这是一个悖论,因为该应用程序必须在脱机时工作,因此数据必须脱机存储。
这里实现的安全协议有两个密钥,但是一旦第一个密钥被破解,就很容易获得第二个密钥。在第一个级别中,用户的密码是用他们自己的密码作为密钥加密的,同时他们的用户名被反转为salt。还有第二个密钥,‘数据加密密钥’,在成功地对服务器进行身份验证时从服务器返回。此密钥用于加密用户名和任何IndexedDB数据。这个“数据加密密钥”是使用用户的密码进行加密的。因此,如果攻击者能够解密用户的密码,那么他们就可以轻松地使用密码解密‘数据加密密钥’,然后使用解密的‘数据加密密钥’解密用户的用户名和任何加密的IndexedDB数据。只有加密形式的用户名、密码和数据需要永久存储在客户端上,因为通过使用用户的用户名和登录屏幕中输入的密码,就可以解密任何持久化的数据。
但是,登录后,用户名和密码以未加密的形式存储在客户端的会话中,这样应用程序就可以定期与服务器重新认证,如果存在断续连接,就可以无缝地重新认证;2)随时检索解密的数据加密密钥,以便能够查询/保存IndexedDB数据,并在必要时解密/加密。如果不是一个要求,那么只需要在会话中存储数据加密密钥。如果用户尚未注销或未关闭浏览器,则这将导致可维护性,因为恶意用户将能够以解密形式(使用调试工具)查看用户的密码和用户名。然而,这并不比让用户能够更改密码的传统在线应用程序发生的情况更糟糕,尽管传统的在线应用程序通常有会话超时,因此恶意用户只有有限的时间来操作。此外,如果浏览器崩溃,通常会给用户一个选项,用他们的会话信息恢复他们以前的窗口/选项卡,因此浏览器应该被正确关闭。
上面通过的议定书几乎肯定没有遵循最佳做法。例如,salt不是随机的(用户名反转),很可能是短的,容易受到字典攻击,同样也可以适用于密码(密码的强度是服务器的一个功能),没有键拉伸,例如PBKDF2。然而,考虑到所施加的限制,我看不出如何能够遵循“最佳实践”并满足需求。也许可以改进散列,例如改进salt,也许是用户名和站点特定字符串的组合,但是,即使这需要javascript中的逻辑,而确定的攻击者可以理解它。Javascript可以被混淆,但这也只会使它变得更困难,而不是不可能,任何能够破解加密密钥的人都不会发现Javascript的混淆很大程度上是一个障碍。也许,有了一些未来聪明的内在支持,浏览器就有可能有重大的改进。
https://stackoverflow.com/questions/23256389
复制相似问题