我一直想知道,如何系统知道吗?我以为密码另存为哈希。这是否意味着当系统能够比较新密码的相似性时,旧密码实际上被保存为纯文本吗?
#1 楼
由于使用passwd
时需要同时提供旧密码和新密码,因此可以轻松地以明文形式在内存中比较它们,而无需将它们写在驱动器上。 实际上,密码在最终存储时会被散列,但是在那之前,您输入密码的工具当然可以直接访问它,就像其他程序可以访问您在密码中输入的内容一样从STDIN读取键盘时。
这是PAM系统的功能,用于
passwd
工具的背景。现代Linux发行版使用PAM。 更具体地说,
pam_cracklib
是PAM的模块,它允许基于一些弱点拒绝密码,这些弱点会使它们非常容易受到攻击。不仅仅是密码太相似,可以认为是不安全的。源代码具有可以检查的内容的各种示例,例如密码是回文密码,还是两个单词之间的编辑距离。这样做的目的是使密码更能抵抗字典攻击。
另请参见
pam_cracklib
联机帮助页。评论
您对“如何”解释与我的回答中报告的论点相称有想法吗?当主机不支持PAM时,“ passwd”应用程序采用两种不同的方法吗?附注:完全没有批评家。我只是在想(作为PAM,BTW,这是我的第一个猜测……只是在复制源代码之前)。
–Damiano Verzulli
2014-12-27 19:38
更令人不安的是企业密码规则,如果您在前四个密码中的任何一个中使用了相同或相似的密码,就会提醒您。
–尼克T
2014年12月30日,下午3:58
@NickT(有必要)如何打扰-他们不能只保存您的最后4个哈希,然后以与该问题相同的方式将每个哈希与您提议的新哈希进行比较吗?
– neminem
2014年12月30日17:14
@neminem“ ...或类似的”
–尼克T
2014年12月30日在17:20
@NickT啊,很公平,因为在这种情况下,您要与用户输入的用于更改密码的“旧密码”进行比较,而不是与保存的哈希进行比较。尽管如此,您仍然可以假设使用注释中发布的BWG方法,至少检查真正简单的更改(一个字符替换,一个字符添加/删除等)。
– neminem
2014年12月30日在17:34
#2 楼
至少在我的Ubuntu中,出现以下情况时会出现“太相似”消息:“ ...超过一半的字符是不同的字符....”(有关详细信息,请参见下文)。感谢PAM的支持,正如@slhck答案中明确说明的那样。对于其他不使用PAM的平台,在以下情况下会出现“太相似”消息:的字符是不同的...。”(有关详细信息,请参见下文)
要自己进一步检查此语句,可以检查源代码。方法如下。
passwd程序包中包含“ passwd”程序:
verzulli@iMac:~$ which passwd
/usr/bin/passwd
verzulli@iMac:~$ dpkg -S /usr/bin/passwd
passwd: /usr/bin/passwd
我们正在处理开源技术,我们可以不受限制地访问源代码。获得它的方法很简单:
verzulli@iMac:/usr/local/src/passwd$ apt-get source passwd
之后,很容易找到相关的代码片段:
verzulli@iMac:/usr/local/src/passwd$ grep -i -r 'too similar' .
[...]
./shadow-4.1.5.1/NEWS:- new password is not "too similar" if it is long enough
./shadow-4.1.5.1/libmisc/obscure.c: msg = _("too similar");
快速检查一下“ obscure.c”就可以了(我只剪切并粘贴了相关代码):
static const char *password_check (
const char *old,
const char *new,
const struct passwd *pwdp)
{
const char *msg = NULL;
char *oldmono, *newmono, *wrapped;
if (strcmp (new, old) == 0) {
return _("no change");
}
[...]
if (palindrome (oldmono, newmono)) {
msg = _("a palindrome");
} else if (strcmp (oldmono, newmono) == 0) {
msg = _("case changes only");
} else if (similar (oldmono, newmono)) {
msg = _("too similar");
} else if (simple (old, new)) {
msg = _("too simple");
} else if (strstr (wrapped, newmono) != NULL) {
msg = _("rotated");
} else {
}
[...]
return msg;
}
所以,现在,我们知道有一个“相似”功能,该功能基于旧的和新的检查两者是否相似。以下是代码段:
/*
* more than half of the characters are different ones.
*/
static bool similar (const char *old, const char *new)
{
int i, j;
/*
* XXX - sometimes this fails when changing from a simple password
* to a really long one (MD5). For now, I just return success if
* the new password is long enough. Please feel free to suggest
* something better... --marekm
*/
if (strlen (new) >= 8) {
return false;
}
for (i = j = 0; ('#include <config.h>
#ifndef USE_PAM
[...lots of things, including all the above...]
#else /* !USE_PAM */
extern int errno; /* warning: ANSI C forbids an empty source file */
#endif /* !USE_PAM */
' != new[i]) && ('q4312078q' != old[i]); i++) {
if (strchr (new, old[i]) != NULL) {
j++;
}
}
if (i >= j * 2) {
return false;
}
return true;
}
我还没有审查过C代码。我仅限于信任函数定义之前的注释:-)
在结构化的“ obscure.c”文件中定义了PAM和NON-PAM感知平台之间的区别。像:
q4312078q
评论
这是一个很长的答案,似乎并不能直接回答以下问题:当密码散列时,如何将其与旧密码进行比较。
–詹姆士林
2014-12-27 21:47
@jamesdlin:正如Rinzwind对原始问题的注释中所述,哈希在此问题上不起作用:当您发出“ passwd”命令更改密码时,您需要同时提供“旧”和“新”密码。因此,“ passwd”代码一次比较/检查两个密码(以清晰的形式;完全没有哈希值)完全没有问题。
–Damiano Verzulli
2014年12月27日22:10
@DamianoVerzulli不过,这并没有真正解决这个问题。问题不是“您使用什么C代码来判断两个字符串是否相似”;密码与其他所有密码完全相同。关于密码的事情使它们变得有趣,那就是它们永远不会以明文形式存储,这就是问题所在。这回答了“使用什么标准以及如何在C中完成”,但是对于“什么标准”和“我将如何在C中进行此工作”这太长了,这是一个SO问题,而不是SU问题。
–cpast
2014-12-27 22:55
@DamianoVerzulli passwd要求输入新旧密码的事实就是答案。此答案的其余部分无关紧要。
–詹姆士林
2014-12-28 5:18
+1是极为相关且有趣的答案!很高兴看到比较密码的实际代码实际上适用于纯文本,而不是按预期的方式适用于哈希。
–nico
2014-12-29 20:15
#3 楼
答案比您想像的要简单得多。实际上,它几乎可以看作是魔术,因为一旦您解释了这个窍门,它就消失了:旧的片刻就在眼前。评论
“……还是糖果。”
–尼克T
2014年12月30日17:39
傻兔子,特里克斯是给孩子们的!
– iAdjunct
2014年12月30日17:55
它不能解释的是什么时候知道您过去的n个密码:)“密码最近使用过”,这可以防止在公司环境中交换相同的几个密码。
– Juha Untinen
2014年12月31日9:48
@Juha Untinen:的确如此,但是只要记住最后的N个哈希即可解决。捕获“与第N个密码相同”很容易,而捕获“与第N个密码类似”则很困难。据我所知,这些系统仅检查与最后一个密码的相似性,以及与最后一个N的相似性。如果它们确实检查与最后一个N的相似性,那么这是一个非常有趣的技巧,不是吗!我不知道他们会怎么做。
–Cort Ammon
2014年12月31日在17:34
#4 楼
尽管其他答案是正确的,但值得一提的是您无需提供旧密码即可使用此密码!实际上,一个人可以生成类似于该密码的一堆密码。您提供的新密码,对其进行哈希处理,然后检查这些哈希值是否与旧的匹配。如果是这种情况,则将判断新密码与旧密码相似! :)
评论
虽然这确实是实现这一壮举的一种方法(许多网站都在使用它),但这并不是这种情况。
– Brian S
2014年12月29日15:43
那真是个绝招!一点点计算密集,但很聪明!
–Cort Ammon
2014年12月29日18:55
您至少应该估计一下要进行有意义的检查或链接到外部资源,需要生成多少个相似的密码。否则,这仅仅是可能的替代方案的想法,而不是充分的答案。
–氢化物
2014年12月31日7:41
@hyde取决于某人可能想到的标准。对我来说,如果添加/删除/修改的字符数最多为3个,则密码相似。因此,每个字符有62个散列(如果我们仅使用字母数字)是密码长度(n)乘以3的组合,即62 *(n!)/(6 *(n-3)!),等于13540 12个字符长的密码。但是,如果有人想到了不同的东西,那么这个方程是没有用的,那为什么还要麻烦呢?
–基拉
2014年12月31日14:20
愚蠢的答案,但有见地。为什么傻? 1.您将不得不生成数量无法想象的哈希。 2.这样的设置会削弱原始密码的安全性。如果有人获得了所有相似密码的哈希值,而不仅仅是一个哈希值,那么他们将有更多的时间来破解它。
– Rok Kralj
15年1月3日在20:58
#5 楼
一方面未涵盖:密码历史记录。一些系统支持此功能。为此,它保留了密码的历史记录,并使用当前密码对其进行加密。更改密码时,它将使用“旧”密码来解密列表并进行验证。并且,当设置新密码时,它会再次保存使用从新密码派生的密钥加密的列表。,这就是
remember=N
在PAM(存储在/etc/security/opasswd
中)中的工作方式。但是Windows和其他Unix供应商也提供类似的功能。
评论
第一关:纯文字?没有。如果(!)保存,则保存哈希并比较哈希。在Linux中,它会使用新密码检查当前密码。两者都由用户在更改密码时提供。@Rinzwind但是比较散列将不起作用,因为一个字符的差异将导致完全不同的哈希值
另请参阅Facebook是否存储纯文本密码?关于信息安全的其他检测相似性的方法,仅给出了旧密码的哈希值和新密码的纯文本(旧密码无明文)。
您实际上可以测试散列的旧密码和纯文本新密码之间的相似性。只需生成与新密码相似的密码列表,对所有密码进行哈希处理,然后将产生的哈希值与旧密码哈希进行比较即可。如果有匹配项,则类似。
@BWG:这有点过分简化了-当前的哈希方案对哈希值加盐,因此首先您要从旧的密码哈希中提取盐,并确保将盐用于新密码。 (我指出这一点是因为API可能不会公开强制使用特定盐的方法。)