密码盐如何帮助防止彩虹桌袭击?
我在理解盐对密码的用途方面遇到了一些麻烦。 我的理解是,主要用途是阻止彩虹桌的攻击。 然而,我所看到的实现这些方法似乎并不能真正使问题变得更困难。
我看过很多教程,build议使用盐作为以下内容:
$hash = md5($salt.$password)
原因是哈希现在不是映射到原始密码,而是密码和盐的组合。 但是要说$salt=foo
和$password=bar
和$hash=3858f62230ac3c915f300c664312c63f
。 现在有人用彩虹表可以颠倒散列,并提出input“foobar”。 然后他们可以尝试密码的所有组合(f,fo,foo,… oobar,obar,bar,ar,ar)。 获取密码可能需要几毫秒,但其他的不多。
我见过的其他用途是在我的linux系统上。 在/ etc / shadow中,散列密码实际上是与 salt一起存储的。 例如,“foo”的盐和“bar”的密码将哈希到: $1$foo$te5SBM.7C25fFDu6bIRbX1
。 如果黑客以某种方式能够得到这个文件,我不知道盐的用途是什么,因为te5SBM.7C25fFDu6bIRbX
的反向散列已知包含“foo”。
感谢任何人都可以摆脱这一点。
编辑 :感谢您的帮助。 总结一下,我的理解是,盐使得哈希密码更加复杂,从而使其不太可能存在于预先计算好的彩虹表中。 之前我误解的是,我假设所有哈希表都存在彩虹表。
破解单个密码时,公开的盐不会使字典攻击变得更困难。 正如你所指出的,攻击者可以同时访问哈希密码和盐,所以当运行字典攻击时,她可以简单地使用已知的盐,试图破解密码。
公共盐有两件事情:使更多的时间来破解大量的密码,并使它不能使用彩虹表。
要理解第一个,想象一个包含数百个用户名和密码的密码文件。 如果没有盐,我可以计算“md5(attempt [0])”,然后扫描整个文件,看看这个散列是否出现在任何地方。 如果存在盐,则必须计算“md5(salt [a]。attempt [0])”,与条目A比较,然后比较“md5(salt [b]。attempt [0])”)等等。现在我有n
倍的工作要做,其中n
是文件中包含的用户名和密码的数量。
要理解第二个,你必须了解彩虹表是什么。 彩虹表是用于常用密码的预先计算的散列的大量列表。 再想象一下没有盐的密码文件。 我所要做的就是通过文件的每一行,提取哈希密码,然后在彩虹表中查找。 我从来没有计算一个单一的散列。 如果查找速度比散列函数快(这可能是),这将大大加速破解文件。
但是,如果密码文件被腌制,那么彩虹表将不得不包含预先哈希的“盐密码”。 如果盐是足够随机的,这是不太可能的。 我可能会在我常用的预先哈希密码列表(“彩虹表”)中包含“hello”,“foobar”和“qwerty”等内容,但是我不打算使用“jX95psDZhello”或预先计算“LPgB0sdgxfoobar”或“dZVUABJtqwerty”。 那将使彩虹桌非常大。
所以,salt将攻击者减less为每次每次一行计算,当加上足够长的足够随机的密码(通常来说)是不可破解的。
其他的答案似乎并没有解决你对这个话题的误解,所以在这里:
盐的两种不同的用途
我看过很多教程,build议使用盐作为以下内容:
$hash = md5($salt.$password)
[…]
我见过的其他用途是在我的linux系统上。 在/ etc / shadow中,散列密码实际上是与salt一起存储的。
你总是必须用密码存储salt,因为为了validation用户input的密码数据库是什么,你必须将input与salt结合起来,对它进行散列,并将其与存储的散列进行比较。
散列的安全性
现在有人用彩虹表可以颠倒散列,并提出input“foobar”。
[…]
因为te5SBM.7C25fFDu6bIRbX的反向散列已知包含“foo”。
这是不可能的(至less在理论上)颠倒哈希。 “foo”的散列和“saltfoo”的散列没有什么共同之处。 改变密码散列函数的input中的一个位应该完全改变输出。
这意味着你不能用普通的密码build立一个彩虹表,然后用一些盐来“更新”它。 你必须从一开始就考虑到盐。
这就是为什么你首先需要彩虹桌的全部原因。 由于无法从哈希中获取密码,因此需要预先计算最可能使用的密码的所有哈希,然后将哈希与哈希进行比较。
盐的质量
但是说一下
$salt=foo
“富”将是一个非常糟糕的select盐。 通常你会使用一个随机的值,用ASCII编码。
此外,每个密码都有自己的盐分,与系统中所有其他盐类不同(希望)。 这意味着攻击者必须单独攻击每个密码,而不是希望其中一个哈希与其数据库中的某个值相匹配。
攻击
如果一个黑客以某种方式能够得到这个文件,我不知道盐的用途是什么,
彩虹表攻击总是需要/etc/passwd
(或者使用任何密码数据库),否则你会如何比较彩虹表中的哈希值和实际密码的哈希值?
至于目的:假设攻击者想要为10万个常用英文单词和典型密码(认为“秘密”)build立一个彩虹表。 没有盐,她将不得不预先计算100,000次哈希。 即使使用2个字符的传统UNIX盐(每个都是64个选项之一: [a–zA–Z0–9./]
),她将不得不计算和存储4096000000个散列值…这是一个相当大的改进。
用盐的想法是使用暴力猜测比用普通的基于字符的密码难得多。 彩虹桌往往是build立在一个特殊的字符集,并不总是包括所有可能的组合(虽然他们可以)。
所以一个好的盐值将是一个随机的128位或更长的整数。 这是彩虹表攻击失败的原因。 通过为每个存储的密码使用不同的盐值,还可以确保为特定的盐值构build的彩虹表(如果您是具有单一盐值的stream行系统,情况可能如此)并不能让您访问所有密码一次。
还有一个很好的问题,有很多很深思熟虑的答案 – 还有+1!
我没有明确提到的一个小问题是,通过为每个密码添加一个随机盐,实际上保证了两个碰巧select相同密码的用户将产生不同的哈希值。
为什么这很重要?
想象一下美国西北部一家大型软件公司的密码数据库。 假设它包含3万个条目,其中500个具有密码蓝屏 。 进一步假设黑客通过从用户到IT部门的电子邮件中读取密码来设法获得这个密码。 如果密码是不encryption的,黑客可以在数据库中find散列值,然后简单地进行模式匹配,就可以访问其他499个帐户。
对密码进行唾沫确保500个账户中的每一个都具有唯一的(盐+密码),为每个账户生成不同的哈希值,从而减less对单个账户的违规。 我们希望,任何一个在电子邮件中填写明文密码的用户都无法访问下一个操作系统的未公开API。
我正在寻找一个很好的方法来应用盐,发现这个优秀的文章与示例代码:
http://crackstation.net/hashing-security.htm
作者build议每个用户使用随机盐,以便获得一个盐的访问不会使整个哈希列表容易破解。
存储密码:
- 使用CSPRNG生成一个长的随机盐。
- 将saltjoin密码,并使用SHA256等标准encryption散列函数进行散列。
- 将salt和hash保存在用户的数据库logging中。
validation密码:
- 从数据库中检索用户的salt和hash。
- 将saltjoin给定的密码,并使用相同的散列函数进行散列。
- 将给定密码的散列与来自数据库的散列进行比较。 如果它们匹配,则密码是正确的。 否则,密码不正确。
盐可以使彩虹桌攻击失败的原因是,对于n位盐,彩虹桌必须比没有盐的桌子尺寸大2 ^ n倍。
你用“foo”作为盐的例子可能使虹表增加1600万倍。
鉴于卡尔的128位盐的例子,这使得表2 ^ 128倍大 – 现在这么大 – 换句话说,有人有便携式存储之前多久呢?
破解基于散列的encryption的大多数方法都依赖于powershell攻击。 彩虹攻击本质上是一种更高效的字典攻击,其目的是使用低成本的数字存储来创build一个可能的密码子集映射到哈希,并促进反向映射。 这种攻击是有效的,因为许多密码通常很短,或者使用几种基于字的格式之一。
这种攻击在密码包含更多字符并且不符合通用字格式的情况下是无效的。 开始使用密码较强的用户不会受到这种攻击风险的影响。 不幸的是,很多人不会select好的密码。 但有一个妥协,你可以通过添加随机垃圾来改善用户的密码。 所以现在,他们的密码不是“hunter2”,而是有效的“hunter2908!fld2R75 {R7 /; 508PEzoz ^ U430”。 但是,由于您现在必须存储此额外的密码组件,因此会降低较强复合密码的有效性。 事实certificate,从现在起,每个密码,甚至是弱密码,都不再容易受到相同的预先计算的散列/彩虹表的攻击。 相反,每个密码哈希表项仅仅是一个唯一的哈希表。
假设你有一个密码强度要求较弱的网站。 如果你没有使用密码salt,那么你的哈希就容易受到预先计算的哈希表的攻击,有权访问哈希的人就可以访问很大一部分用户的密码(不过很多人使用了易受攻击的密码,大量的百分比)。 如果你使用一个常量密码盐,那么预先计算的哈希表就不再有价值了,所以有人需要花时间为这个盐计算一个自定义的哈希表,但是它们可以递增地计算,计算表覆盖了更大的排列的问题空间。 最脆弱的密码(例如简单的基于字的密码,非常短的字母数字密码)将在数小时或数天内被破解,脆弱的密码在数周或数月后会被破解。 随着时间的推移,攻击者可以获得用户越来越多的密码。 如果您为每个密码使用独特的盐,那么需要几天或几个月才能访问每个易受攻击的密码。
正如你所看到的,当你从不加盐到恒盐加盐到一个独特的盐时,你会增加几个数量级来努力在每一步破解易受攻击的密码。 如果没有盐,用户密码中最弱的用户可以轻易访问,而且这些弱密码对于一个确定的攻击者来说是可以访问的,只有一个独特的盐,访问密码的成本提高得很高,只有最有决心的攻击者才能访问到易受攻击的密码的一小部分,然后只有很大的代价。
这恰恰就是这种情况。你永远无法完全保护用户免遭糟糕的密码select,但是你可以将损害用户密码的成本提高到一个使得即使是一个用户的密码过于昂贵也不会让步的问题。
腌制的一个目的是击败预先计算的散列表。 如果有人拥有数以百万计的预先计算的散列表,他们将不能在表中查找$ 1 $ foo $ te5SBM.7C25fFDu6bIRbX1,即使他们知道散列和盐。 他们仍然必须蛮横的力量。
另一个目的,正如Carl S所提到的那样,是使得强制性的哈希列表更加昂贵。 (给他们所有不同的盐)
即使盐是公开的,这两个目标仍然是完成的。
据我所知,盐的目的是使字典攻击更难。
这是一个众所周知的事实,很多人会用密码来代替看起来随机的string。
所以,黑客可以利用这一点,而不是仅仅使用暴力。 他不会寻找像aaa,aab,aac这样的密码,而是使用文字和普通的密码(比如主人公的名字!))
所以如果我的密码是Legolas的话,黑客就可以尝试一下,用一些“less”的尝试来猜测。 但是,如果我们密码密码,它变成fooLegolas哈希将是不同的,所以字典攻击将不成功。
希望有所帮助!
我假设你正在使用PHP — md5()函数,并且在$variables—前面加上variables—你可以试试看这篇文章Shadow Password HOWTO特别是第11段。
此外,你害怕使用消息摘要algorithm,你可以尝试真正的密码algorithm,比如mcrypt模块提供的algorithm,或者更强的消息摘要algorithm,比如提供mhash模块的algorithm(sha1,sha256和其他)。
我认为强大的信息摘要algorithm是必须的。 众所周知,MD5和SHA1存在碰撞问题。