密码存储在内存中安全吗?

13

我倾向于将用户密码存储在内存中供日后使用。

var credentials = {};
function register(username,password){
    //when users click sign up
    credentials.username = username;
    creadentials.password = password;
}
function login(){
    //Users can click login at anytime. Or they just don't.
    ajax('/User/login',credentials).then(function(){
        credentials = {};
    });
}

我应该担心这种方法的安全任务吗?如果这是一个不好的想法,攻击者将如何检索密码?


4
假设你没有在 creadentials 打错字的情况下,我可以从扩展程序、书签脚本、或者一个 iframe 等多种入口写入 alert(window.credentials.password) - CodingIntrigue
1
是的,而且使用普通的HTTP协议发送时,它们会以明文形式“通过网络”传输,任何人都可以看到... - Neil Hibbert
在页面中使用JavaScript存储敏感数据值的安全问题在于,敏感值可以作为文本在源代码中被查看,或者页面上的另一个JS函数可以访问该对象并提取这些值。当您在单个页面上运行来自多个来源的应用程序(例如Facebook)时,这将成为一个问题。 - Viraj Nalawade
1
@Tresdin 我可以在Chrome中安装扩展。或者只需在某人的计算机上打开控制台并输入该命令。 - CodingIntrigue
4
你为什么要这么做?密码应该立即被替换为一些会话令牌。如果需要再次使用,用户应该再次输入密码。 - Thilo
显示剩余3条评论
3个回答

18

问题是你试图防止哪种攻击?

当尝试判断某个东西是否安全时,尝试列出可能的攻击者,然后看看他们是否能够攻击它。例如,在这种情况下:

  • 一个离线攻击者(基于网络):

    在所有方面,内存中的密码都是安全的。

  • 一个在线攻击者,不同的用户,非管理员

    在所有方面,内存中的密码都是安全的,因为操作系统限制了攻击者访问内存块的权限。

  • 一个在线攻击者,相同的用户,非管理员

    如果攻击者可以以与您的代码相同的用户帐户访问系统,则内存中的密码可能会泄漏。

  • 一个在线攻击者,不同的用户,root

    这与上述情况相同,密码可能会泄漏。

但是,这里有一个重要的陷阱。如果攻击者可以作为相同的用户或根用户访问系统,那么您将面临更大的问题。例如,他们可以篡改您的代码,远程发送所有密码(当它们被输入时)给他们。

因此,在实际操作中,无论哪种情况下密码都会泄漏。

但是,这里有一个主要的例外。想象一下应用程序出现段错误。操作系统会生成核心转储。如果您以明文存储密码,则密码将以明文形式出现在该核心转储中。这是一个相当严重的问题。

建议

虽然实际上,任何能够读取明文密码的攻击者都可能做其他恶意事情,但我们想要进行深度防御。这意味着为攻击者提供多个障碍。我们不想让事情变得容易。

因此,我建议不要以明文方式存储密码。如果稍后需要明文密码(例如用于登录到远程系统),我建议重新设计以避免使用OAuth2或另一个联合身份验证系统。但是,如果必须这样做,请至少使用未存储(或至少保留)在内存中的密钥加密它。

更好的方法是对其进行一次单向散列,就像您为存储而做的那样(使用bcrypt、scrypt、pbkdf2等)。

2
您无论如何都会在内存中保存密码,尽管时间很短。它在内存中停留的时间越长,被嗅探的可能性就越大。但是,如果有人已经能够从您的内存中嗅探出密码,那么您已经失去了保护。因此,无论您将其保留多久,都不会有太大区别。
这可能与您的AJAX / REST基础设施的安全性有关,也可能无关紧要。也许您不应该一开始就使用明文密码,而是转向令牌系统,在初始身份验证之后不需要明文密码。但是,从我们看到的片段来看,这太过笼统。

然而,即使是短暂的时间也会有很大的区别。如果用户离开电脑,@RGraham 可以走到他们的桌子上窃取密码。如果它只在某个作用域局部变量中存在于 Ajax 请求的持续时间内,这将不会成为问题。 - Thilo
好的。如果你在一个函数中限定了变量的作用域,那么很难获取到它。而且如果没有提供物理安全保障,那么几乎无法做出任何保证(例如硬件键盘嗅探器)。 - deceze

2
每个攻击者可能获取明文密码的点都是一个问题。另一方面,这种情况易遭受攻击,而替代方案却不易遭受攻击的情况极为罕见(尽管我能想到一些)。
无论哪种情况,似乎您希望在注册后允许用户登录,可能同时等待验证邮件的确认?在这种情况下,更好的做法是将用户名和密码存储在服务器端内存中,因为它仍然可以给您带来所有相同的优势,而不会突然发现存在危险。最理想的情况是不要将密码存储在服务器端内存中,只存储用户名和一个标志/时间戳,表示密码是正确的。

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