Как Linux узнает, что новый пароль похож на предыдущий?

145

Несколько раз я пытался изменить пароль пользователя на разных машинах Linux, и когда новый пароль был похож на старый, ОС жаловалась, что они слишком похожи.

Я всегда задавался вопросом, как система узнает об этом? Я думал, что пароль сохраняется как хеш. Означает ли это, что когда система может сравнить новый пароль на предмет сходства, старый пароль фактически сохраняется в виде простого текста?

Arkonix
источник
30
1-й выход: простой текст? нет. Если (!) Сохранено, вы сохраняете хэш и сравниваете его. В Linux, хотя он проверяет текущий пароль с новым паролем. ОБА предоставляются пользователем при смене паролей.
Rinzwind
42
@Rinzwind Но сравнение хешей не сработает, потому что разница в один символ должна привести к совершенно другому хешу
slhck
17
См. Также Facebook хранит пароли в виде простого текста? по информационной безопасности для других способов обнаружения сходства, учитывая только хэш старого пароля и открытый текст нового пароля (без старого текста для старого).
Боб
21
На самом деле вы можете проверить сходство между хэшированным старым паролем и открытым паролем. Просто сгенерируйте список паролей, похожих на новый, хешируйте их все и сравните полученные хеши со старым хешем паролей. Если есть совпадение, то это похоже.
BWG
2
@BWG: Это небольшое упрощение - современные схемы хэширования солят хеш, поэтому сначала вы должны извлечь соль из хэша старого пароля и убедиться, что вы используете эту соль для ваших паролей, похожих на новые. (Я указываю на это, потому что вполне возможно, что API не предоставит способ заставить определенную соль.)
Ульрих Шварц

Ответы:

156

Поскольку при использовании вам необходимо указывать как старый, так и новый пароль passwd, их можно легко сравнить в открытом тексте, в памяти, не записывая их где-нибудь на диске.

Действительно, ваш пароль хэшируется, когда он наконец сохраняется, но пока это не произойдет, инструмент, в котором вы вводите свой пароль, может, конечно, просто получить к нему доступ напрямую, как любая другая программа, может получить доступ к вещам, которые вы вводили на клавиатуре, когда он читал из STDIN.

Это особенность системы PAM, которая используется в фоновом режиме passwdинструмента. PAM используется в современных дистрибутивах Linux.

Более конкретно, pam_cracklibэто модуль для PAM, который позволяет отклонять пароли на основании нескольких недостатков, которые делают их очень уязвимыми.

Не только пароли, которые слишком похожи, могут считаться небезопасными. Исходный код имеет различные примеры того , что можно проверить, например , является ли пароль палиндром или то , что изменить расстояние между двумя словами. Идея состоит в том, чтобы сделать пароли более устойчивыми к атакам по словарю.

Смотрите также на pam_cracklibстраницу руководства.

slhck
источник
у вас есть идеи о том, «как» ваше объяснение соответствует аргументам, изложенным в моем ответе? Существуют ли два разных подхода, применяемых приложением «passwd», когда хост не поддерживает PAM? PS: Критики нет вообще. Мне просто интересно (как PAM, кстати, была моя первая догадка ... как раз перед тем, как поискать исходный код).
Дамиано Верзулли
27
Еще более тревожат правила корпоративного пароля, которые предупреждают вас, если вы использовали такой же или похожий пароль среди любых из последних четырех.
Ник Т
4
@NickT Как это (обязательно) беспокоит - они не могли просто сохранить ваши последние 4 хэша, а затем сравнить каждый из них с вашим новым предложенным так же, как этот вопрос?
neminem
1
@neminem "... или похожий"
Ник Т
1
@NickT Ах, честно, потому что в данном конкретном случае вы сравниваете данные со «старым паролем», который пользователь вводит для изменения пароля, а не с сохраненным хешем. Тем не менее, вы можете гипотетически использовать метод BWG, опубликованный в комментарии, по крайней мере, для проверки действительно простых изменений (замена одного символа, добавление / удаление одного символа и т. Д.).
neminem
46

По крайней мере, в моем 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 */
оборота Дамиано Верзулли
источник
9
Это длинный ответ, который, похоже, не дает прямого ответа на вопрос о том, как он может сравниваться со старым паролем при хэшировании паролей.
jamesdlin
10
@jamesdlin: как указано в комментарии Rinzwind к исходному вопросу, хеши не играют никакой роли в этом вопросе: когда вы вводите команду «passwd» для смены пароля, вы должны предоставить как «старый», так и «новый» пароль. Таким образом, у кода «passwd» нет проблем при сравнении / проверке обоих паролей одновременно (в чистом виде, без хеширования).
Дамиано Верзулли
3
@DamianoVerzulli Тем не менее, это не решает вопрос. Вопрос был не в том, «какой код на C вы используете, чтобы определить, похожи ли две строки»; это точно так же для паролей, как и для всего остального. Дело в том , пароли , что делает их интересным является то , что они никогда не хранятся в незашифрованном виде , и это то , что вопрос касается. Это отвечает «какие критерии используются и как это делается в C», но это слишком долго для «каких критериев» и «как бы я сделал это в C» - это вопрос SO, а не вопрос SU.
cpast
7
@DamianoVerzulli И тот факт, что passwdзапрашивает как старые, так и новые пароли, является ответом . Остальная часть этого ответа не имеет отношения к делу.
Джеймсдлин
3
+1 за и крайне актуальный и интересный ответ! Приятно видеть, что реальный код, сравнивающий пароль, фактически работает с открытым текстом и, как и ожидалось, не с хешем.
Нико
36

Ответ гораздо проще, чем вы думаете. На самом деле, это почти квалифицируется как магия, потому что как только вы объясните хитрость, она исчезнет:

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

Password changed successfully

Он знает, что ваш новый пароль похож ... Потому что вы ввели старый пароль всего минуту назад.

Корт Аммон
источник
2
"... или конфетка."
Ник Т
1
Глупый кролик, трикс для детей!
iAdjunct
1
Чего он не объясняет, так это когда он знает ваши прошлые n паролей :) «Пароль был использован слишком недавно», что не позволяет менять те же самые пароли в корпоративной среде.
Юха Унтинен
3
@Juha Untinen: Это правда, но это можно сделать, просто запомнив последние N хешей. Поймать «такой же, как N-й пароль» легко, это « похоже на N-й пароль», что сложно. Насколько мне известно, эти системы проверяют только сходство с последним паролем и одинаковость с последним N. Если они проверяют сходство с последним N ... это действительно интересный трюк, не правда ли! Я понятия не имею, как они это сделают.
Cort Ammon
7

Хотя другие ответы верны, стоит упомянуть, что вам не нужно указывать старый пароль, чтобы это работало!

Фактически, можно создать группу паролей, аналогичную введенному вами новому паролю, хэшировать их, а затем проверить, совпадает ли какой-либо из этих хэшей со старым. Если это так, то новый пароль оценивается как старый! :)

Муравей
источник
2
Хотя это действительно средство для достижения этой цели (и используется многими веб-сайтами), в данном случае это не то, что происходит.
Брайан С
Это ловкий трюк! Чуть более вычислительно, но умно!
Cort Ammon
Вы должны по крайней мере дать некоторую оценку того, сколько похожих паролей нужно будет сгенерировать, чтобы иметь значимую проверку или ссылку на внешний ресурс. В противном случае это просто идея возможной альтернативы, а не обоснованный ответ.
Хайд
@hyde, который зависит от критериев, о которых кто-то может подумать. Для меня пароли похожи, если было добавлено / удалено / изменено не более 3 символов. Таким образом, это 62 хеша для каждого символа (и если мы используем только алфавитно-цифровые символы), умноженного на 3 от длины пароля ( n), то есть 62 * (n!)/(6 * (n - 3)!), что равно 13540 для пароля длиной 12 символов. Но если кто-то думает о чем-то другом, уравнение бесполезно, так зачем беспокоиться?
Killah
Глупый ответ, но, тем не менее, понимание. Почему тупой? 1. Вам нужно создать невообразимое количество хэшей. 2. Такая настройка может ослабить безопасность исходного пароля. Если кто-то получит хеши всех похожих паролей вместо одного хеша, им будет намного проще взломать его.
Рок Краль
5

Один аспект не был покрыт: история паролей. Некоторые системы поддерживают это. Для этого он хранит историю паролей и шифрует их с помощью текущего пароля. Когда вы меняете свой пароль, он использует «старый» пароль для расшифровки списка и проверки. И когда он устанавливает новый пароль, он сохраняет список (снова) зашифрованный ключом, полученным из нового пароля.

Вот как remember=Nработает в PAM (хранится в /etc/security/opasswd). Но также Windows и другие поставщики Unix предлагают аналогичные функции.

Экес
источник