Pull to refresh

Comments 44

Без описания PBKDF2, bcrypt (хотя упоминание есть), scrypt, Argon2 пост выглядит неполным


Ему неизвестна глобальная соль, поэтому ее придется брутить.

Но ещё есть вариант, когда конфиг с солью тоже сливается через какую-нибудь RCE-уязвимость (или даже тупо по недосмотру с неправильно настроенными правами на файл, пару раз и на такое натыкался)

Не сказано про методики на уровне архитектуры — создание небольших микросервисов с задачами "регистрация/логин/удаление", аудит которых прост и дёшев, а выкачивание базы хешей соответственно требует взлома микросервиса, доступного извне, и постоянных запросов к этому микросервису авторизации (привет сетевым экранам и эвристическому анализу трафика между микросервисами). Плюс — hash blinding каким нибудь hmac перед внесением в базу с хранением ключа от блиндинга в HSM.


meh.

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

Очень плохо, что в 2018 году это все еще первая идея.
В мире .net есть такая штука как Identity. Там сразу и хранение и изменение и бан. Рекомендую обратить внимание, если гвоздями не прибиты к php.
Это не первая идея в 2018 году, это первая идея исторически.
Еще в четырнадцатом году глобальную соль раскритиковали в пух и прах. Например Как испортить безопасность паролей, следуя советам с Хабра. Правда там глобальную соль почему-то называют перцем. А ведь злоумышленник вообще может быть сотрудником и иметь доступ и к базе и к исходному коду.

В то же время есть усовершенствованный вариант хэширования хэша: hash(перец+hash(pass+соль)). Где соль уникальна для каждого пользователя, а перец — для каждой попытки авторизации, и выдается сервером.

Гм, а как ваш "усовершенствованный вариант" применим к хранению в БД?

Одним из требований к хэш-функциям же является быстрота выполнения.

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

Если уж говорить про php — то из-за безалаберного отношения к паролям в ядро давно уже включили обёртку password_hash. И использовать надо именно это.
Строго говоря, все же есть требованиек быстроте: она не должна быть слишком быстрой.
Это если говорить уже применительно к паролям, а не вообще о хэшировании. А так то хеши применяются много где и много где уместно смещение в сторону производительности. Контроль целостности файлов, например.
Зачем вообще хранить пароли? Давным давно уже придумали SRP-6a

Несколько дополнений.


  1. Про соль не сказано, почему же она мешает построить радужные таблицы. Тут все очень просто, соль — это удлинитель пароля. Чем длиннее пароль, тем больше ресурсов требует построение таблиц… вплоть до полной невозможности их построить на существующем железе. То, что эта "часть пароля" открыта — ничего не меняет, ибо она случайна, а значит радужные таблицы нужно строить для всех вариантов.


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

Ну и 3. По поводу придумывания своих алгоритмов, хешей от хешей и т.п. Не делайте так. В криптографии много нюансов, о которых вы не знаете. Например, Timing attack. Используйте проверенные инструменты, предназначенные именно для хеширования и проверки паролей.

Тут все очень просто, соль — это удлинитель пароля.
Красивый бред, Вы сами до этого дошли или кто-то подсказал? Не говорите так больше при людях… Учитывая фиксированную длину выходной последовательности и возможность коллизии с прообразом произвольной длины (не обязательно тоже большой) этот удлинитель можно было бы засунуть очень далеко и глубоко. Соль изначально предназначалась для защиты от простого поиска повторений прообразов (слили базу, узнали/угадали/перебрали 1 простой пароль, а потом выборкой или визуальным осмотром нашли кучу коллег по несчастью для первого бедолаги) с чем она успешно справляется по сей день.

Видимо вы слишком молоды, что бы знать о радужных таблицах.

Видимо, Вы учили криптографию по Википедии.

Говорить о криптографии с человеком, говорящим о подборе пароля через коллизии? Смешно.

Не смешнее, чем говорить о криптографии с домохозяйкой и любителем «удлинителей». И замечу, что ни слова про подбор паролей в предложении о коллизиях не было… Хотя вы уже сами дали себе верную оценку:
В криптографии много нюансов, о которых вы не знаете.

Ну вы же сами сказали, что длинная соль плохо, ибо "возможность коллизии". Но, видимо, вы совсем не это имели ввиду, а что имели, то не в виду ;) Видимо вас волнует вероятность коллизии… или нет? Уж объяснитесь.


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

Ну вы же сами сказали, что длинная соль плохо, ибо «возможность коллизии».
Интересный плод Вашего воображения. Такого в мою голову даже придти не могло… Я говорил, что ОЦЕНКА соли, как удлинителя — мимо темы. И я ни как не оценивал плоха длинная соль или хороша.
Конкретно имелось ввиду, что добавление соли несёт не тупо «удлинительный» характер, а увеличивает энтропию. И поэтому говорить «с солью длиннее! А значит лучше» — бред, учитывая, что хеш-функция в итоге свернёт, что 5, что 25 символов — ей без разницы. И не гарантируется, что именно вот к этим 25 нет коллизии, скажем, с прообразом гораздо меньшей длины. И поэтому оценка длины прообраза (с солью или без) практически ни какого смысла не имеет (ну за исключением защиты от тупого перебора (полного или по словарю).
Конечно длина увеличится — это факт. Но это не ставилось целью в идеи подсаливания хешей. Повторяю — в первую очередь это защита от простого поиска повторений прообразов. Всё остальное — следствия.

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


"Маскирование" одинаковых паролей — вторая задача.


А коллизии тут вообще отношения не имеют. Не ищут коллизии.

hmac384 или sha384(пароль+глобальное чтонить). Про потери перфоманса… только на тестах в вакууме.

Разве многократное хеширование не увеличивает вероятность коллизий?

Многократное хэширование увеличивает вероятность коллизий, но это не критично и многие его используют.
Об этом можно прочитать здесь: habr.com/post/100301

Всегда интересовала эта тема. Спасибо за ссылку.

Реально хэшируют 2^8 раз подряд? О_о
Это действительно помогает?

Я для своего сервиса сделал просто хэш(индивидуальная_соль+хэш(хэш(имя_пользователя)+хэш(пароль_пользователя)))
Неужели этого недостаточно?

Смотря какой хэш. Но, подозреваю, такой, что будет перебираться на хорошем GPU очень быстро.


Для сравнения: в Django по умолчанию используется PBKDF2, в котором SHA256-хэш хэширует 150000 (прописью: сто пятьдесят тысяч) раз подряд

Чтобы на GPU не перебрали, очевидно же :)


Я тут по случайному совпадению запустил перебор одного md5-хэша за пару дней до этого поста — на дохлом ноутбучном GPU. 8 и 9 символов уже перебраны, 10 символов переберутся через полтора месяца. Если обзавестись хотя бы двумя хорошими нвидиями, можно будет и 10 символов за пару дней перебрать) И это если не вспоминать пришедшие из мира криптовалют ASIC и FPGA, которые заточены именно для такого перебора (только в контексте всяких там блокчейнов, но по сути то же самое).


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

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


Только если знает алгоритм конкатенации промежуточных строк, да?

Безопасность через неясность это плохо, стоит автоматически предполагать, что вместе с базой слит и код сайта, в котором есть этот алгоритм (к тому же мне самому доводилось сливать код сайтов пару раз, хех)

А если не сайт, а сервер игры? Хостящийся на амазоне.

Извиняюсь, я просто в теме профан, но в качестве хобби пилю клиент-серверную игру, и вот как раз недавно делал систему авторизации)

А в чём принципиальная разница-то? С точки зрения сливов сервер игры тоже не обязательно безопасен и теоретически может обеспечить слив через какую-нибудь дырку. Разница разве что в нагрузке алгоритма на сервер, но у PBKDF2 даже с 150000 итераций нагрузка всё равно небольшая — это не какой-нибудь Argon2, который придуман специально чтобы выжирать и проц, и оперативку)) (а придуман он тоже именно для того, чтобы затруднить перебор на GPU)


Ну или можно включить режим неуловимого Джо и заявить что-то вроде «да кому нахрен нужен этот мой сервер игры, никто ничего подбирать не будет». Именно по этому принципу на двух моих старых сайтах до сих пор используются несолёные md5 и sha1 :D

Спасибо большое, изучу тему поглубже)

Хотя с другой стороны vladbarcelo в комментах выше предлагает вынести аутентификацию в микросервис, и это в принципе может немного защитить как базу, так и алгоритм. Но зачем, когда можно просто взять хороший алгоритм, который достаточно надёжен, даже если он всем известен? Тот же PBKDF2 хотя бы

никак не затруднят перебор

Разница очевидна если конечная цель подобрать пароли пользователей. Сравните:
ХЕШ("12345") -> нашли 29 пользователей с таким паролем.
ХЕШ("12345" + ИНДИВ.СОЛЬ) -> нашли 1 пользователя с таким паролем. Но ещё нужно обнаружить 28 пользователей с таким же паролем, но другим итоговым хешем.
Всё так, но если в качестве хэша используется простой md5 или типа того, то точно так же перебрать остальных пользователей займёт миллисекунды, даже если их миллионы) А ещё это всё будет не иметь значения, если целью является подбор пароля одного конкретного пользователя или поиск наибольшего числа пользователей с паролями вида 123456 (перебрать всех по словарю не так уж долго даже с солью)
Вы опять не уловили разницу. У вас есть словарь из 1000 слов и миллион пользователей. В одном случае для полного перебора надо сгенерировать 1000 хешей, в другом 1.000.000.000 (миллиард Карл!).
Моя ноутбучная видеокарта считает 2.000.000.000 md5-хэшей в секунду. Два миллиарда в секунду, Карл! Ноутбучная, Карл!

Чтобы вычислительную сложность повысить.

Интересно, если хранить в БД не соленые многораундные хэши, а зашифрованную пару соль+хэш пароля. Можно также делать многораундное шифрование. Можно даже шифровать ассиметрично и хранить приватный ключ рядом с БД.
Плюсы: 1) асиметричный шифр более ресурсоемкий, чем любой хэш, и плохо брутится. 2) По определению нет радужных таблиц. 3) Даже, если сольют базу и приватный ключ, в лучшем случае получат хэш пароля и соль

Что-то я не понял, если при сливе всё равно «получат хэш пароля и соль», то какой смысл в шифровании?
Во-1х, слить нужно и БД и приватный ключ, что гораздо-гораздо сложнее. Например, ключ может располагаться на физическом токене с крипточипом. Во-2х, даже если это каким-то образом удастся, остается последний эшелон защиты — многораундное шифрование соленого хэша с его же солью. Ассиметричный шифр на GPU уже не погоняешь, таблицы не подходят, остается только жесткий брут на CPU.

По-моему намного проще будет просто вынести всю аутентификацию в микросервис без всяких шифрований, как vladbarcelo предлагал. А уж микросервис может располагаться хоть на условном «токене», хоть вообще в другой стране — фиг сольёшь, даже если основной сайт сольют целиком

Не спорю, но тут вроде статья и обсуждение про способы хранения паролей в БД. А так-то, конечно, можно придумать что угодно другое.
Sign up to leave a comment.