zmts / passwords.md
Save zmts/b72d3bcfd07634ff519da407bb86f361 to your computer and use it in GitHub Desktop.
Про хранение паролей в БД
Про хранение паролей в БД
При создании нового юзера
- При регистрации юзер вводит некий пароль
- Генерим случайную соль индивилуально для каждого юзера
- Создаем хеш на основе введенного юзером пароля и соли
- Записываем хеш(не пароль) в БД + соль в отдельном филде
Авторизация существующего юзера
- Юзер вводит в поле авторизации некий пароль
- Берем соль из базы и данный пароль
- Солим только что полученный пароль, в итоге получаем хеш
- Берем валидную хеш из БД и сравниваем ее с только что полученным хешем
- Profit, если введенный пароль вырный авторизируем, если нет говорим юзеру ввести правильный пароль
Суть не в дешифровке хеша из базы и сверке его с введенным паролем, а в создании нового хеша из нового введенного юзером пароля и соли из базы и последующей сверкой нового хеша с хешем из БД.
Практическое применение: создание хеша
var bcrypt = require('bcryptjs'); bcrypt.genSalt(10, function(error, salt) < // генерим соль >> передаем ее в колбек bcrypt.hash("some_password_from_input", salt, function(error, hash) < // берем пароль из инпута + соль и генерим хеш // получаем хеш и сохраняем в БД // в случае использования bcryptjs необходимость хранения соли отпадает, почему объясняется ниже >); >);
Практическое применение: проверка хешей
- Берем пароль из инпута, хеш из БД(hash_from_db)
- Ф-ция compare сама извлекает соль из хеша(hash_from_db) и солит им нововведенный пароль
- И сверивает новый хеш с хешем из БД(hash_from_db) Вот почему мы не сохраняли соль в БД, bcryptjs сам знает как извлечь соль из хеша, и унас отпадает необходимость хранить соль отдельно
bcrypt.compare("some_password", hash_from_db, function(error, result) < if (result)< // авторизируем юзера >>);
Откуда bcrypt.compare берет соль
var sol = bcrypt.genSaltSync(); >> '$2a$10$ydKFuX0Jfxsega193bReze' var myHash = bcrypt.hashSync('123456', sol); >> '$2a$10$ydKFuX0Jfxsega193bRezezqVklYDdrYSAHk5ho1uE8CPDuqNA8p6'
Первые 29 символов и есть соль $2a$10$ydKFuX0Jfxsega193bReze
- https://habrahabr.ru/post/210760/
- https://habrahabr.ru/post/130965/
- https://www.youtube.com/watch?v=rCIsuMEFRro
Про хранение паролей в БД
Когда встал вопрос хранения паролей, конечно, первой идеей было просто записывать их в открытом виде в соответствующей табличке в базе данных. И все бы ничего, если бы доступ к ней действительно напрямую клиенты получить не могли. Но, к сожалению, в различных веб-приложениях по-прежнему иногда работает такая известная всем SQL-инъекция, не говоря уже о других потенциальных уязвимостях. В вопросах безопасности вообще принято предполагать худшее и готовить план действий и защиту даже на такой случай. Будем считать, что злоумышленник нашел в веб-приложении лазейку, тем или иным способом радостно выгружает себе таблицу с именами и паролями пользователей и дальше уже распоряжается ими, как ему вздумается. В общем случае его дальнейшие действия могут быть следующими:
- выполнение нелегитимных действий от имени пользователей с использованием их учетных данных на уязвимом ресурсе: например, к учетной записи привязана банковская карта, и теперь злоумышленник может ей пользоваться;
- попытка использования полученного пароля на других ресурсах: далеко не всегда пользователи, следуя советам, придумывают каждый раз новые пароли для разных сервисов;
- попытка выявить правило генерации пароля и перейти ко второму пункту: некоторые формируют какое-то правило составления пароля, в итоге на разных ресурсах пароли разные, но подчиняются одному и тому же правилу, которое можно выявить;
- повышение привилегий: в той же таблице может храниться и пароль администратора, со знанием которого иногда можно получить полный контроль над сервером.
Шифрование Хэширование
Идея сразу оказывается не такой хорошей. Что делать? Здорово было бы хранить пароли в зашифрованном виде. Тогда, даже если их извлекут, восстановить не смогут или, по крайней мере, потратят на это слишком много времени. Здесь выбор встает между двумя ветками развития: шифровать пароли или хэшировать. Разработчики остановились на втором, и, в принципе, понятно, почему. Сравним наших претендентов по разным характеристикам:
- Трудоемкость. Шифрование занимает больше времени, а какое преобразование мы бы ни выбрали, его придется проделывать при каждой проверке пароля. Одним из требований к хэш-функциям же является быстрота выполнения.
- Длина выходных значений. Результат шифрования имеет переменную длину, результат хэширования – всегда одинаковую, а хранить однородные по размеру данные в базе данных очень уж удобно. Не говоря уже о том, что длина пароля в зашифрованном виде будет давать некоторую информацию о длине исходного пароля. Одинаковая длина, правда, приводит к возможности возникновения коллизий, но об этом ниже.
- Управление ключами. Для шифрования требуется ключ, который тоже где-то придется хранить и надеяться, что его никто не найдет. В любом случае, генерация и управление ключами это отдельная история (они не должны быть слабыми, их нужно регулярно менять и так далее).
- Возможность коллизии. При шифровании выходные данные от различных входных даных всегда тоже будут различны. При хэшировании же это не всегда так. Постоянная длина хэша означает ограниченность множества выходных значений хэш-функции, что приводит к возможности коллизии. То есть, допустим, пользователь действительно заморочился и придумал себе по-настоящему классный длинный пароль, в котором есть и спецсимволы, и цифры, и буквы в нижнем и верхнем регистре. Злоумышленник вводит в поле пароля не менее классный пароль “admin”. Сервер для проверки и сравнения хэшей захэшировал его. Хэши совпали. Обидно.
Атаки на хэшированные пароли
Итак, злоумышленник заполучил нашу таблицу с именами пользователей и паролей. Пароли теперь захэшированы, но это нашего атакующего не останавливает, и он всерьез намерен их восстановить. Его возможные действия:
- брутфорс по словарю: если с эталонным паролем администраторов у злоумышленника ничего не вышло, он обратится к словарю популярных паролей и попытает счастья с их хэшами;
- радужные таблицы: вообще сегодня ему, может, не надо будет совсем ничего вычислять и перебирать по словарю. Достаточно будет обратиться к лежащим в сети радужным таблицам. В радужных таблицах содержатся уже вычисленные кем-то до этого хэш-значения и соответствующие им входные данные. Важно отметить, что в силу коллизий, пароль, который предложит радужная таблица, не обязательно будет именно тем, который использует пользователь. Предвычисленные значения есть уже для MD5, SHA1, SHA256, SHA512, а также для их модификаций и некоторых других. Попробовать обратить хэш можно, например, здесь;
- полный перебор: если не поможет и это, придется прибегнуть к брутфорсу и перебирать подряд все возможные пароли, пока вычисленные хэши наконец не совпадут.
MD5 – 627 мс
SHA-1 – 604 мс
SHA-256 – 739 мс
SHA-512 – 1056 мс
А ведь сегодня брутфорс можно распараллелить и выполнить в разы быстрее на GPU (а также на APU, DSP и FPGA). Однако помимо выбора более долгого алгоритма и более длинного выходного результата можно сделать кое-что еще.
Хэширование хэша
Чтобы помешать нарушителю воспользоваться готовыми радужными таблицами, существует техника хэширования пароля несколько раз. То есть вычисляем хэш от хэша от хэша от хэша… и так n раз (надо, правда, сильно с этим не увлекаться, потому что при обычной проверке пароля пользователя серверу тоже придется это проделывать). Теперь так просто по радужной таблице он пароль не найдет, да и время на брутфорс заметно увеличится. Но ничто не остановит злоумышленника от того, чтобы сгенерировать радужную таблицу по словарю паролей, зная алгоритм хэширования. Тем более, для самых популярных комбинаций этого метода такие таблицы уже сгенерированы:
«
Добавить соль по вкусу
Для того, чтобы и это он не смог сделать, пароли сегодня хэшируются с добавлением соли.
Соль – это дополнительная случайная строка, которая приписывается к паролю и хэшируется вместе с ним. Из полученного таким образом хэша по радужной таблице пароль уже не восстановишь. Зная соль и выходной хэш, злоумышленник обречен на брутфорс и никакие заранее вычисленные таблицы ему, скорее всего, не помогут.
Таксономия соления паролей:
1. По принципу соления:
- уникальная соль для каждого пользователя: индивидуальная для каждого пользователя – таким образом, если соль станет известна злоумышленнику, брутить придется пароль каждого по отдельности. И кроме того, даже если два пользователя мыслят одинаково и придумали идентичные пароли, хэши все равно на выходе будут разными;
- глобальная соль: одинакова для всех, используется для всех хэшей;
- и то, и другое.
- в базе: как правило, индивидуальные соли хранятся в той же базе, что и хэши паролей; часто даже в той же строке;
- в коде (читать: в конфиге): глобальную соль обычно хранят не в базе данных, а, например, в конфиге, чтобы нарушителю пришлось потратить время на ее подбор.
- Ему неизвестна глобальная соль, поэтому ее придется брутить.
- Ему известны соли пользователей, но заготовленных таблиц с этими солями у него нет, поэтому пароли придется брутить.
- Процесс этот займет еще больше времени из-за того, что придется хэшировать хэши по n раз.
Как хранят пароли различные CMS
WordPress
До версий 3.х пароли просто хэшировались с помощью MD5. Сейчас используется библиотека phpass. По умолчанию к паролю спереди приписывается соль и полученная строка хэшируется MD5 2^8 раз.
Joomla
До версии 1.0.12 использовался просто MD5. Используется библиотека phpass, по умолчанию bcrypt с солью и 2^10 повторениями.
Drupal
До версии 6 md5 без соли. Используется библиотека phpass. По умолчанию соленый sha512 с 2^16 повторениями.
Silverstripe
Использует соленый Blowfish c 2^10 повторениями.
Где и как хранить данные пользователей, пароли, логины?
Ребята, подскажите пожалуйста, где лучше хранить данные пользователей — это пароли, логины
Я как понимаю, они должны быть собраны в баз данных с мд5 к примеру, но где лучше хранить эти данные чтобы не могли получить к ним доступ?
upd: Задал вопрос некорректно. Данные находятся в БД, как этот самый БД защитить и где хранить следуя закону 152-ФЗ о перс. данных?
Заранее благодарен!
- Вопрос задан более трёх лет назад
- 9892 просмотра
1 комментарий
Простой 1 комментарий
платежные данные
Вам знакома аббревиатура PCI DSS?
Решения вопроса 1
Имя, email, телефон, пароль и другое хранят в базе данных или в крайнем случае в обычном .txt файле.
Обратите внимание! То что вводит пользователь в поле пароль (например 12345) не записывают в базу данных. Создают хэш этого пароля + соль. Почитайте о солении паролей . На выходе в Вашей базе в поле password должен быть хэш (bdadb0330124cda0e8499c9cd118f7bd). Если пользователю нужно войти, то вы сравниваете хэш который получился после ввода пароля с тем который храниться в Вашей базе данных.
Ответ написан более трёх лет назад
Комментировать
Нравится 2 Комментировать
Ответы на вопрос 4
Пароли вообще не хранить. Платёжные данные — только если ты создал фишинговый сайт.
Остаются логины. Можешь хранить их хоть в блокнотике.
Ответ написан более трёх лет назад
Нравится 6 3 комментария
Farid @anvarli Автор вопроса
Задал вопрос некорректно. Данные находятся в БД, как этот самый БД защитить и где хранить следуя закону 152-ФЗ о перс. данных?
Как тогда аутентифицировать пользователей, если у нас не будет логин-парольной проверки?
fctoha, кто сказал, что не будет?
Photographer & SysAdmin
Тоже выскажу свое мнение, если ты прочитал, но не понял предыдущие 4-ре разных ответа.
Логины — в БД
Пароли — нигде
Ответ написан более трёх лет назад
Комментировать
Нравится 4 Комментировать
Системный администратор со стажем.
Логины и прочие данные, как правило хранят в базе данных.
Пароли не хранят вообще.
Ответ написан более трёх лет назад
Нравится 1 6 комментариев
Farid @anvarli Автор вопроса
Задал вопрос некорректно. Данные находятся в БД, как этот самый БД защитить и где хранить следуя закону 152-ФЗ о перс. данных?
Farid А как проводить аунтифткацию пользователя тогда ? В зашифрованном виде то можно хранить ?
Константин, Кого хранить? И причем тут аутентификация?
АртемЪ, Давайте подумаем, зачем же нужны пароли, ещё и с логинами )) Речь идёт о хранении паролей (это тема вопроса, если что). Так вот: пароль, который вводит пользователь, нужно сравнить с тем, что хранится в БД или где либо ещё. А вы пишите, что пароли хранить не надо. Так вот: Как проводить аутентификацию, если пароли нигде не хранятся и не с чем сравнивать ?
Константин, Хранить пароли нельзя, и их никто никогда не хранит на стороне сервера.
Единственное место где должен хранится пароль — голова пользователя который его придумал.
В БД на сервере хранится только хэш пароля.
Хэши и сравниваются.
Где лучше(безопаснее) всего в программе хранить пароль от БД?
важный пароль к базе данных зашифровать простой прогой типа XOR заменой простым паролем программы (вас как юзера). При запуске проги запускаете её и она XOR-ит вашим простым паролем пароль базы данных и получаете реально расшифрованный пароль. Надёжность зависит от длины и сложности ваших паролей.
23 сен 2022 в 17:28
Скорее всего пользователь вообще не должен иметь прямого доступа к бд. Если ваше приложение ходит в бд и при этом выполняется в недоверенной среде (у пользователя) — значит, вероятно, вы делаете что-то очень сильно не так
23 сен 2022 в 17:45
@andreymal я не совсем понял ваш ответ, вы бы не могли разъяснить подробнее, что я делаю не так? И вероятно, вы можете посоветовать литературу, где я могу об этом почитать/научиться этому?
24 сен 2022 в 6:29
.conf-файл просто не надо разрешать читать каким попало пользователям. Режим 0600 — и до свидания.
19 окт 2022 в 9:31
@user_587 Вы видимо не в курсе, как работают подобные файловые разрешения. «режим 0600» фактически устанавливает только номинальные ограничения
19 окт 2022 в 9:34
7 ответов 7
Сортировка: Сброс на вариант по умолчанию
Никакого способа защищенно хранить пароли в программе нет. Пользователю доступны все ее данные, включая пароль и содержимое из базы данных. Максимум, чего вы сможете добиться — обфускации пароля. Для защищенного хранения паролей и т.п. чувствительных данных необходимо использование аппаратного носителя с неизвлекаемыми ключами.
Отслеживать
ответ дан 19 окт 2022 в 9:46
user7860670 user7860670
29.9k 3 3 золотых знака 17 17 серебряных знаков 36 36 бронзовых знаков
Комментарии не предназначены для расширенной дискуссии; разговор перемещён в чат.
20 окт 2022 в 6:27
Если бд на сервере, то сервер должен выполнять с ней работу => все логины и пароли должны храниться на сервере. Программа же должна общаться с сервером посредством запросов, в которых передаются данные, с которыми мы хотим что-то сделать
Отслеживать
ответ дан 21 окт 2022 в 17:11
evgeni2306 evgeni2306
175 8 8 бронзовых знаков
А для авторизации работы с этой программой на сервере (прокси) все равно понадобится локально хранимый пароль. Но это не пароль базы, поэтому с базой в любом случае можно будет делать только то, что реализовано в прокси
23 окт 2022 в 21:32
Есть 2 варианта:
- Вынести пароль и ссылку к бд в dll который при необходимости будет обновляться.
- Создать файл, с определенным методом шифрования и дешифрования (тут есть разные варианты реализации), а ключ к дешифровки хранить непосредственно в .exe файле.
Но лично я бы написал бы простой PHP скрипт на сервере, который бы обращался к базе данных. Если говорить про обычный хостинг, и у пользователя уже хранить в .exe статичную ссылку, а на сервере уже хранить пароль.
Отслеживать
51.6k 204 204 золотых знака 67 67 серебряных знаков 251 251 бронзовый знак
ответ дан 23 сен 2022 в 15:47
47 6 6 бронзовых знаков
любые строки, которые мы храним в скомпилированных файлах читаются, если этот файл открыть как txt
23 сен 2022 в 15:53
@SpaceResearcher тогда шифровать строку в с++ и сохраняй ее хэш, а после запуска программы, считывай хэш из файла и декодируй
23 сен 2022 в 16:00
пароль поменяется — менять хеш в проге — перекомпиливать, к тому же этот хеш нереально расшифровать же 🙂 Должно быть какое-то хорошее решение, но я его пока не нашел
23 сен 2022 в 16:08
@SpaceResearcher сделай тогда по третьему варианту Но лично я бы написал бы простой php скрипт на сервере, который бы обращался к базе данной, если говорить про обычный хостинг, и у пользователя уже хранить в .exe статичную ссылку, а на сервере уже хранить пароль.
23 сен 2022 в 16:14
«ключ к дешифровки хранить непосредственно в .exe файле» — это эквивалентно хранению пароля базы в .exe c небольшой обфускацией
19 окт 2022 в 9:24
Если нету посредника, который будет соединятся с базой — пароль в том или ином виде не может не быть на клиенте. Клиенту нужно использовать пароль чтоб установить соединение с БД.
Возможно, существуют движки БД или плагины для них, которые позволяют установить соединение с помощью аппаратных ключей или одноразовых токенов, но это довольно редкие варианты, и рассматривать их не буду.
Так же, под «БД» я представляю какую-то СУБД типа MySQL, где очень мало возможностей ограничения доступа.
Возможно, у вас другой движок БД, где сервер представляет всю нужную защиту данных и разграничение доступов, и ваша задача — именно спрятать пароль от соединения в обход клиентской программы.
Соответственно, ответ исходит из этой точки зрения.
Думаю, лучше всего хранить пароль — в зашифрованном виде в конфиге.
На счет шифрования — алгоритм должен быть проверенный временем, то есть например AES. Без велосипедов.
Ключ шифрования — частично захардкодить, частично вычислять в рантайме (например, операции над массивом). Так как компилятор может оптимизировать такой код, следует его написать так, чтоб компилятор не догадался, что результат будет константой. Очень хорошее решение — так же использовать идентификаторы привязанные к железу. Например, «Volume Serial Number» раздела, на котором лежит программа. Тогда даже если скопировать программу на флешку — он не будет работать.
Ну и всю эту красоту прогнать через HMAC.
Еще один мелкий лайфхак обфускации: прогнать base64 через шифр цезаря =)
Еще один интересный способ хранения пароля, который я использовал в одном проекте (в описании я немного упростил схему):
Пароль зашифрован ключем, который есть хешем числа от 1 до 10000. Ни ключ ни это число не сохраняются нигде. При установлении соединения ключ шифрования пароля подбирается в реальном времени. Так же имеется хеш пароля, чтоб убедится что ключ расшифрован правильно.
Отслеживать
ответ дан 19 окт 2022 в 12:18
Давид Манжула Давид Манжула
3,125 11 11 серебряных знаков 23 23 бронзовых знака
Всё это не поможет абсолютно никак, потому что клиент прочитает готовый вычисленный ключ тупо из оперативной памяти
19 окт 2022 в 14:09
@andreymal разве? Пароль обычно используется только для соединения с базой. После того как соединение установлено и пароль больше не нужен — можно очистить память и освободить переменную
20 окт 2022 в 6:17
Ничто не помешает клиенту прочитать пароль ещё перед очисткой памяти
20 окт 2022 в 11:46
@andreymal это мгновение между расшифровкой пароля, отправкой и очисткой памяти? Ну можно еще насыпать мусора в памяти, чтоб было сложнее найти
21 окт 2022 в 11:24
Мой ответ подразумевает, что речь идёт о локальной системе, т. е. клиентское приложение запускается на том же компьютере, где находится и СУБД, и БД.
Пароль нужно хранить в .conf в зашифрованном виде. Программа читает конфигурацию и дешифрует пароль, используя ключ, жёстко забитый в код программы.
Аргументы: 1) пароль не должен быть зашит в коде, чтобы его можно было менять; 2) пароль не должен быть доступен в открытом виде в конфигурационном файле.
Другого варианта нет. И этот вариант, как и любой другой, не защищён от реверс-инжиниринга.
Если это секретный пароль, то обновлять его в конфигурационном файле нужно с помощью другой программы, в которую забит тот же ключ шифрования.
Тут предлагают всякие варианты с хостингом, серверами и пр. интернетом, но в условии о доступе в сеть речи нет. Это может быть локальная база данных, которую нужно защитить от несанкционированного доступа пользователя. Это сразу отсекает метод защиты через аутентификацию средствами ОС. Защита БД осуществляется приложением, так как только приложение может менять БД и только запрограммированным образом, исключая риск намеренного или ненамеренного повреждения или изменения данных.
Появилась мысль, сам делал такое недавно. Исходя из гипотезы локального применения. Нужно защитить приложение от доступа. Сделать его в виде службы с Web-интерфейсом, приложение запускается от какой-то выделенной учётной записи, доступ к файлам и папкам приложения только у этой учётной записи (ну и система, и администраторы, понятно). Таким образом, нельзя будет изучить исполняемый файл приложения, его бибилиотеки, конфигурационные и другие файлы.
Естественно, всё это подразумевает, что пользователь не обладает правами администратора и не может получить административный доступ к системе.
С уточнёнными условиями неободимо сделать следующее:
- доступ к БД осуществляет серверное backend-ПО;
- клиентское приложение подключается к серверу с помощью учётных данных, которые пользователь вводит интерактивно.
Таким образом, в приложении и его конфигурационных файлах никакие пароли не хранятся.