Что такое соленый хэш
Солим пароли
Данная заметка призвана пролить свет на использование соли при хешировании пароля. Если посмотреть в комментарии к этому топику habrahabr.ru/post/145642, то возникает подозрение, что некоторые люди неправильно понимают предназначение соли. На примерах постараюсь показать, для чего используется этот механизм. Всех заинтересовавшихся прошу под кат.
Представим простую авторизацию. От пользователя к нам приходит связка значений логин/пароль, мы получаем хеш пароля и сравниваем данную связку с данными, хранящимися в базе. Для простоты будем использовать MD5 и примеры кода на PHP.
В данном случае, если у пользователя пароль qwerty, мы получим следующий хеш: d8578edf8458ce06fbc5bb76a58c5ca4. Если злоумышленник получит доступ к нашей базе, для подбора паролей он может воспользоваться уже готовыми сервисами(http://wordd.org/D8578EDF8458CE06FBC5BB76A58C5CA4), в которых уже есть значения, дающие данный хеш, либо сбрутить самому.
Для защиты от уже готовых таблиц хешей с значениями, можно использовать статическую соль:
Сейчас при том же пароле qwerty мы получим совершенно другой хеш bdadb0330124cda0e8499c9cd118f7bd. Готовые таблицы уже не помогут злоумышленнику, ему придется использовать брутфорс. Вот здесь и кроется минус статической соли: злоумышленник сможет сгенерировать свою таблицу хешей со статической солью и получить значения большинства паролей из базы. Для устранения этого минуса используется уникальная соль к каждому хешу:
Т.е. теперь помимо логина/хеша пароля в базе необходимо будет хранить значение сгенерированной соли для каждого пользователя. Разберем пример: у нас два пользователя: user1 и user2. Оба используют пароль qwerty. Но у первого была сгенерирована соль zxcv а у второго asdf. В итоге у пользователей при одинаковом пароле будут различные хеши: 1d8f3272b013387bbebcbedb4758586d и a192862aa3bf46dffb57b12bdcc4c199.Что это дает: теперь нельзя будет сгененерировать одну таблицу хешей, для нахождения значения хеша с динамической солью придется генерировать заново. Все это направлено на увеличение времени подбора значений в случае «слива» базы, при использовании «хороших» алгоритмов хеширования, на подбор хотя бы пары паролей уже может уйти значительное количество времени. Важно понимать, что генерируемая соль защищает не одного единственного пользователя, а всех вместе от массового брута. На этом все, хочу напомнить что используйте криптостойкие алгоритмы хеширования SHA1, SHA512. Используемый выше MD5 к использованию не желателен, т.к. признан устаревшим.
Хорошо резюмировал Kolonist в своем комментарии habrahabr.ru/post/145648/#comment_4894759 ( за что ему отдельное спасибо и плюс):
Еще раз.
1. Нет соли — используем уже готовые радужные таблицы.
2. Есть одна на всех соль — генерируем одну радужную таблицу и «ломаем» по ней всех пользователей.
3. Есть отдельная соль для каждого пользователя — отдельно брутфорсим каждого пользователя.
codedokode / Как солить и хешировать пароли.md
Здесь старая версия урока, которая больше не обновляется.
Итак, ты решил сделать авторизацию и регистрацию через пароли. Как максимально обезопасить пароли пользователей от взлома и от своих же любопытных сотрудников (если ты работаешь не один, а в большой компании)?
Для начала, никогда не храни открытые пароли. Храни соленые хеши от них. Хеш-функция, например md5, sha1 (про них написано в вики, почитай) — это практически необратимая функция. То есть получить хеш по паролю просто, а вот восстановить пароль, имея хеш практически невозможно — надо перебирать все возможные варианты паролей и сравнивать получившиеся хеши.
Какой смысл в хэше, если md5 все равно можно расшифровать? Пусть даже перебором?
Это займет много или очень много времени. Может, взломщик устанет ждать или пароли потеряют актуальность. Например, если хорошо шифровать, то годы (по идее там перебирать можно и 100 лет, но я думаю скоро изобретут какую-нибудь штуку для ускоренного перебора), вместо того чтобы взять и увидеть пароли в открытую.
Ок, достаточно ли использовать хеширование и хранить только хеши?
Нет! Без так называемой «соли» многие пароли можно подобрать за секунду если там использовать просто md5(pass). Не веришь? Читай ниже.
Что такое соль? Что значит «соленый хеш»?
Теперь попробуем применить математику и посчитать насколько надежны разные способы хеширования. Сейчас подбор пароля делается 2 способами:
Перебираем все возможные пароли, начиная например с 1111111 и заканчивая zzzzzzz и вычисляем от каждого md5-хеш. При этом число вариантов, которые надо подобрать, зависит от длины и набора символов (чем их больше тем больше перебирать). Скорость перебора md5 на топовых видеокартах составляет около 10 миллиардов в секунду ( http://www.opennet.ru/opennews/art.shtml?num=30201 и http://hashcat.net/oclhashcat/ ). А ведь можно взять не одну видеокарту, а много, если очень надо.
Заметь, что если у тебя база с кучей хешей, то их все можно проверять их все одновременно примерно с такой же скоростью как и один хеш.
Считаем число вариантов.
36^6 — значит 36 в 6-й степени, то есть 36*36*36*36*36*36 если что.
10^19 и перебирать их 10^9 секунд на одной карте (11500 дней) или 115 дней на сотне карточек.
Люди часто ставят паролем не бредовый набор букв, а слова или куски слов. Значит, какие-то символы рядом встречаются чаще, их можно перебирать в первую очередь тем самым сокращая число вариантов и ускоряя время нахождения.
В общем, видишь, без добавления соли пароли подберутся на раз. И не все же ставят 10-символьные пароли, у многих там просто слово или цифры.
Есть еще другой вариант — скачать огромные радужные таблицы (читай в вики про них) где хранятся уже рассчитанные цепочки хешей (для простых паролей). И конечно все хеши от обычных паролей длиной до 10 символов там уже есть (больше нету, так как они начинают занимать гигабайты. Но это вопрос времени, когда жесткие диски станут больше). Если ты хранишь в базе md5(pass) она вскроется мигом. Таблицы можно скачать тут: https://www.freerainbowtables.com/en/tables2/ (если не открывается, выбери английский язык и открой ссылку еще раз).
Заметь что в будущем компьютеры будут мощнее, и значит подбираться пароли будут быстрее. Теперь подумаем как защититься и усложнить жизнь взломщикам:
С правильным подходом даже простой md5 замучаешься расшифровывать.
Хеш + соль, как панацея от декрипта
Но это всё была присказка. а сказка — впереди…
Теперь возвращаемся к нашей главной проблеме, КОРОТКИЕ И ПРОСТЫЕ ПАРОЛИ юзеров.
Что мне нужно, что бы «взломать» выше описанный способ «хранения» паролей. А главное — что я уже ИМЕЮ для этого?
А имею я совсем НЕ МАЛО! Можно сказать, что у меня уже есть пароль юзера. А точнее говоря — у меня уже есть все пароли большинства юзеров. А почему? да всё потому же! «короткие и простые пароли юзеров».
Теперь, что я делаю…
1. Я регюсь на взламываемом сайте.
2. Взламываю БД или то место, где хранятся хеши паролей. (это условие данной темы)
3. Нахожу свой хеш. (по моему имени юзера)
-. Зачем мне нужны первые три шага?
+. Для того, чтобы определить, каким образом получают хеш на сайте. Т. е. я перебираю возможные варианты:
md5($pass);
md5(md5($pass));
md5(md5(md5($pass)));
sha1(md5(crypt($pass)));
… и т. д., пока не получу мой хеш!
Если программер использовал просто md5(md5($pass));, то мне легче.
4. «Формула» получения хеша у меня есть, теперь мне нужна прога которая сгенерирует
все хеши ПО ДАННОЙ формуле (скачаю или сам напишу), и не много времени (если в секунду 1’000’000 хешей, то для 56’800’235’584 хешей это около 20 часов, НО это считайте МАКСИМУМ, а если по словарю перебирать или только пароли из цифр, то времени на порядок меньше потребуется).
И ВСЁ! Все пароли длиной до 6-и символов у меня «в кармане»!
И так! Этот метод взломали, теперь ПРО СОЛЬ…
Ломаем метод автора статьи…
-. Выполняю первые 3 шага.
Теперь, если я взломал БД и получил хеши паролей, то я также и получил каждую «солинку».
И что я делаю?
Да всё тоже самое.
Просто теперь при поиске «формулы» получения хеша я добавляю эту соль, при чём всеми возможными вариантами!
md5(md5($pass.$salt));
md5(md5($pass).$salt);
md5(sha1($salt.crypt($pass)));
… и т. д…
Ну а далее думаю уже догадываетесь… Генерю все хеши добавляя соль УЖЕ в правильное место и используя правильную формулу.
НО здесь как видите уже есть один «худенький» плюсик.
Речь уже идёт не о взломе всех паролей, а о взломе одиночного аккаутна, соль то для каждого юзера своя, а значит генерировать таблицу придётся для каждого юзера заново. Во как!
А почему плюсик «худенький»?
Да опять же всё потому, что «ПРОСТЫЕ И КОРОТКИЕ ПАРОЛИ». (на верное я вам уже надоел. терпи’те!)
Начинаю генерить по словарю используя только цифры (большинство паролей — это даты рождения). Обычно на сайте требуют пароль длиной не менее 6-и символов, т. е. я перебираю например:
Так же, даты когда юзер пишет что то типа 111977; (1 января 1977 года, т. е. варианты без нулей)
Так же варианты с 7-и значными датами и с 8-и значными…
«Год у меня был… 3 — за побег… 5 — за дет-сад… ну сколько за старуха дадут? ну пусть 10 лет… И я из-за каких-то 16 лет. »
Ну пусть у нас получилось всего 1’000’000 вариантов даты рождения! Если машина генерирует 1’000’000 хешей в секунду — получается я буду вскрывать по юзеру в секунду, а если двигаться от младших к старшим, то ещё быстрее.
И что у нас получилось? Мы вскрыли за один час — 3600 юзеров «с СОЛЬЮ»!
И вся прелесть в том, что и соль НЕ ПОМОГЛА! А почему? Вижу по лицу, уже догадались!
последний раз: «ПРОСТЫЕ И КОРОТКИЕ ПАРОЛИ».
«И что же?» — скажете вы — «значит нет надёжного метода?».
И ПРАВИЛЬНО скажете!
Вы ищете в интернете надёжный метод или как вы ещё любите «часто используемый метод», и при этом вы УЖЕ СОВЕРШАЕТЕ ОШИБКУ! потому, как «то, что знают двое — знают все!» и как вы знаете «то, что один человек построил — другой завсегда поломать сможет».
Ну так и что же делать?
А всё просто, «ХОЧЕШЬ ЖИТЬ — УМЕЙ ВЕРТЕТЬСЯ!»
Не используйте общеизвестные приёмы, или изменяйте их на свой манер, отпиливайте, приклеивайте, меняйте местами, копируйте, придумывайте что то своё, и т. д. и т. п… Думайте своей головой. И вообще, подумайте, а стоит ли овчина выделки. Нужна ли вам эта бетонная крепость, или можно и и так прожить в деревянной… Даже если вы напишете код, который будет чередовать функции хеширования 10-20 раз, например в файле «enter.php». Во первых: что мне помешает написать программку которая будет перебирать все варианты чередования функций md5, sha1, crypt, и т.д., и в итоге будет находить нужную последовательность за считанные секунды. А во вторых: где гарантия, что я не заставлю сервер не выполнить ваш файл «enter.php», а просто прочитать его, или найти в вашем сайте ещё какую дырку и получить исходный код файла. И тогда хоть ваш код чередует 1000 раз, да и всё что угодно, я просто повторю ваш код при генерации таблицы хешей и результат будет тот же, а все ваши старания понапрасну…
Так что, надёжной защиты нет. Бывает лишь более надёжная защита, и бывает хакер который хитрее Вас, кстати, который не обязательно умнее Вас!
Взлом «посоленных» хешей
Безопасность веб-приложений: Что можно, а что нельзя делать при шифровании с использованием соли.
Безопасность веб-приложений: Что можно, а что нельзя делать при шифровании с использованием соли
Обзор:
Вопрос безопасности баз данных стал более насущным по мере того, как базы данных становились более открытыми. Шифрование является одним из пяти основных факторов безопасности данных.
Небезопасной практикой является хранение такой важной информации, как пароль, номер кредитной карты в базе данных в незашифрованном виде. Эта статья охватывает различные возможности шифрования.
Даже в если вы зашифровали вашу информацию, это совершенно не значит, что она находится в полной безопасности. В этой статье рассматриваются действия со стороны злоумышленника.
Соль (Криптография)
http://en.wikipedia.org/wiki/Salt_(cryptography)
Предположим, что украден хешированный пароль пользователя. Известно, что пароль является одним из 200,000 английских слов. Система использует 32-х битную соль. «Посоленный» ключ – это оригинальный пароль, добавленный к произвольной 32-х битной соли. Из-за соли посчитанные хеши злоумышленника не подойдут (не удастся использовать радужные таблицы). Злоумышленник должен посчитать хеш каждого слова с каждым из 232 (4,294,967,296) возможных вариантов соли, добавленных к паролю, до тех пор, пока не будет получено совпадение. Общее число возможных комбинаций может быть получено умножением количества слов в словаре на количество возможных вариантов соли:
2^ <32>\умножить на 200 000 = 8.58993459 \умножить на 10^ <14>
Для завершения брут-форс атаки злоумышленник должен перебрать почти 900 триллионов хешей, вместо всего-лишь 200,000. Даже если пароль сам по себе достаточно прост, соль делает взлом паролей достаточно сложной операцией.
Соль должна быть неизвестной. Если злоумышленник знает, какая используется соль, он сразу может перейти к первому шагу. Ниже приведены несколько возможных способов взлома «посоленных» хешей.
Приложения, не использующие хеши:
Во время изучения веб-приложения я дошел до этого места программы. Программа использовала javascript для шифрования пароля пользователя перед отправкой. В качестве соли использовался текущий ID сессии.
На сервере программа не сможет проверить значение пароля по причине использования соли и случайного ID сессии. И поскольку MD5 является нереверсивной хеш-функцией, пароль не сможет быть проверен до тех пор, пока пароли хранятся в виде текста в базе данных.
В качестве соли для шифрования пароля перед отправкой используется случайно сгенерированный ID сессии. Это значит, что серверные базы данных не будут зашифрованы.
Иногда такого рода программы выдают много информации.
Пункт №1: Всегда шифруйте вашу базу данных паролей.
Для того, чтобы использовать все эти виды атак, вы должны знать, при помощи какого алгоритма был посчитан хеш.
Что можно сделать, чтобы выяснить используемый алгоритм хеширования??
Ответ: Все алгоритмы генерируют хеш фиксированной длины. Поэтому на основании выходного значения вы можете прикинуть, какой алгоритм использовался☺. “Все это – достаточно известные факты”, но по-прежнему я помещаю их здесь.
Для этого я размещу небольшую таблицу для выявления хеш-функций на основе их выходного значения
Функция: md5(“входные данные”); Hash(“входные данные”); Вывод: 32 Символа Пример: “5f4dcc3b5aa765d61d8327d eb882cf99”
Функция: System.Security.Cryptogr aphy Вывод: 32 Символа Пример: “5f4dcc3b5aa765d61d8327d eb882cf99”
Функция:java.secur ity.MessageDigest Вывод: 32 Символа Пример: “5f4dcc3b5aa765d61d 8327deb882cf99”
Функция: Crypt() По-умолчанию DES вывод: 13 Символов Пример: “sih2hDu1acVcA”
Есть ли смысл в соли из хеша пароля?
Прочитал кучу статей про правильное хранение и шифрование паролей.
Из всего существующего самым «популярным» является сохранение пароля в базе в виде md5(md5(password)+salt), при этом соль хранится в базе в соседней колонке (ну или в той же колонке где и хэш).
Такой способ конечно усложняет взлом пароля, но имея хеш и соль взломать все равно можно.
Есть ли смысл, если
1. хешируем пароль: hash1 = md5(password)
2. в качестве соли берем допустим 10 символом от хеша hash1
3. получаем итоговый хэш по старому алгоритму: md5(md5(password)+salt), или
md5( md5(password)+substr(md5(password),0,10) )
Вопрос: будет ли этот способ лучше способа с хранением соли в отдельной колонке, или хуже? Может есть что-то более «хитро-извращенное»?
Да, конечно этот способ лучше.
То, что вы предлагаете называется динамической солью.
Если уж хочется чего-то «хитро-изварщенного», то можно хранить в базе что-то такое:
где динамическая соль будет вычисляться так, например:
Обычно как… соль для каждого пользователя своя. Обычно это рандомная строка. При хешировании пароля с солью достигается большая криптозащита за счет увеличения времени перебора для получения нужной строки пароля + соли.
А можно сделать еще круче — можно использовать медленные алгоритмы. Тобиш скажем хеширование происходит в цикле. Если колличество итераций динамическое — то и это хорошо. И алгоритмы шифрования надо брать не быстрый md5 а что-нибудь помедленнее, например sha512. Это в свою очередь сведет попытки подбора хэша и генерации радужных таблиц на нет, ибо каждый вариант перебора будет происходить немыслимо медленно. На хорошей видиокарте с CUDA можно в секунду сгенерить миллиончик MD5 хэшей. А так хорошо если сотню сгенерит.
Для чего вообще нужна соль? А для того, чтобы md5(password)+salt было достаточно длинным, чтобы его нельзя было получить из хэша по предвычисленным таблицам. Таблица-то даст что-то, но нет никакой гарантии, что в конце будет именно ваша соль.
По-моему, криптостойкость одна и та же: тот же уровень противодействия перебору и та же защита от таблиц.