題 Linux如何知道新密碼與前一個密碼類似?


有幾次我嘗試在各種Linux機器上更改用戶密碼,當新密碼與舊密碼相似時,操作系統抱怨它們太相似了。

我一直想知道,系統如何知道這一點?我以為密碼保存為哈希。這是否意味著當系統能夠比較新密碼的相似性時,舊密碼實際上是保存為純文本?


140
2017-12-27 17:22


起源


第一關:純文本?沒有。如果(!)保存,則保存哈希值並比較哈希值。在Linux中,它使用新密碼檢查當前密碼。更改密碼時,用戶提供兩者。 - Rinzwind
@Rinzwind但是比較哈希將不起作用,因為一個字符的差異應該導致完全不同的哈希 - slhck
也可以看看 Facebook存儲明文密碼嗎? 上 信息安全 用於檢測相似性的其他方法僅給出舊密碼的散列和新密碼的明文(舊的沒有明文)。 - Bob
您實際上可以測試散列舊密碼和純文本新密碼之間的相似性。只需生成一個類似於新密碼的密碼列表,將它們全部哈希,然後將生成的哈希值與舊密碼哈希值進行比較。如果有任何匹配,則類似。 - BWG
@BWG:這有點過於簡單化了 - 當前的哈希方案會使哈希值變得很糟糕,所以首先你要從舊的密碼哈希中提取鹽,並確保你使用那個鹽來獲得類似的新密碼。 (我指出這一點,因為API可能不會暴露強制特定鹽的方法。) - Ulrich Schwarz


答案:


既然你需要供應舊的  使用時的新密碼 passwd,它們可以很容易地在明文,內存中進行比較,而無需在驅動器上的某處寫入。

事實上,當你的密碼最終存儲時,你的密碼會被哈希化,但在此之前,你輸入密碼的工具當然可以直接訪問它,就像任何其他程序可以訪問你在STDIN上讀取時在鍵盤上輸入的內容一樣。

這是一個特點 PAM系統 在背景中使用 passwd 工具。 PAM由現代Linux發行版使用。

進一步來說, pam_cracklib 是一個PAM模塊,允許根據幾個弱點來拒絕密碼,這些弱點會使它們非常容易受到攻擊。

這不僅僅是密碼太過相似而且可以被認為是不安全的。該 源代碼  有各種可以檢查的例子,例如:密碼是回文還是兩個單詞之間的編輯距離。這個想法是使密碼更能抵抗字典攻擊。

也可以看看 pam_cracklib 手冊頁。


155
2017-12-27 19:27



你有什麼想法,你的解釋是否適合我在答案中報導的論點?當主機是“passwd”應用程序時,是否有兩種不同的方法 不 PAM感知? P.S。:沒有批評者。我只是想知道(作為PAM,順便說一下,這是我的第一個猜測......就在點擊源代碼之前)。 - Damiano Verzulli
更令人不安的是公司密碼規則,如果您在過去四年中的任何一個中使用相同或類似的密碼,則會提醒您。 - Nick T
@NickT那是如何(必然)令人不安的 - 他們不能只保存你最後的4個哈希值,然後以與這個問題相同的方式將每個哈希值與你提出的新哈希值進行比較? - neminem
@neminem“......或類似的” - Nick T
@NickT啊,公平地說,因為在這種特殊情況下,您要與用戶輸入的用於更改密碼的“舊密碼”進行比較,而不是針對已保存的哈希。還是你 可以 假設使用BWG中發布的註釋方法,至少檢查真正簡單的更改(一個字符替換,一個字符添加/刪除等)。 - neminem


至少在我的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; ('\0' != new[i]) && ('\0' != old[i]); i++) {
            if (strchr (new, old[i]) != NULL) {
                    j++;
            }
    }

    if (i >= j * 2) {
            return false;
    }

    return true;
}

我還沒有看過C代碼。我在函數定義之前限制自己信任評論:-)


PAM和NON-PAM感知平台之間的區別在“obscure.c”文件中定義,該文件的結構如下:

#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 */

46
2017-12-28 18:14



這是一個很長的答案,似乎沒有直接回答當密碼為哈希時如何與舊密碼進行比較的問題。 - jamesdlin
@jamesdlin:正如Rinzwind對原始問題的評論,哈希所做的那樣 不 在這個問題上扮演任何角色:當您發出“passwd”命令來更改密碼時,您需要提供“舊”和“新”密碼。所以“passwd”代碼在同時比較/檢查兩個密碼時都沒有問題(以清晰的形式;根本沒有哈希)。 - Damiano Verzulli
@DamianoVerzulli然而,這並沒有真正解決這個問題。問題不是“你用什麼C代碼判斷兩個字符串是否相似;”對於密碼和其他任何東西完全相同。事情 密碼 使它們變得有趣的是它們從未以明文形式存儲,這就是問題所要求的。這回答“使用什麼標準以及如何在C中完成”,但是對於“什麼標準”和“我將如何在C中執行此操作”的時間太長是一個問題,而不是SU問題。 - cpast
@DamianoVerzulli和事實 passwd 要求新密碼和新密碼 是答案。這個答案的其餘部分是無關緊要的。 - jamesdlin
+1為和非常相關和有趣的答案!很高興看到比較密碼的實際代碼實際上在明文上工作,並且如預期的那樣,不在哈希上。 - nico


答案遠比你想像的要簡單得多。事實上,它幾乎有資格作為魔法,因為一旦你解釋了這個技巧,它就會消失:

$ passwd
Current Password:
New Password:
Repeat New Password:

Password changed successfully

它知道你的新密碼是類似的...因為你剛才輸入了舊密碼。


37
2017-12-29 13:41



“......還是糖果。” - Nick T
傻兔子,trix適合孩子們! - iAdjunct
它沒有解釋的是它何時知道你過去的n個密碼:)“密碼最近已被使用”,這可以防止在公司環境中交換相同的幾個密碼。 - Juha Untinen
@Juha Untinen:這是真的,但這可以通過簡單地記住最後的N個哈希來處理。捕獲“與第N個密碼相同”很容易,它的“類似 到第N個密碼“很難。據我所知,這些系統只檢查與最後一個密碼的相似性,與最後一個N的相同性。如果他們確實檢查了與最後一個N的相似性...這真的很有趣訣竅現在,不是嗎!我不知道他們是怎麼做到的。 - Cort Ammon


雖然其他答案是正確的,但值得一提的是,您無需提供舊密碼即可使用!

實際上,可以生成一堆密碼,類似於您提供的新密碼,哈希它們,然後檢查這些哈希是否與舊密碼相匹配。如果是這種情況,則判斷新密碼與舊密碼類似! :)


8
2018-01-02 11:06



雖然這確實是實現這一壯舉的一種手段(並且被許多網站使用),但這並不是在這種情況下發生的事情。 - Brian S
這是一個巧妙的伎倆!一點點計算密集,但聰明! - Cort Ammon
您至少應該估計需要生成多少類似密碼才能進行有意義的檢查或鏈接到外部資源。否則,這只是一個可能的替代方案的想法,而不是一個經證實的答案。 - hyde
@hyde取決於某人可能會想到的標準。對我來說,如果添加/刪除/修改了最多3個字符,則密碼類似。因此,每個角色的62個哈希(如果我們只使用字母數字),則是密碼長度的3個組合(n),這是 62 * (n!)/(6 * (n - 3)!),等於12個字符長密碼13540。但是,如果有人想到不同的東西,這個等式是無用的,那麼為什麼要這麼麻煩呢? - Killah
愚蠢的答案,但仍然是一個洞察力。為什麼這麼傻?你必須生成一個難以想像的哈希值。 2.這樣的設置會削弱原始密碼的安全性。如果某人獲得了所有類似密碼的哈希值而不是一個哈希值,那麼他們就有更容易破解它的時間。 - Rok Kralj


未涉及一個方面:密碼歷史記錄。有些系統支持這一點。為此,它會保留密碼歷史記錄並使用當前密碼對其進行加密。當您更改密碼時,它使用“舊”密碼來解密列表並進行驗證。當它設置一個新密碼時,它會確保(再次)使用從新密碼派生的密鑰加密列表。

這是怎麼回事 remember=N 適用於PAM(存儲在 /etc/security/opasswd)。但Windows和其他Unix廠商也提供類似的功能。


4