本地存储可以被认为是安全的吗? [关闭]

Posted

技术标签:

【中文标题】本地存储可以被认为是安全的吗? [关闭]【英文标题】:Can local storage ever be considered secure? [closed] 【发布时间】:2013-06-21 05:59:57 【问题描述】:

我需要开发一个可以长时间离线运行的网络应用程序。为了使其可行,我无法避免在本地存储中保存敏感数据(个人数据,但不是您只会存储散列的那种数据)。

我接受这不是推荐的做法,但在别无选择的情况下,我正在执行以下操作来保护数据:

使用 stanford javascript 加密库和 AES-256 对进入本地存储的所有内容进行加密 用户密码是加密密钥,不存储在设备上 通过 ssl 从单个受信任服务器提供所有内容(在线时) 使用 owasp antisamy 项目验证进出服务器本地存储的所有数据 在 appcache 的网络部分,不使用 *,而是仅列出与受信任服务器连接所需的 URI 通常尝试应用 OWASP XSS 备忘单中建议的指南

我明白魔鬼往往在细节中,并且知道总体上对本地存储和基于 javascript 的安全性存在很多怀疑。任何人都可以评论是否有:

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

感谢您的帮助。

【问题讨论】:

“我接受这不是推荐的做法” - 是这样吗?不正是为此而创建的相反吗? 澄清一下,我的意思是不建议将敏感数据存储在本地存储中。 您不应该通过大型网络传递敏感数据? @user1173706 为什么应用程序必须长时间离线运行?用户是什么样的?您必须支持哪些浏览器?我个人认为这是可能的,但我需要了解你的场景的细节。 @Benjamin 我已经更新了这个问题。谢谢。 【参考方案1】:

网络加密

下面详细介绍了客户端(浏览器)javascript 中的加密问题。除了其中一个问题之外的所有问题都不适用于WebCrypto API,现在是reasonably well supported。

对于离线应用,您仍然必须设计和实施安全的密钥库。

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

Native-Javascript 加密(WebCrypto 之前)

我认为主要问题是有人可以物理访问计算机并为您的站点读取 localStorage,并且您希望密码学来帮助防止这种访问。

如果有人拥有物理访问权限,那么您也很容易受到比阅读更糟糕的攻击。这些包括(但不限于):键盘记录器、离线脚本修改、本地脚本注入、浏览器缓存中毒和 DNS 重定向。这些攻击只有在用户使用机器后才有效。然而,在这种情况下,物理访问意味着您会遇到更大的问题。

因此请记住,本地加密货币有价值的有限情况是机器被盗。

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

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

这些弱点中的每一个都对应于一类加密妥协。换句话说,虽然你可能有“加密”的名字,但它远低于人们在实践中所渴望的严格程度。

话虽如此,精算评估并不像“Javascript 加密很弱,不要使用它”那么简单。这不是背书,严格来说是警告,它要求您完全了解上述弱点的暴露、您面临的向量的频率和成本,以及您在发生故障时的缓解或保险能力:Javascript crypto,在尽管它有弱点,但可能会减少您的曝光率,但只能针对技术能力有限的盗贼。但是,您应该假设 Javascript 加密对针对该信息的坚定且有能力的攻击者没有任何价值。有些人会认为,当已知有如此多的弱点是实施所固有的时,将数据称为“加密”是一种误导。换句话说,您可以略微减少您的技术风险敞口,但您会因披露而增加您的财务风险敞口。当然,每种情况都是不同的——减少金融风险的技术风险的分析并非微不足道。这是一个说明性的类比:Some banks require weak passwords,尽管存在固有风险,因为他们因弱密码而遭受损失的风险低于最终用户支持强密码的成本。

? 如果您阅读最后一段并认为“互联网上有一个叫 Brian 的人说我可以使用 Javascript 加密”,不要使用 Javascript 加密。

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

【讨论】:

NCC 集团从 2011 年起提供了关于“不要使用 JavaScript 加密”的一般立场的其他文档(引用):JavaScript Cryptography Considered Harmful(尤其是由于下载该工具的第 22 条规则)验证下载... PRNG质量...等)【参考方案2】:

嗯,这里的基本前提是:不,它还不安全。

基本上,您不能在 JavaScript 中运行加密:JavaScript Crypto Considered Harmful。

问题在于您无法可靠地将加密代码输入浏览器,即使可以,JS 也并非旨在让您安全地运行它。因此,除非浏览器拥有加密容器(加密媒体扩展提供,但出于 DRM 目的而受到反对),否则不可能安全地进行。

就“更好的方法”而言,目前还没有。您唯一的选择是以纯文本形式存储数据,并希望获得最好的结果。或者根本不存储信息。无论哪种方式。

无论是这样,或者如果您需要那种安全性,并且您需要本地存储,请创建一个自定义应用程序...

【讨论】:

Downvoter:你能提供一个更好的答案吗?我意识到这是一个有争议的问题,安全专业人员(以及非专业人员)之间存在重大分歧,因此值得分享另一种观点。除非您出于其他原因投反对票,否则我该如何改进这个答案? @ircmaxell 不是我,但我不同意这个答案。 “问题是你不能可靠地将加密代码输入浏览器,即使你可以,JS 也不是为了让你安全地运行它。” - 为什么? 固有的问题是什么?您可以使用斯坦福 JavaScript 加密库并在其中加密/解密。你可以散列,你可以安全地做所有事情。我看不到在 JS 中执行标准 crpyto 的离线应用程序中存在的固有问题,就像用任何其他语言构建的应用程序一样。 @BenjaminGruenbaum:问题在于加密代码需要与第三方代码交互的多个地方。我链接到的那篇文章的全部要点是您无法控制执行环境。所以你安装了斯坦福加密库。那么如果某些浏览器插件覆盖sjcl.encrypt 将密钥通过电子邮件发送给攻击者会发生什么?在 JS 中,这是 100% 可能的,你无法阻止它。这就是根本点。没有“安全”机制来防止其他 JS 对您的数据做讨厌的事情。这是一个问题 @ircmaxell 如果你和狗一起睡觉,你不能指望醒来时不会有跳蚤。如果用户安装了恶意软件插件,就像用户在他们的 PC 上安装病毒一样,它并没有什么不同。您的 Java 或 C 程序可以尽可能地安全,但只要攻击者有能力运行代码,您就完蛋了。这对 JS 来说并没有什么不同。插件不只是神奇地出现在浏览器中。此外,如果用户有恶意软件,不保存加密的信息也无济于事,因为它可能会实时劫持数据。 @BenjaminGruenbaum:不同意。在普通应用程序中,您需要要么 来破坏应用程序本身(读取内存位置),或者获得对盒子的root 访问权限(破坏操作系统)。无论哪种方式,您都需要做出比正常行为更深层次的妥协。 JS 在正常行为中允许这样做。问题出在哪里...【参考方案3】:

作为对这个主题的探索,我有一个题为“使用 Web 加密 API 保护 TodoMVC”的演示文稿(video、code)。

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

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

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

【讨论】:

【参考方案4】:

这是一篇非常有趣的文章。我正在考虑实施 JS 加密以在使用本地存储时提供安全性。很明显,这只会在设备被盗(并且正确实施)时提供保护。它不会提供针对键盘记录器等的保护。但这不是 JS 问题,因为键盘记录器威胁是所有应用程序的问题,无论它们的执行平台(浏览器、本机)如何。对于第一个答案中引用的文章“JavaScript Crypto Considered Harmful”,我有一个批评;它指出“您可以使用 SSL/TLS 来解决这个问题,但这既昂贵又复杂”。我认为这是一个非常雄心勃勃的主张(并且可能相当有偏见)。是的,SSL 是有成本的,但是如果您考虑为多个操作系统开发本机应用程序的成本,而不是仅因为这个问题而基于 Web 的应用程序,那么 SSL 的成本就变得微不足道了。

我的结论 - 客户端加密代码有一席之地,但与所有应用程序一样,开发人员必须认识到它的局限性并在适合他们的需要时实施,并确保有降低风险的方法。

【讨论】:

历史上存在与初始连接协商相关的异常成本(机械成本,而非财务成本)。以至于企业会使用专用的 SSL 终端设备,除了证书颁发和保证成本之外,这在财务上可能会变得昂贵。如今,其中许多问题已得到解决,例如延长会话持续时间以避免后续请求中的初始握手。【参考方案5】:

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

但是,如果 javascript 需要解密(验证),那么解密算法就会暴露出来并且可以被操纵。

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

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

【讨论】:

【参考方案6】:

没有。

任何网页都可以访问localStorage,如果你有密钥,你可以更改任何你想要的数据。

话虽如此,如果您可以设计一种方法来安全地加密密钥,那么您如何传输数据并不重要,如果您可以将数据包含在闭包中,那么数据(在某种程度上)是安全的。

【讨论】:

“任何网页”都无法访问。它只能被当前域中的页面访问。 @dtabuenc 相反,我不久前做了一支笔,显示every single key/value pair in your localStorage,没有任何黑客攻击。 不!对不起。本地存储是按域隔离的。在一个域中运行的代码无法访问由另一个域存储到本地存储中的值。例如,google.com 在本地存储中存储了一堆东西。您将无法在您的笔示例中列出来自 google.com 的任何键。 @dtabuenc 测试过,你是对的。 @DanielTabuenca 你能提供一些资料来进一步解释你的答案吗?

以上是关于本地存储可以被认为是安全的吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

本地存储库的好常春藤教程? [关闭]

H5的本地存储

使用 Ionic 的本地存储

你推动每一次提交吗? [关闭]

iOS 钥匙串在设备之间共享数据

线程本地存储,thread_local关键字是必须的吗?