是否可以将本地存储视为安全的?[关闭]


160

我需要开发一个可长期离线运行的Web应用程序。为了使它可行,我无法避免将敏感数据(个人数据,而不是您将仅存储散列数据的类型)保存在本地存储中。

我接受不推荐这样做,但是我几乎没有选择要执行以下操作来保护数据:

  • 使用斯坦福javascript密码库和AES-256将所有内容都加密到本地存储中
  • 用户密码是加密密钥,未存储在设备上
  • 通过ssl从单个受信任的服务器提供所有内容(在线时)
  • 使用owasp antisamy项目验证往返服务器本地存储的所有数据
  • 在应用程序缓存的网络部分中,不使用*,而是仅列出与受信任服务器连接所需的URI
  • 通常尝试应用OWASP XSS速查表中建议的准则

我很欣赏魔鬼在细节上的细节,并且知道人们对本地存储和基于JavaScript的安全性普遍持怀疑态度。任何人都可以评论是否存在:

  • 上述方法的根本缺陷?
  • 有什么可能的解决方案来解决此类缺陷?
  • html 5应用程序必须长时间离线运行时,还有什么更好的方法来保护本地存储?

谢谢你的帮助。


“我接受不推荐这样做” -是吗?是不是为此专门创建了它呢?
hakre 2013年

2
为了澄清,我的意思是不建议您将敏感数据存储在本地存储中。
user1173706 2013年

这样,您不应该在大型网络上传递敏感数据吗?
hakre 2013年

@ user1173706为什么应用程序必须功能必须离线运行较长时间?用户是什么样的?您必须支持哪些浏览器?我认为这是可能的,但我需要了解有关您的方案的细节。
本杰明·格伦鲍姆

@Benjamin我已经更新了问题。谢谢。
user1173706 2013年

Answers:


74

Web加密

客户端(浏览器)javascript中的加密问题将在下面详细介绍。除了这些关注点之外,所有关注点均不适用于WebCrypto API,该API现在得到了很好的支持

对于脱机应用程序,您仍然必须设计和实现安全的密钥库。

另外:如果您使用的是Node.js,请使用内置的加密 API。

本机Java密码术(WebCrypto之前的版本)

我认为主要的关注点是可以物理访问计算机的人员,该计算机正在读取localStorage您网站的,而您希望通过加密来防止这种访问。

如果某人具有物理访问权限,那么您也很容易遭受其他攻击,这比读书更糟。这些包括(但不限于):键盘记录程序,脱机脚本修改,本地脚本注入,浏览器缓存中毒和DNS重定向。仅当用户在计算机受到威胁后使用计算机时,这些攻击才起作用。但是,在这种情况下进行物理访问意味着您会遇到更大的问题。

因此请记住,如果机器被盗,则本地加密很有价值的局限性场景是。

有些库确实实现了所需的功能,例如Stanford Javascript Crypto Library。但是,存在一些固有的弱点(如@ircmaxell的答案的链接所述):

  1. 缺乏熵/随机数生成;
  2. 缺少安全的密钥库,即如果私钥存储在本地或存储在服务器上(禁止离线访问),则必须对其进行密码保护;
  3. 缺乏安全擦除;
  4. 缺乏时序特征。

这些弱点中的每一个都对应于一类密码妥协。换句话说,尽管您可能拥有“ crypto”的名字,但它远低于人们在实践中所追求的严格性。

综上所述,精算评估不如“ Javascript加密功能弱,不要使用它”那么简单。这不是背书,严格地是警告,它要求您完全了解上述弱点的风险,所面临媒介的频率和成本以及在出现故障时的缓解或保险能力:Javascript crypto,in尽管它有弱点,但可能会减少您的接触风险,但只能针对技术能力有限的小偷。但是,您应该假定Java加密对于以该信息为目标的坚定而有能力的攻击者没有价值。当已知实现中固有的许多弱点时,有些人会认为将数据称为“加密”是一种误导。换一种说法,您可以略微减少技术风险,但可以通过披露增加财务风险。当然,每种情况都是不同的-减少将技术风险暴露于财务风险的分析并非易事。这是一个说明性的类比:尽管存在固有风险,但一些银行仍要求使用弱密码,因为它们所遭受的弱密码损失要小于支持强密码的最终用户成本。

🔥如果您阅读了最后一段,并认为“互联网上某个叫Brian的人说我可以使用Java加密技术”,请不要使用Java加密技术。

对于问题中描述的用例,用户加密本地分区或主目录并使用强密码似乎更有意义。该类型的安全性通常经过良好测试,广泛信任并且普遍可用。


NCC Group从2011年起提供了有关“请勿使用JavaScript加密”的一般立场的其他文档(引用):JavaScript密码学被认为有害(特别是由于22下载工具来验证下载是否有害 …PRNG质量) …等)
amcgregor

58

好吧,这里的基本前提是:不,它尚不安全。

基本上,您不能在JavaScript中运行加密:JavaScript Crypto被认为有害

问题是您无法可靠地将密码输入浏览器,即使可以,也不是为了让您安全地运行JS而设计的。因此,直到浏览器拥有一个加密容器(加密媒体扩展提供了该容器,但出于DRM目的而遭到反对)之前,将无法安全地进行操作。

就“更好的方式”而言,目前还没有。您唯一的选择是将数据存储为纯文本格式,并希望达到最佳效果。或者根本不存储信息。无论哪种方式。

要么,或者如果您需要那种安全性,并且需要本地存储,则创建一个自定义应用程序...


8
Downvoter:您能提供更好的答案吗?我意识到这是一个颇有争议的问题,其中安全专业人员(以及非专业人员)之间也存在很大分歧,因此值得分享其他观点。除非您出于其他原因拒绝投票,在这种情况下,我该如何改善此答案?
ircmaxell

9
@ircmaxell不是我,但是我不同意这个答案。“问题是,您无法可靠地将密码输入浏览器,即使可以,也不是为了让您安全地运行JS而设计的。” -为什么?有什么内在的问题呢?您可以使用Stanford JavaScript加密库并在其中进行加密/解密。您可以哈希,并且可以安全地进行所有操作。我在使用标准crpyto的JS脱机应用程序中没有看到固有的问题,就像使用任何其他语言构建的应用程序一样。
本杰明·格伦鲍姆

11
@BenjaminGruenbaum:问题在于,在很多地方,该密码都需要与第三方代码进行交互。我链接到该文章的重点是您无法控制执行环境。因此,您将安装Stanford Crypto库。然后,如果某些浏览器插件重写sjcl.encrypt以将密钥通过电子邮件发送给攻击者,会发生什么情况?在JS中,这是100%可能的,您无法采取任何措施来阻止它。这就是基本点。没有适当的“安全性”机制来阻止其他JS对您的数据进行令人讨厌的事情。那是个问题
ircmaxell,2013年

13
@ircmaxell如果您和狗一起睡觉,您不能指望不被跳蚤唤醒。如果用户安装的恶意软件与在PC上安装病毒的用户相同,则没有什么不同。您的Java或C程序可以像它获得的一样安全,但是一旦攻击者有能力运行使您陷入困境的代码,就可以保证它的安全。JS没什么不同。插件不仅会神奇地出现在浏览器中。此外,如果用户感染了恶意软件,则不保存加密信息将无济于事,因为这可能会实时劫持数据。
本杰明·格伦鲍姆

9
@BenjaminGruenbaum:不同意。在普通应用程序中,您可能需要破坏应用程序本身(以读取内存位置),或者需要root用户才能访问该框(危害操作系统)。无论哪种方式,您都需要做出比正常行为更深刻的折衷。JS允许这种正常行为。这是问题所在……
ircmaxell

12

作为对该主题的探索,我有一个名为“使用Web加密API保护TodoMVC”的演示文稿(视频代码)。

它使用Web加密API通过密码保护应用程序并使用密码派生密钥进行加密,从而将加密的待办事项列表存储在localStorage中。如果忘记或丢失密码,将无法恢复。(免责声明-这是一个POC,而不是用于生产使用。

在其他答案的状态下,这仍然容易受到客户端计算机上安装的XSS或恶意软件的影响。但是,当数据存储在服务器上并且正在使用该应用程序时,任何敏感数据也将位于内存中。我建议脱机支持可能是引人注目的用例。

最后,对localStorage进行加密可能只会保护数据免受攻击者的攻击,这些攻击者对系统或其备份具有只读访问权限。它为OWASP十大A6敏感数据暴露项目增加了少量的纵深防御,并允许您回答“这些数据是否长期以明文形式存储?” 正确地。


3

这是一篇非常有趣的文章。我正在考虑实施JS加密,以在使用本地存储时提供安全性。绝对清楚,这仅在设备被盗(并且正确实施)时才提供保护。它不会提供针对键盘记录程序等的保护。但这不是JS问题,因为键盘记录程序威胁是所有应用程序的问题,无论它们的执行平台(浏览器,本机)如何。对于第一个答案中引用的文章“ JavaScript Crypto被认为有害”,我有一个批评;它指出“您可以使用SSL / TLS解决此问题,但这既昂贵又复杂”。我认为这是一个非常雄心勃勃的主张(并且可能带有偏见)。是的,SSL有成本,

我的结论-客户端加密代码存在一个地方,但是与所有应用程序一样,开发人员必须认识到它的局限性,并在适合其需求的情况下实施,并确保有减轻其风险的方法。


历史上,与初始连接协商相关的费用非常高(机械的,不是财务的)。到这一点,公司将使用专用的SSL终端设备,这可能会在经济上使成本超出证书颁发和保证成本。如今,这些问题中的许多问题已得到解决,例如延长了会话持续时间以避免在后续请求上进行初始握手。
amcgregor

2

无法访问任何网页(true),但可以通过chrome(ctl-shift-J)等开发工具轻松访问和轻松编辑。因此,在存储值之前需要自定义加密。

但是,如果javascript需要解密(以进行验证),则解密算法将公开并可以进行操作。

Javascript需要一个完全安全的容器,并且需要能够正确实现仅对js解释器可用的私有变量和函数。但是,这违反了用户安全性-因为跟踪数据可以不受惩罚地使用。

因此,javascript将永远不会完全安全。


-29

没有。

任何页面都可以访问localStorage,如果您有密钥,则可以更改所需的任何数据。

话虽如此,如果您可以设计一种安全地加密密钥的方法,则无论如何传输数据都没有关系,如果可以将数据包含在闭包中,那么数据(某种程度上)是安全的。


19
“任何网页”都不是必需的。仅当前域中的页面可以访问它。
dtabuenc '16

相反,@ dtabuenc,我用笔写了一下,向您显示了localStorage中的每个键/值对,没有任何黑客攻击。
hellol11

3
不!抱歉。本地存储是按域隔离的。在一个域中运行的代码无法访问由另一个域存储到本地存储中的值。例如,google.com将一堆东西存储在本地存储中。在您的笔示例中,您将无法列出google.com中的任何键。
dtabuenc

@dtabuenc测试了它,您是对的。
hellol11
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.