我看到过密码哈希的示例是:H(用户名+ salt +密码)。添加用户名的目的是什么?有什么目的吗?

评论

相关:用用户名的哈希值生成盐是否可以接受?

作者很可能混淆了“盐”和“胡椒”?如果您错误地使用了胡椒粉而不是(而不是添加)盐,那么添加用户名确实是合理的(尽管仍然不是一个好方法)。将用户名添加到仅胡椒中将至少使在同一台计算机上查找具有相同密码的用户更加困难(否则,纯胡椒不会阻止)。

生成确切的唯一哈希结果。假设其他用户之前已经保存过密码?,因此需要用户名以使其对某些用户更具唯一性。

@mfathirirhas盐对每个用户都是唯一的。

#1 楼

不,没有目的。这是安全剧院*。盐的目的是使对所有散列密码的并行攻击变得不可行,并破坏彩虹表。在其中添加用户名不会改善该行为或增加安全性的任何其他方面。它实际上有一个缺点,因为如果您更改用户名,您现在会遇到一些麻烦,并且您需要维护一个更复杂和非标准的系统。从纯粹的密码学意义上讲,没有缺点。但是,实际上,更多的复杂性意味着更多的错误。
salt和用户名的属性
您可能会认为用户名本身可能不是公开的,因此使用它作为额外的秘密也不会受到伤害,但事实是,数据库很可能已经包含纯文本用户名,从而使这一本已令人怀疑的好处无效。人们应该坚持现有的身份验证技术。但是,让我们看一下每个对象的属性:
盐是:


不是秘密-盐以明文形式存储。


安全-它们是随机生成的,而且很长。


唯一-每个用户的使用意愿都是故意的。


密码是:


秘密-假设它们没有放在便笺上。


安全-如果不是猎人2。密码应该是好的。


唯一-理想情况下,至少,但并非所有密码都是理想的。


现在将其与用户名进行比较。用户名是:


不是秘密-它们是公开的,或者至少以纯文本格式存储。


不安全-没有人认为选择一个复杂的用户名。


不是唯一的-用户名可以在站点之间安全共享。


优质盐的特征
现在,盐到底能做什么?通常,优质的盐具有三个好处:


它可以防止攻击者立即攻击每个用户的哈希。攻击者不再能够散列候选密码并立即针对每个单个条目对其进行测试。他们被迫重新计算任何给定的密码,以测试每个用户的哈希值。盐提供的好处随着不同目标哈希条目的数量线性增长。当然,即使仅需要一个哈希值,盐也仍然很重要,如下所述。


它使彩虹表不可行。彩虹表是高度优化的预计算表,它会将密码与哈希值进行匹配。它们占用的空间少于巨大的查询表,但是生成时间却很长(以时空为代价)。为了使Rainbow表正常工作,给定的密码必须始终解析为相同的哈希。盐打破了这个假设,使得彩虹表不切实际,因为它们必须为每种可能的盐添加一个新条目。随机。攻击者只有在掌握了哈希值(以及盐之后)之后才能开始攻击。如果盐已经是公开的,但哈希值尚未公开,则可以通过为该特定盐生成彩虹表来优化攻击。这就是WPA2如此丑陋的协议的原因之一。最重要的是ESSID(网络名称),因此有人可以在进行四向握手之前就开始对目标路由器发起攻击。


那么,这有什么可能的好处当该值是公共的,不安全的并且可以重复使用时,将在散列之前连接一个值?最终并不需要攻击者挖掘更多信息。它不会增加盐的安全性。它不会增加密码的复杂性。没有好处。
正确的密码哈希
那么,他们应该怎么做才能提高安全性呢?他们可以使用诸如PBKDF2,bcrypt,scrypt或argon2之类的KDF代替单个哈希。他们可以添加Pepper,这是存储在数据库外部的随机全局值,并添加到了密码和盐中,这使得有必要窃取Pepper来尝试攻击哈希,而不是简单地使用SQLi来转储数据库。 >编辑:正如一些评论所指出的那样,存在一种人为设计的方案,其中用户名将有益于添加到混合中。在这种情况下,实现将被严重破坏,以至于盐实际上不是盐,并且用户名是数据库中唯一的每用户唯一或半唯一值,在这种情况下,将用户名混入会更好比什么都没有。但实际上,如果没有盐,则应开始使用一种盐,而不要尝试使用用户名。使用真实的安全性,当用户的安全在线时不要半途而废。
*在这种情况下,我将安全区定义为实施安全措施的实践,这种措施实际上并不能提高安全性。有意义的方式,并且仅用于提供更好的安全性的错觉。

评论


评论不作进一步讨论;此对话已移至聊天。

–Rory Alsop♦
18年8月8日在22:00

“没有人考虑选择一个冗长而复杂的用户名。”我不同意这一点。

– Kf6Jg'dAHj-'zNw2FDthNCwkh'-4x
18 Mar 8'8在23:26

“用户名通常在站点之间共享。”不得不大笑,因为这与密码不同,密码通常在站点之间共享。由于盐是唯一保证唯一的部分,因此我们的开发人员最好做到这一点!

– jpaugh
18 Mar 9 '18 at 14:47



@PeterGreen我不确定为什么会这样。如果盐使用的RNG不好,那还不是很糟糕。

–森林
18 Mar 10 '18 at 1:50

包含一个您没有提到的盐还有另一个好处:它可以防止在未知密码的顶部复制已知密码的哈希值,从而可以合法地访问另一个用户的帐户。不过,我忘记了这种攻击的名称。

–鲍勃森
18 Mar 11 '18 at 0:20

#2 楼

如果按预期的方式盐分足够随机,则添加用户名不会增加其他保护。但是,除了使代码更复杂之外,它也不会造成任何危害,这会增加发生错误的可能性。在进行代码审查时,它可能被视为开发人员未完全理解他在做什么的标志。因为在这种情况下,用户名实际上是出于盐不能提供服务的目的。但是,这不是推荐的方法,因为盐应该是随机的,而用户名不是。

请参阅在对诸如hash(username_str + password_str)之类的密码进行哈希处理时,使用用户名作为盐是一个好主意吗?以及应使用什么盐?深入讨论了什么是优质盐以及为什么用户名不是优质盐。另请参阅为什么加盐散列更安全地存储密码?首先要了解盐的用途。

评论


如果盐是从密码派生的,则实现者手头上会有更多问题。如果他们能够添加用户名,则他们应该能够解决问题。

–森林
18年8月8日在7:27

@forest:就像我说的那样:如果开发人员没有使用随机盐,他将无法完全理解自己在做什么。在这种情况下,开发人员可能会提出关于如何使用非唯一盐的最疯狂的想法,例如使用用户名或从密码中导出盐,或者“只是为了确定”。请参阅参考资料盐是否必须是随机的,还是仅仅是唯一且未知的?还是可以从密码派生出盐吗...看看盐的概念通常是如何被理解的。

– Steffen Ullrich
18 Mar 8 '18在7:36



等一下...如果盐是从密码派生的,那么您根本就没有盐,只是略有不同的哈希生成算法,该算法又容易受到彩虹表的攻击。彩虹表略有不同。

– gnasher729
18 Mar 10 '18 at 23:32

#3 楼

正如@Damien_The_Unbeliever在评论中指出的那样,它可以防止在系统受到部分破坏的情况下冒充用户。

想象以下情况。不知何故,攻击者已获得对用于登录的db表的读/写访问权,其中包含用户名,密码哈希和盐-可能是通过SQL注入攻击。该攻击者没有其他对系统的提升访问权限,但希望以无法追踪(或难以追踪)的方式模拟系统中的用户。


首先,攻击者记录了原始信息。受害者帐户的密码哈希和盐。
接下来,攻击者注册自己的帐户,并将密码哈希和盐从其帐户复制到受害者帐户。
现在,攻击者可以登录到使用攻击者自己的密码的受害者帐户。
攻击者完成攻击后,他们会还原受害者的密码哈希值和盐,这使得受害者很难意识到发生了什么事。

系统,具有此访问级别的攻击者可以使用受害者的用户名,盐和任意密码(而不是复制自己的密码)来简单地生成密码哈希,如果系统除盐之外还使用了胡椒粉,则这是不可能的(为所有密码哈希添加到输入的全局定义常数,该常数存储在与密码哈希和盐不同的地方)。在不影响Pepper的情况下,在这种情况下,攻击者可以使用受害者的已知密码设置密码哈希的唯一方法是复制系统生成的密码,如上所述。

请注意,两个-因素身份验证甚至无法阻止这种情况。如果攻击者还可以访问用户的2FA初始化代码(也许存储在同一数据库表中),则攻击者的代码也可以暂时写入受害者的帐户。

相反,如果在计算密码哈希时使用了用户名,则这种特定的模拟攻击将不起作用。即使攻击者将其密码哈希,盐和2FA代码复制到受害者的帐户中,在受害者帐户上使用攻击者的密码也不会产生与攻击者帐户相同的密码哈希,因此登录将失败。

好处是否值得额外的复杂性和错误的可能性值得商bat,因为这种情况要求攻击者已经严重破坏了系统,并且在这种情况下攻击者无法恢复用户的安全。实际密码。但是,可以说这是一种额外的保护。

评论


@IMSoP系统已经严重破坏了数据库的读写访问权限,以至于您已经可以模拟用户。只需将您的用户设置为管理员即可。只需更改用户的用户ID。你什么都可以做。

–森林
18 Mar 8 '18 at 14:51

@forest如果攻击者能够执行SQL注入攻击,但其他方面没有破坏系统,则否,冒充用户不是一件容易的事。我添加了一些说明,并提供了指向SO帖子的链接,该帖子解释了为什么“胡椒”除了盐之外还有用。 (这是完全相同的情况,其中一个受损的数据库并不意味着整个系统都受到了损害。)如果这不是人们所关心的情形,那么没有人会在其哈希表中使用胡椒。

– Zacronos
18 Mar 8 '18 at 14:54

@forest完全按照此答案所说的方式提供帮助:它防止具有写访问权的用户冒充用户的一种方法。如您所说,通过与数据库中的其他记录打乱,可能还有其他方式可以做到这一点,并且这个答案清楚地表明好处是值得商,的,但它确实限制了特定的攻击,并迫使攻击者找到另一条路线。

–IMSoP
18 Mar 8 '18 at 14:58

@AndrolGenhald同意了,我在回答中承认,这样做可能不值得。交换用户名可能是一个选择,但是如果数据中发生任何非规范化或完全记录日志,仅交换用户名可能就无法提供完美的模拟。 OP提出的问题不是这样做是否值得,而仅仅是它是否有目的,如果有的话。

– Zacronos
18年8月8日在15:14

如果我们将其重新构想为内部威胁,则此答案中描述的攻击会让我觉得更合理。想象一下,一家公司拥有一个由恶意管理员管理的数据库实例支持的单点登录系统,该实例具有对密码数据库的读/写访问权限,但对他们想进入的其他资产没有读/写访问权限(包括映射)在SSO身份和权限之间)。这样的流氓管理员可以通过覆盖用户的密码条目来代替自己的密码哈希来访问其他特权更高的帐户。

–路易斯·卡西利亚斯(Luis Casillas)
18 Mar 8 '18在20:50



#4 楼

首先,应使用专用的密码哈希功能(例如bcrypt,Argon2,scrypt或PBKDF2)进行密码哈希处理。在这种情况下,您不必像原始方法那样处理盐和密码的连接。该函数将那些作为单独的参数。有关此主题,请参阅本网站上最常见的问答之一“如何安全地对密码进行哈希处理”。 。因此,通常适用于现代专用密码散列的三个规则是:


每次注册新密码时,您都应该产生新鲜的盐。 (请注意,这意味着用户更改密码时,应为该密码生成一个新的盐,而不是为旧密码重用该盐。盐绑定到密码数据库条目的状态,而不是用户。) > salt的值应与密码本身无关;密码知识对猜中盐应该没有帮助,否则,攻击者可能会使用该知识来预先计算攻击表。一个明显的例子是,您不应将密码本身当作盐。 (这听起来不那么傻了,在这种情况下,您不会在密码中加盐。但是它很傻,因为两个使用相同密码的用户将具有相同的哈希值。)盐彼此相等应该很低。最好不仅在您的应用程序中,而且在全球范围内。

现在,我们可以通过进行以下观察来回答您的问题:


足够数量的随机字节已满足这些条件。合理的16个随机字节(来自加密强度高的随机数生成器)。
将用户名与这样的随机盐连接起来并没有帮助。
如果以某种可预测的方式生成了盐,但有些重复(例如,作为每次您注册新密码时都会增加的计数器)或作为时间戳生成的盐,则将诸如用户名或网站域名之类的其他值连接起来有助于它更加独特。但是使用随机盐会更简单(无需跟踪持久计数器状态)。