PHP Security - проверка учетной записи пользователя, когда хешированный пароль сломан

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

Вот как я храню пароли в базе данных:

обычный текстовый пароль -> пароль хеша (я использую whirlpool, но любой метод будет практически работать)-> перемешать / перемешать хешированный пароль (с помощью функции str_shuffle()).

Я храню пароль пользователя в базе данных примерно так, чтобы убедиться, что база данных скомпрометирована, и злоумышленник не сможет восстановить взломанный пароль в базе данных. (Потому что как вы можете в некотором смысле перевернуть случайный текст, который используется в качестве хэша? - Хотя я уверен, что вы можете создать список возможностей, сравнив список хэшей, которые используют одни и те же символы.)

Я проверяю, верен ли пароль пользователя, введенный им в форме входа в систему (по сравнению со сломанным хешем в базе данных), путем подсчета отдельных букв + цифр (af & 0-9) в обеих строках / паролях, и проверяю, они совпадают, и если они это сделают, я предполагаю, что они правильно вошли в систему.

И еще раз, я хочу знать, насколько это безопасно, по вашему мнению, и как я могу улучшить его, чтобы сделать его приемлемым для практического использования. (Если возможно.) & Я также хотел бы сделать все возможное, чтобы избежать "обратимого" хэша. (т. е. идея создать свой собственный способ обеспечения совпадения паролей, я хочу сделать его более вероятным, чтобы полностью предположить, что злоумышленник не сможет перевернуть пароли в базе данных.

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


ДРУГАЯ ИНФОРМАЦИЯ:

1) Пароли хранятся с уникальными солями (поэтому не одна учетная запись имеет одну соль)

2) Соли паролей всегда меняются (каждый раз, когда успешный вход в систему происходит с учетной записью пользователя, он меняет соль пользователей в базе данных. Я делаю это, чтобы изменить хэш в базе данных, что приводит к менее частому конфликту паролей (надеюсь,) а также для предотвращения нежелательных пользователей использовать один и тот же неверный пароль несколько раз для входа в систему (если им удастся найти один, единственный способ добиться этого - грубое обращение или "угадывание", к которому уязвима любая система входа в систему).

Когда я говорю "коллизия паролей", я имею в виду малейший шанс того, что слова "привет" и "синий" будут иметь одинаковое количество символов (как я объяснил, я считаю отдельные символы + цифры и сравниваю их, чтобы предположить, что это правильный пароль)..)

3) Я также МОГУ БЫТЬ сохранить первые 3 знака / числа хешированного пароля без изменений str_shuffle, чтобы также помочь убедиться в правильности вводных слов. (Создав 2 проверки, 1) проверьте, имеют ли обе строки одинаковые ПЕРВЫЕ 3 ЧАСА / Числа и 2) Затем сравните количество символов в каждой строке. (Надеюсь сделать пароли коллизиями, опять же реже).

4) Очевидно, что будут добавлены другие меры безопасности (например, максимальное количество попыток входа в систему, капча и т. Д.), Чтобы помочь защитить от автоматического взлома, чтобы хакеру было сложнее найти возможный пароль или реальный пароль.

Я сделал успешный PoC из этого, и он работает как шарм, хотя мне еще предстоит протестировать PoC против атаки по словарю / грубой силы, чтобы увидеть вероятность коллизий паролей. & Как часто они.

Если я изложил много "бесполезной" информации, игнорируйте ее. Я просто стараюсь объяснить это разумно.

4 ответа

Это кажется ужасно неэффективным и небезопасным для меня.

В частности: столкновения. Вы упомянули это уже в Other Info.

Просто проверка количества символов в хешированном и зашифрованном виде позволяет вероятности столкновения пройти через крышу. Вы позволяете одному паролю быть действительным и для всех перестановок его хэша. Учитывая длину 128 символов в хэше вихря, это очень большое число.

Таким образом, в основном, позволяя это, вы позволяете потенциальному bruteforcer проверять много тысяч паролей одновременно, вводя один.

Они не получат постоянный доступ к системе, поскольку вы сказали, что меняете хэш после каждого входа в систему, но вероятность того, что они получат доступ ОДНАЖДЫ, существенно возрастает.

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

Если вы хотите сделать его более безопасным, просто используйте несколько итераций хеша. Сохраните хешированный пароль и количество хеш-итераций. Каждый раз, когда пользователь снова входит в хэш, сохраняйте его и увеличивайте количество итераций. Это в достаточной степени изменит хранимый хэш, не создавая слишком много криптографических недостатков.

Не балуйтесь с вашей идеей больше. Это небезопасно.

Существует только около двух способов защиты паролем, которые обеспечивают достаточный уровень защиты от взлома:

  1. Используйте аппаратный модуль безопасности, выполняющий что-то вроде HMAC-SHA1. Модуль является внешним оборудованием, внешний мир не знает внутреннего секрета (доступного только через физический доступ к модулю) внутри модуля, и без этого модуля сгенерированные хэши никогда не будут восстановлены. Выделенное оборудование с "быстрым" алгоритмом хеширования делает это жизнеспособным решением для множества проверок паролей. См. http://en.wikipedia.org/wiki/Hash-based_message_authentication_code для получения подробной информации.
  2. Используйте очень медленный алгоритм хеширования. Такие вещи, как "scrypt" или "bcrypt" будут выполняться очень медленно, что препятствует быстрому брутфорс-сканированию списка паролей по списку известных хэшей. В настоящее время PHP поддерживает только bcrypt.

Вы можете удивиться, почему вы должны использовать внешнее оборудование, инкапсулирующее секрет. Все просто: все, что доступно с машины, выполняющей хэш, может быть украдено. Кража секрета аналогична использованию одной и той же соли (или ее вообще не требуется) для всех ключей: в конечном итоге вы получаете "только" очень быстрый алгоритм хеширования со всеми известными компонентами и можете сразу же начать взламывать пароли.

Таким образом, если нет выделенного оборудования, единственным другим вариантом является алгоритм хэширования медленного пароля.

Есть решение для PHP: password_compat - это библиотека, которая переопределяет API хэширования паролей PHP для версий до PHP 5.5. Если вы уже используете 5.5, вы просто используете эти функции.

Ваша схема перетасовки сделает пароль менее безопасным. Сравнение количества экземпляров букв и цифр после тасования повышает вероятность того, что два человека имеют одинаковое значение пароля (как вы сказали, коллизия).

Повторное посоление - это то, что вы можете использовать. Каждый раз, когда пользователь успешно входит в систему, вы можете повторно ввести пароль и сохранить его снова. Это может быть даже лучше, если вы измените процедуру пароля PHP, чтобы использовать значение времени высокого разрешения, увеличивая уникальность. По сути, вы постоянно вращаете соль пароля. Вам нужно будет сохранить чистый пароль, сравнить его хэш с сохраненным, повторно посолить и хэшировать чистый пароль и сохранить снова.

Вывод криптографически сильной хеш-функции для всех намерений и целей уже псевдослучайный. Попытка добавить энтропию путем скремблирования ничего не дает. Он ничего не делает для того, чтобы сделать хеш менее "обратимым", поскольку единственный способ "обратить" хеш - это выбрать вход, хэшировать его, сравнивая с хешем; это то же самое, что вы должны делать при входе пользователя в систему, это то же самое, что и злоумышленник: изменение алгоритма сравнения не меняет эту основную операцию. (Как уже отмечалось, ваш ослабленный алгоритм сравнения на самом деле помогает злоумышленнику.)

Общепринятый способ решения этой проблемы уже достаточен:

  1. Убедитесь, что ваш ввод уникален, засолив его (псевдо) случайным шумом, это заставляет злоумышленника выполнять хэширование.
  2. Выберите медленный хеш (предпочтительно bcrypt или scrypt, с достаточно высоким коэффициентом стоимости, который делает возможным выполнение один раз, но невозможным для злоумышленника делать миллиарды раз), что делает его вычислительно невозможным для злоумышленника для подбора заставить хеш в своей жизни.

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

Другие вопросы по тегам