“ if password == XXXXXXX”是否足以确保最低安全性?


20

如果我为具有中到低安全风险的应用程序创建登录名(换句话说,它不是银行应用程序或任何其他应用程序),那么我可以接受用户输入的密码,只需输入类似以下内容的密码即可:

if(enteredPassword == verifiedPassword)
     SendToRestrictedArea();
else
     DisplayPasswordUnknownMessage();

这似乎很容易有效,但是我当然不介意是否仅此而已。对用户名/密码组合进行简单检查是否足够?

更新:特定项目恰好是Web服务,验证完全是服务器端的,并且不是开源的。域会改变您的处理方式吗?


3
这取决于有效密码来自何处?如果是硬编码,则不更改密码就无法配置/更改密码。如果它来自配置文件,则访问该文件的任何人都将可见。
Alb

1
“检查用户名/密码组合是否足够”可以做什么?
克里斯,

3
@opinion:这似乎比没有登录更令人担心。请为此类强烈要求提供一些理由。
Morgan Herlocker 2011年

1
您的术语是错误的,当您比较密码以进行验证时,不能确保其有效。 请花一些时间来了解它们之间的区别。
billy.bob 2011年

1
这意味着纯文本密码存储是不负责任的。这还意味着向用户发出密码错误的警报,这为潜在的攻击者提供了太多信息。您应该始终模棱两可,即“登录名或密码错误”。
Rein Henrichs

Answers:


26

不是没有SSL

如果密码是通过网络以纯文本格式发送的,则这是不安全的。如果密码是通过网络以纯文本格式发送的,则在服务器端散列密码也是不安全的。

由于HTML <input type="password"/>标记以纯文本形式发送其内容,因此,无论您如何在服务器上存储密码,这都是一个问题,除非您的网站使用SSL传输密码。

(HTTP身份验证会在浏览器中弹出一个对话框,要求您输入密码,它可能是明文,也可能不是明文,这取决于服务器和浏览器共有的身份验证机制。因此,这可能是一种无需使用而避免这种情况的方法SSL。)

如果站点管理员怀疑,则不是

现在,假设您正在使用HTTPS来访问网站,那么如果您信任站点管理员(他们可以读取纯文本密码)以及有权访问该计算机的其他人员来正常运行,那么这可能是安全的。现在,很明显,他们可以对您的网站进行任何操作(因为要管理该网站),但是,如果他们可以读取密码,则他们也可以在其他人的站点上使用被盗的登录名/密码对。

一种使密码对管理员安全的方法

一种安全的密码存储和检查方式如下:

def change_password user, new_password
  salt = random(65536).to_s(16) #will be 4 characters long
  password_hash = salt + hash(salt + new_password)
  store(user,password_hash)
end

def does_password_match? user, entered_password
  correct_password_hash = retrieve(user)
  salt = correct_password_hash[0...4]
  entered_password_hash = salt + hash(salt + entered_password)
  return correct_password_hash == entered_password_hash
end

对于哈希函数,请尝试使用强大的功能,以及尚未使用好的彩虹表的功能。如果需要在彩虹桌子周围工作,您可以更改盐的长度。

根据您所处的环境,网络延迟的可变性以及用户名是否旨在为公众所知,hash('0000'+entered_password)如果用户不存在,则可能需要计算另一个代码路径,以防止攻击者根据花费的时间确定哪些用户名有效,再确定密码不正确。


1
好的建议:)关于SSL,我们需要设计一些可以在野外使用的东西,并且仅使用非对称密码对密码进行编码(需要Javascript),然后在服务器上对其进行解码。盐+哈希然后正常发生。另外,由于公钥是随网页一起发送的,因此它可以经常任意更改。
Matthieu M.

1
@Matthieu M .:当某人可以伪造您的网页时,他还可以在那里将公共密钥更改为他本人知道相应私钥的密钥。因此,您的想法仅对被动阅读攻击有所帮助,而对中间人没有帮助。
圣保罗Ebermann

@Paulo:是的,我同意SSL不仅与加密有关,而且与证书有关,不幸的是,我在这里不做主,当人们说他们想定期使用该网页时 http://连接 ……令人沮丧: /
Matthieu M.

@Matthieu:这是否意味着您要将public_key作为公共网页的一部分encrypt(entered_password, public_key)发送,在客户端上进行计算,然后将结果发送到执行的服务器上does_password_match?(user, decrypt(encrypted_password, private_key))
肯·布鲁姆

@Ken:或多或少,您正确地进行了加密。为了匹配密码,它的密码更多does_password_match(user, salt, decrypt(encrypted, key)),具体取决于用户。正如我所说,明显的问题是缺乏中间人保护。
Matthieu M.

52

这表明,即使在安全性较低的情况下,也要以开放文本形式保存密码,这是不可以的。

您应该拥有:

if(hash(enteredPassword) == storedHash)

您可以使用简单的哈希,例如MD5


22
+1用于散列密码。但我至少也要加些盐。否则,由于用户将在系统之间重用用户名和密码,因此,破坏您的低安全性应用程序可能会使攻击者破坏更高安全性的应用程序。例如,最近的HBGary黑客设法破坏了运行其网站的CMS系统,并将其转变为对其服务器的根访问,部分原因是低安全性CMS系统并未在哈希中加盐arstechnica.com/tech-policy/新闻/ 2011/02 /…
贾斯汀·凯夫

1
同意...考虑以下问题。“字符串JavaFile.class | grep -i password”
比尔

如果仅使用一次密码,则密码为纯文本会有什么问题?

10
@Tim,因为用户不会只使用一次密码。研究始终表明,用户被告知多次重复使用密码(例如,register.co.uk / 2011/02/10 / password_re_use_study ),无论他们被告知不重复使用多少次。
斯科特

3
@Tim:此外,只需在文本编辑器中打开exe,dll等,您可能会在此处看到密码。
Gus Cavalcanti

14

我同意那些建议使用散列的人的意见,但是您在这里也正在重新发明一个轮子。根据平台的不同,您可能会找到一个角色/用户管理工具,该工具可以安全可靠地覆盖所有用户管理内容,而无需您过多干预。


我只是发现了ASP.Net成员资格提供程序,但我看着他们在想:“我浪费了多少时间来实现这样的事情?”
glenatron

8

安全是一个非常棘手的问题,特别是因为在给用户带来不便与确保其信息安全之间需要保持平衡。通常,所需安全性的公式取决于数据的重要性。简而言之:

isSecuritySufficient = effortToBreak > rewardForBreaking

对做坏事的人的普遍误解是他们所追求的。他们大多数人是在破坏信任。您应该始终竭尽所能来保护用户的信任。其中一部分是在进行尽职调查以确保其身份安全。他们可能不太在乎所存储的数据,但他们确实在乎自己的身份,即使是在最低安全阈值下也是如此。

有许多低成本的选择(可以实施并影响用户)。其中之一就是将密码散列到最低限度。任何以纯文本形式存储与密码一样敏感的内容的服务都应该被黑客入侵。

密码保护的一般原则

  • 决不以纯文本形式存储密码
  • 使用安全的散列函数(例如SHA-1甚至SHA-512)进行散列(即使MD5也很难找到匹配的散列)
  • 使用应用盐值。盐是随机字节,或者添加到密码中以使其更难以猜测。盐应在运行时生成,并使用有关机器的信息作为种子值,而不是以任何方式存储和引用。
  • 使用用户特定的盐值。将此与您的应用盐一起使用。
  • 加密通过网络的所有身份验证请求。这意味着对Web应用程序使用SSL。

由于您将使用SSL进行身份验证,因此至少要对与用户帐户有关的所有页面进行加密。这允许尽可能多地保护用户身份。

关于密码管理的注意事项:用户将不时忘记密码。您可以做的绝对最糟糕的事情是通过电子邮件将密码发送给他们。如果您执行上述原则,无论如何您将无法做到。最好提供一种使用发送到其注册电子邮件地址的链接来重置其密码的方法。该重置链接将具有一次性使用代码,以确保访问页面的人就是他们。


1
刚开始,我对应用盐+用户盐的想法确实感到震惊,但是我对它的思考越深,我就越不相信我。例如,如果您使用了应用程序盐的4个字符和用户盐的4个字符,则该用户盐和8个字符的用户盐之间的区别只是每个用户的盐都相同。似乎仅增加用户盐的大小而不是增加应用盐会更安全。另外,如果应用程序盐基于硬件,则在不使所有密码无效的情况下无法升级或更改硬件。
David Conrad

问题是用户盐和用户密码一起包含在数据库行中。如果一个坏人知道盐的用途(并且确实如此),并且他们在数据库中看到了盐,那么他们就会知道如何彻底破解它。通过在应用程序中包含一个已计算的部分(每次提醒您都是一样的)而不是存储它,这使得破解用户表变得更加困难。当然,您可以更进一步,制作1份纯无盐盐和1份经计算的盐,两者都是用户特定的。
Berin Loritsch 2011年

嗯,我知道了,将部分盐保留在数据库之外。确实有道理。谢谢。
戴维·康拉德

只要每行唯一,我看不出存储盐的问题。这是一个哈希值:“ fd84235a55bbfeb1585a3dd069d48127989c9753058b51b6ba2056fd6c5a0a91”(SHA256),这是盐:“ 671254bdf7944f8fa88e6c9913b948ee”。认为您可以获得密码?该盐没有彩虹表(即使您得到了盐),也被卡在蛮力逼迫中。
Bryan Boettcher

3

除非密码用于其他用途,否则就可以了。用户仍然有风险决定可以重用该密码,因此使用以下方法会更好:

if(hash(enteredPassword) == hashOfValidPassword)

如果是为自己或知道密码以纯文本格式存储的人,那很好。


1
就像贾斯汀·凯夫(Justin Cave)对vartec的回答if (hash (enteredPassword + salt) == hashOfValidSaltedPassword)所做的评论一样,请使用盐,因此-请注意,+它可能是串联的,而不是加法的。这确实阻碍了Rainbow表的使用,后者是可能的密码哈希表。
David Thornley,

如果您要检查的只是一个哈希,它们会不会只是在可能的字符串循环中运行,直到生成与存储的哈希相同的哈希?毕竟,有许多字符串可能对应于同一哈希。
Morgan Herlocker

@Prof Plum:如果哈希算法很好,很难找到冲突。这是现代加密技术的基础:它们本质上是单向功能。

3

源代码可用吗?即使没有,我也很确定如果二进制文件可用,可以在机器指令中找到密码。我建议做一个校验和并进行比较。

即使您认为安全性不是很重要,也不要忽略它。


2
是的,如果这是一个开源项目,那就不好了:)

-1-如果您认为拥有来源会有所作为,那么您对安全一无所知。
mattnz 2012年

1

绝对不。有读这个,它描述了黑客如何入侵了一个安全的网站。您计划将您作为链中最薄弱的环节。


0

在几个答案中已经指出,您不应存储密码本身,而应存储哈希值-并且应使用SSL。

您可能会说,有什么大不了的?如果我的应用程序被黑客入侵,那就不用担心了。嗯,这是用户在所有站点上重复使用相同密码的一种非常普遍的模式。作为一个黑客,您可以黑客入侵您的网站并获得用户密码,该黑客可以在其他网站上冒充许多对这些用户而言更为重要的用户。因此,入侵您的网站可能是黑客获得银行信息的第一步

仅散列密码是不够的。您需要用盐将其哈希。黑客拥有反向哈希查找表,因此对于给定的哈希,他们可以找到匹配的密码。

如果选择不实施这些功能,则应告知用户这种安全性不足,鼓励他们不要使用与其他地方相同的密码。


-2

只要这是服务器端。

如果需要更高的安全性,请使用https并在数据库中加密\散列密码。


3
为什么要假设这是一个Web应用程序?
克里斯,

好点子!我已经做了。
11

4
-1,即使是在服务器端,也仍然不行。
GSto
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.