在Javascript变量中存储密码的安全隐患是什么?

7

我正在开发一个需要良好安全性的Web应用程序。在当前设计中,许多用户操作需要用户重新发送他们的密码(否则服务器将不得不以明文方式存储它,至少是暂时的)。

许多用户交互是通过AJAX请求进行的。与其让用户为每个请求重新输入密码,我想做这样的事情:

var password_plain = document .getElementById ("password") .value;

ajax ("/login.php", {password: password_plain, username: ...});

// later

ajax ("/api.php", {password: password_plain, action: ...});

假设设计是合理的,例如:
  • 服务器不存储或泄漏明文密码
  • SSL已正确设置
  • 客户端JavaScript定期检查我们是否仍然登录,并在会话过期时设置password_plain=null(并清除DOM值)
  • 服务器本身是安全的
威胁模型是攻击者无法物理访问客户端或服务器计算机,也无法在两者上运行任意代码,但可以引诱用户访问客户端浏览器中的恶意其他网页。
在JavaScript变量中,密码是否安全?

唯一真正重要的是您使用HTTPS发布登录凭据,并且您的服务器正在使用适当的现代密码哈希。 - Pointy
1
并且您没有XSS漏洞。 - SLaks
1
@SLaks 是的,XSS 和 CSRF 保护很重要。基本上,关键在于您如何密切保护服务器通信并防范会话攻击(XSS、CSRF)。网络连接另一端的客户端不一定是您自己的代码。 - Pointy
3个回答

5

这要看情况。

如果您没有正确地封装您的作用域,第三方脚本在执行期间可以读取和修改您的变量(假设它被保留超过一个事件循环周期),但这是一种边缘情况。只要它是在任何类型的函数或模块内完成,并且您旁边没有XSS漏洞,就可以了。

也有关于程序可以查看内存等内容的问题,但这也无关紧要,因为如果用户在其计算机上运行此类软件,则您的JS代码是他们最不必担心的事情。

但我会补充一点,不建议您一遍又一遍地传输密码,通常您想要验证一次,获取某种一次性令牌(如会话令牌),并在会话期间使用该令牌进行身份验证。与密码不同,会话在出现问题时可以轻松地在服务器端失效。

重要的是:

  • HTTPS:如果未加密,请勿通过网络传输密码。在客户端对其进行哈希或加密不是可行的解决方案。
  • XSS或SQL注入 - 基本上任何从一种语言到另一种语言的转换都是危险的。在使用一种语言生成语句之前,请务必进行严格转义。
  • 数据库中的明文密码 - 这更多是服务器问题,基本上始终使用强大的加密哈希算法在数据库中存储密码。

1
浏览器漏洞,恶意插件和新的漏洞无法进行防范。尽管闭包在数据封装方面对于更好的模块化设计很好,但不足以安全地隔离敏感数据。我强烈建议重新考虑以这种方式存储任何用户凭据;它简直不安全。 - Mark
@Mark 但是我们仍将会话数据存储为 cookie,这本质上是一次性密码,这些密码通常可以从 JS 中访问,在非加密连接的情况下也容易受到中间人攻击。 - Madara's Ghost
1
“一次性”的概念在这里非常关键。如果该会话 ID 被盗,其影响不会像用户的主要凭据那样严重。这就是为什么首先使用会话 ID 而不是始终传输密码的原因。 - Mark
请问您能否详细解释一下“正确封闭作用域”的含义?我想您是指(function () { var password = ... })(),还是说还有其他的内容需要注意? - spraff
@spraff 是的,基本上就是这样。 - Madara's Ghost
显示剩余4条评论

3
考虑到会话 ID 存储在 cookie 中并随每个请求发送到服务器这一事实。听起来很熟悉吧?这就是你所做的事情,但密码代替了会话 ID。
个人建议使用正确的会话,但如果您想要一个“无状态”的系统,那么您在这里所做的应该是可以的,只要您认为其他方面都是“合理的”(尤其是 HTTPS)。

1

不,将其存储在JavaScript变量中绝对不安全。如果您将其存储在本地,则跨站脚本攻击(XSS)可能会以明文形式破坏并窃取用户的凭据。


1
当然,前提是存在开放的XSS漏洞。如果设计在一般情况下是“合理的”,那么就不会有这样的漏洞。 - Niet the Dark Absol
1
值得注意的是,如果变量在闭包中,并且从未暴露到全局范围,则没有XSS攻击可以看到它。 - Niet the Dark Absol
在处理安全问题时,假设没有漏洞永远不是好事。即使网站今天没有任何可能的XSS,但未来浏览器更新或用户安装恶意插件都可能改变这一点。以这种方式存储用户凭据是不安全的。 - Mark
就我个人而言,我认为“如果用户安装了恶意插件...那不是我们的问题”。 - Niet the Dark Absol
在某种程度上这是正确的,但用户凭据特别敏感。事实是,它们经常在不同网站之间使用,并且通常没有过期时间。当有更好的解决方案存在时(例如会话ID),为什么要不必要地暴露如此敏感的数据呢?如果有人怀疑提问者在亚马逊或大银行工作,我有一种感觉原始问题的答案会有所不同。人们希望他们的凭据得到更好的处理。 - Mark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接