Полагаю, на исходе первой четверти 21-го века все уже отлично понимают, что пароли пользователей к аккаунтам в онлайн-сервисах представляют собой невероятно ценную информацию и, следовательно, их защита играет ключевую роль в обеспечении конфиденциальности и безопасности данных. Несмотря на это, до сих пор не все организации хранят эти пароли должным образом.
В этом посте поговорим о том, как не стоит хранить пароли пользователей и какие методы применяют сервисы, которые всерьез относятся к безопасности.
Неправильный способ: хранение паролей в открытом виде
Самый простой способ — это запись паролей просто в базу данных в незашифрованном виде. Соответственно, при попытке пользователя аутентифицироваться остается только сравнить вводимую им цепочку символов с тем, что хранится у вас в базе.
В этом случае есть риск того, что злоумышленники смогут тем или иным способом украсть эту базу данных. Например, с помощью эксплуатации каких-либо уязвимостей в используемом для хранения данных ПО. Другой вариант — таблицу с паролями может украсть недобросовестный сотрудник с высоким уровнем доступа. Или для кражи паролей могут быть использованы утекшие или перехваченные учетные данные сотрудника. В общем, вариантов того, что может пойти не так, тут масса. Главная мысль: если хранить какие-то данные в открытом виде, то на них рано или поздно кто-то может наложить руки.
Способ чуть лучше: зашифрованные пароли
А что если хранить пароли в зашифрованном виде? На первый взгляд мысль неплохая, но на практике она не очень-то работает. Ведь если в базу данных будут сохраняться зашифрованные пароли, то для сличения с комбинациями символов, вводимыми пользователями, их придется каждый раз расшифровывать.
Следовательно, где-то недалеко от паролей должен храниться и ключ шифрования. А раз так, то в результате взлома этот ключ может попасть в руки злоумышленников одновременно с базой паролей. И это лишает всю затею смысла: преступникам удастся быстренько эту базу расшифровать и в их руках окажутся пароли в открытом виде — то есть мы оказываемся в том же месте, с которого начинали.
Как полушутливо говорят криптографы, шифрование не решает проблему обеспечения конфиденциальности данных, оно всего лишь превращает ее в проблему безопасного хранения ключа. Так что тут можно придумывать какие-то хитрые схемы, снижающие в какой-то степени риски, но в общем виде надежно обезопасить хранение паролей таким способом не получится.
Правильный способ: хранение хешей паролей
Правильнее всего вообще не хранить у себя пароли. Да-да, очень простая идея: если у вас чего-то нет, то это в принципе не может быть украдено.
Но как тогда проверить, правильный ли пароль вводит пользователь, пытающийся залогиниться в ваш сервис? Для этого весьма удобно использовать хеш-функции: специальные криптографические алгоритмы превращают любые данные в строку битов фиксированной длины предсказуемым, но необратимым образом.
Предсказуемым тут означает, что одни и те же данные всегда будут преобразованы в один и тот же хеш. А необратимым — из хеша совершенно невозможно восстановить те данные, которые были захешированы.
Именно так и поступают все онлайн-сервисы, хотя бы немного дорожащие своей репутацией и заботящиеся о защите от утечки пользовательских данных. Когда пользователь вводит пароль при регистрации в сервисе, в базу данных рядом с логином записывается не сам пароль, а хеш этого пароля. И, соответственно, при последующих попытках залогиниться записанный в базу хеш сравнивается с хешем комбинации символов, вводимой пользователем. Если хеши совпадают — значит, пароль соответствует указанному при регистрации.
В случае утечки базы в руках злоумышленников оказываются не сами пароли, а их хеши, из которых невозможно восстановить оригинальные данные (необратимость, помните?). Это гораздо менее опасно, чем доступ к паролям в открытом виде, но радоваться пока все же рано: если в руках у преступников оказались хеши, то они могут использовать их для атаки перебором.
Еще более правильный способ: соленые хеши
Заполучив базу, взломщики будут подбирать комбинации символов под записанные в ней хеши. То есть они будут брать какую-нибудь комбинацию, вычислять ее хеш и искать совпадения по всем записям базы. Если совпадений не найдено, то брать следующую и так далее. В случае совпадения получается, что пароли, на основе которых были вычислены соответствующие хеши, теперь известны.
Еще хуже то, что на самом деле процесс взлома хешированных паролей можно существенно ускорить: для этого используются так называемые радужные таблицы (rainbow tables). Это огромные массивы данных с заранее вычисленными хешами для кучи всевозможных комбинаций символов. Соответственно, достаточно просто искать совпадения между содержимым радужной таблицы и украденной базы. И, конечно же, делается это все не вручную, а автоматизированно, поэтому процесс взлома паролей может занимать куда меньше времени, чем всем нам бы хотелось.
Впрочем, есть и хорошая новость: хеши вообще всех возможных комбинаций символов заранее вычислить невозможно — полная радужная таблица для любого алгоритма хеширования будет занимать больше дискового пространства, чем существует на планете. Скажем, даже для не самого надежного алгоритма MD5 такая гипотетическая таблица будет содержать 340 282 366 920 938 463 463 374 607 431 768 211 456 записей — попробуйте прочитать это число без запинки. Поэтому в радужные таблицы попадают хеши лишь для наиболее распространенных комбинаций символов.
Чтобы бороться с использованием радужных таблиц, специалисты по криптографии придумали эффективное решение. Оно использует еще одно важное свойство хеш-функций: даже малейшее изменение в исходном тексте изменяет результат хеширования до неузнаваемости.
Перед тем как вычислить хеш пароля и записать его в базу, к нему добавляют некий случайный набор символов, который называется соль (salt). И таким образом записанные в базу хеши полностью изменяются — так, что даже наиболее глупые и часто используемые пароли вроде «12345678» и «password» становится невозможно взломать с помощью радужных таблиц.
В варианте попроще используется одна и та же соль для всех паролей. А вот в наиболее устойчивом к взлому — индивидуальные соли для каждой отдельной записи. Красота подхода в том, что соли можно без особых проблем хранить в той же самой базе: знание соли не так уж сильно упрощает задачу злоумышленникам. Для взлома им в любом случае придется использовать чистый brute force — то есть перебирать все варианты.
Чем больше онлайн-сервисов использует такой вариант нехранения паролей — тем меньше вероятность массовой кражи пользовательских учетных данных и последующих неприятностей, связанных со взломом аккаунтов.