Pull to refresh

Comments 99

> 12 символов будут сопротивляться в течение полутора лет (опять же, в среднем), это определенно мало для большинства приложений.

Мало? :)
Ну, как часто ты пароль от, например, почты меняешь? Я вот почти не меняю. Поставил и забыл. А на сторонних сайтах так и вообще никогда не меняю.
Аналогично. Автор, кстати, не углядел более глобальную догму в криптографии — что пароли вообще нет смысла шифровать в БД. Если злоумышленник добрался до ДБ с паролями, до сами пароли ему уже нафиг не сдались. Всё равно что хранить ключ от кабинета в сейфе того же самого кабинета.
Ну как бы, получить доступ к табличке с логинами/паролями — это далеко не всегда то же самое, что получись доступ ко всей базе. Плюс, в больших системах база с паролями может быть физически отделена от БД с чем-то более критичным.
Например список хешей можно получить из бекапа AD, но это же не зачит, что мы получили доступ к самой AD, правда?
С ситуацией бэкапа согласен
Хотя… там же может оказаться и бэкап CD (content dababase), и опять всё по-новой :) Вы скажете, то бэкап CD должен быть зашифрован, но это можно сказать и про бэкап AD.
Ключ, потенциально подходящий к другим кабинетам.

Некрокомент, но этой мысли в даном контексте явно не хватает:

Пароль даёт не только доступ к БД через интерфейс системы, пользующейся этой БД, пароль даёт ещё и возможность совершать новые действия от имени пользователя. От спама, шифрующегося под дружеские сообщения, до переводов денег и далее. А так же, при "удачном" использовании OAuth или применении того же пароля в других системах - и доступ к ним.

Полтора года = день для ботнета в 5к компьютеров. Ботнеты, увы, не только для DDOS используют :(. Так что дамп базы с чего-нибудь слабосекьюрного -> расшифровка пароля -> велика вероятность что этот же пароль используется для более важных ресурсов. Крайне мало людей у которых к каждому сервису свой криптостойкий пароль :(.
Я использую lastpass для этого. Он мне пароли символов по 20 генерит :-)
UFO just landed and posted this here
Ну, его то можно запомнить и нигде больше не использовать :-)
UFO just landed and posted this here
Если он кому-то нужен, то охотится будут за ним лично. А здесь речь о сервисе. ))
UFO just landed and posted this here
Ну только если так смотреть.
А что если человек пользует что-то вроде 1Password?
UFO just landed and posted this here
Если доступ не давать посторонним, то взлом тяжкая штука. Отследить, найти дырки, проникнуть. А если трояна не подкинуть? И вообще не винда у человека и человек не нуб)
Тут без доступа к компу в реале не обойтись. А если так, то не важно, как хранить пароли.
Еще забываете про терморектальный криптоанализ.
На самом деле, вместо того что-бы добавлять соль в конец пароля, ее можно просто размазать по самому паролю.

Например если в качестве уникализатора (?) для соли у нас выступает имя пользователя (username), а пароль (password) и есть соль (!@#$%^&*).

То размазываем сначала соль по username, например простым чередованием символов

username + salt = u!s@e#r$n%a^m&e*

А потом размазываем данное значение по паролю таким-же способом
pua!sss@w#eorr$dn%a^m&e*

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

А если еще пару раз взять md5(sha1(pua!sss@w#eorr$dn%a^m&e*) + md5(username) + sha(password) + username + !@#$%^&*).
Таким вот примерно способом можно решить проблему коротких паролей ровно до тех пор, пока атакующий не знает алгоритма обработки пароля с солью.

+ можно использовать еще медленные алгоритмы преобразования.
> Таким вот примерно способом можно решить проблему коротких паролей ровно до тех пор, пока атакующий не знает алгоритма обработки пароля с солью.
В этом, и только в этом вся проблема. Поэтому, как бы ни печально это звучало, но данный метод ничем не лучше и не хуже обычной конкатенации.
Зачем нужны пароли, если уже есть дамп базы со всей инфой?
Они могут подойти к почте или другим ресурсам — актуально для пользователей, использующих «универсальные пароли».
P.S. Пишу потому, что этот вопрос задается достаточно часто (и здесь тоже), а основная статья тоже описывает азы.
Почему бы просто не использовать SHA2? А PBKDF расчитан на извлечение ключа из пароля, не очень логично его использовать для хранения информации о пароле.
И насчет подбора пароля — соль нужна для предотвращения атаки по Rainbow Tables, которая намного быстрее тупого перебора, и требует не так много места.
По моему, Сальваторе говорит как раз про rainbow tables. Посмотри, сколько терабайт там занимает она. Или я что-то путаю? :-)
Тем что он гораздо более стойкий, чем SHA1.
При чём здесь стойкость самого хэша то ёмое, если в статье брутфорс/таблицы рассматривается?
Ответ в старой статье на хабре про многократное хеширование, ссылка была указана выше, если вкратце — для SHA2 повышается верхний предел разрешенного количества итераций, ну и само-собой больший запас разрядности хэша при снижения стойкости.
По-моему, «радужные таблицы» как раз помогают злоумышленнику решить проблему с суперпозицией функций хеширования, если, конечно, в каждой итерации не добавлять «соль», хотя бы и одинаковую.
Не понимаю. Действительно ли ты утверждаешь, что таблица рассчитанная для sha1(pwd) поможет взломать sha1(sha1(pwd))?
Да. Потому как результат работы одной хеш-функции — есть исходные данные для другой. «Радужные таблицы» позволяют «размотать» вложенность. На 1 уровень вложенности один дополнительный поиск в таблице.
Неправильно. В приведенном примере мы рассчитываем таблицу для пароля из 12 символов. А sha1 дает на выходе строку в 40 символов. Ты до второго пришествия такую таблицу не просчитаешь.
Вот, я тут посчитал :-)

Sergios-MacBook-Pro:projects sergio$ irb
ruby-1.9.2-p290 :001 > combinations = 16**40
 => 1461501637330902918203684832716283019655932542976 
ruby-1.9.2-p290 :002 > size_on_disk = combinations * 40 # two hashes of 20 bytes (binary compact form)
 => 58460065493236116728147393308651320786237301719040 
ruby-1.9.2-p290 :003 > size_in_terabytes = size_on_disk / 1000 / 1000 / 1000 / 1000
 => 58460065493236116728147393308651320786 
Что, разве неправильно посчитал? :-)
Неправильно :) В радужных таблицах для каждой «строки» храниться только первая редукция и последний хеш. Бегом на википедию, читать что такое радужные таблицы :)
Будь другом, посчитай правильно :-)
Лень :) Вот тебе выписка из википедии:

К примеру для паролей длиной не более 8 символов, состоящих из букв, цифр и специальных символов !@#$%^&*()-_+= захешированных алгоритмом MD5 могут быть сгенерированы таблицы со следующими параметрами:
длина цепочки 1400
количество цепочек 50 000 000
количество таблиц 800
При этом вероятность нахождения пароля с помощью данных таблиц составит 0.7542 (75.42 %), сами таблицы займут 596 Гб, генерация их на компьютере уровня Пентиум-3 1ГГц займёт 3 года а поиск 1 пароля по готовым таблицам не более 22 минут.


Да, пераметры другие. Но на порядок результата они не повлияют.
Например, если пароль будет всё же 12, а не 8 символов. То таблицы вырастут всего до 596*12/8 = 894 Гб (как я говорил, таблицы хранят только концы цепочек). Правда при этом упадет вероятность нахождения пароля. Но допустим, удвоив количество таблиц мы вернем её обратно. Тогда таблицы будут занимать аж целых полтора терабайта. Но никак не столько, сколько насчитал ты.
А зато у меня поиск мгновенный и стопроцентный. Для пароли из 40 символов :)
Неправильно. В приведенном примере мы рассчитываем таблицу для пароля из 12 символов. А sha1 дает на выходе строку в 40 символов. Ты до второго пришествия такую таблицу не просчитаешь.

Автор, видимо, имеет ввиду, что при полном переборе мы можем использовать rainbowTables, как-то так:

variantsGenerator = new VariantsGenerator;

while (variant = variantsGenerator.next()) {
   // result = sha1(sha1( variant ));
   result = sha1(getHashFromRainbowTable( variant ));
}



как-то так.
Не так. В радужных таблицах после операции хеширования идет операция редукции — превращение хеша в новый «пароль», который уже пойдет на вход следующей итерации.
Потому что нет удобного способа использовать строку из 320 бит в качестве пароля напрямую.
Упс, не 320, а 160 бит. Попутал малость.
А если нету его для нашей системы. А sha1 есть даже не пылесосах. И секьюрность не меньше, если с умом подойти :-)
Блин, SHA4! Суть то не в этом! Извините.
Вы случайно не следили за соревнованием на право называться SHA-3? Очень там были забавные мотивации на отсеивание кандидатов. Так что «криптограф-любитель» вряд ли сможет сделать что-либо хорошее.
Ко всему прочему, в статье, приведённой несколькими комментариями выше, автор топика соглашается в спорности повышения криптостойкости при применении этого подхода.
BCrypt, к слову, использует несколько итераций, что и даёт стойкость, и что снижает скорость (в том числе составления таблиц). Не вижу причин не использовать его, если отбросить нежелание добавлять новые зависимости.
Сальваторе предлагает много раз прогонять sha1 не для повышения криптостойкости. А для увеличения стоимости генерации хэша. Ну и заодно для защиты от таблиц. :-)

bcrypt — хороший алгоритм. Но можно же и без него обойтись. К слову, redis компиляется вообще без зависимостей. Маленький компактный самодостаточный код. Так что мужик знает о чем говорит :-)
Всё хорошо, это эта фраза просто убила: «Заметим, что в английском языке не так уж и много слов, поэтому эта атака может быть проведена очень легко и быстро.» И это про язык, в котором больше всего слов!
Да брось, откуда данные то? :-)
В любом языке слов ничтожное количество, по сравнению с количеством комбинаций для пароля из хотя бы 8 символов :-)
Слова в английском образуются склейкой нескольких других слов. Количество уникальных корней не так уж велико. Если мы возьмем слово airplane, то это будет 2 словарных слова air и plane, то есть по стойкости это пароль из 2 знаков.
Китайский — вот жесть! 50 тыс. иероглифов.
В словаре Ожегова (русский язык) 57000 слов.
словарный запас обычного человека ограничен
А какой-такой GPU может генерить МИЛЛИАРД хешей в секунду??? По-моему, слишком большое преувеличение.
На что только современные видеокарты не способны. Говорят, они даже деньги добывают :-))
Про майнинг знаю, но мне что-то слабо верится, что можно именно сгенерить и проверить миллиард хешей в секунду. Хотя, на частоте 1 Ггц 300 процессоров может и могут сгенерить миллиард хешей. Вот только где они его держать будут? :)
специализированные криптопроцессоры, стоящие копейки, вполне могут, при этом создать их при современных средствах програмирования ПЛИС, может любой, прослушавший курс микроелектроники — infobez.com/article.asp?ob_no=1203 (пусть старая но интересная статья)
Атака на хеш это поиск коллизии. У атакующего нет цели найти исходный пароль, ему нужно найти строку, которая даст такой же хеш. Тут совершенно без разницы сколько раз SHA1 или любой другой метод применялся в цепочке. Поэтому автор таки не прав, стойкость не повышается.

А вот BCrypt с солью это пока сильно, т.к. BCrypt ограничивает скорость перебора (медленный по дизайну), а случайная соль борется со слабыми паролями.

Кстати, любые правила на пароль, к примеру «минимум одна цифра, буквы в разных регистрах и обязательная пунктуация» делают перебор проще, т.к. я могу отсеять пароли не подходящие под условие. Это реальный пример, когда любитель пытается просто логикой «повысить безопасность» вверенного в его руки объекта. К сожалению такие правила на пароль встречаются повсеместно, что конечно печально.

Не в тему, но все же: пароли зло. Тут ранее пробегала статья про фразы в 4 и более слов. Фразу гораздо сложней подобрать (при этом весь перебор по словарю ;)), за разъяснениями (энтропия) туда. Это пример, когда не любитель правильно подходит к анализу проблемы.
да-да, и комикс на XKCD тоже пробегал где-то тут :-)
Атака на хеш это поиск коллизии. У атакующего нет цели найти исходный пароль, ему нужно найти строку, которая даст такой же хеш. Тут совершенно без разницы сколько раз SHA1 или любой другой метод применялся в цепочке. Поэтому автор таки не прав, стойкость не повышается.
Разница есть, конечно. В любом случае, искать надо любой пароль, который пройдя через sha1(sha1(sha1…))) даст тот же хеш. Но при подборе этого пароля надо пройти все эти итерации этого sha1.

Мне только кажется, что сделать надо sha1(sha1(sha1(sha1…)))+salt), например.
sha1(sha1(sha1(sha1…)))+salt)

Тогда достаточно сгенерировать таблицу со значениями sha1(sha1(sha1…))) и дальше решать начальную задачу sha(pwd+salt), где pwd — sha1(sha1(sha1…)))
Возможно тогда делать sha1(sha1(sha1(sha1…sha1(pwd+salt))))+salt), но мне не нравится идея изобреения велосипеда без оценки его эффективности.
Для этого надо получить доступ к коду и знать на каком шаге добавляется соль.
Простите, что встреваю, но AFAIK в криптографии, да и вообще в IT security хорошим тоном является считать что атакующему известна вся информация о системе за исключением ключей, в том числе и все алгоритмы.
Узнать алгоритм очень просто — атакующему достаточно знать всего один пароль в системе, для этого обычно достаточно зарегистрироваться либо подобрать всего один пароль брутфорсом.
Сомнительное утверждение.

Вот подобрал ты пароль брутфорсом. Какие выводы ты можешь сделать об алгоритме?
Алгоритм — чёрный ящик, но я знаю всё, что у него на входе и на выходе (есть пароль и есть дамп базы), и обладаю достаточным количеством ресурсов, чтобы воссоздать сходный ящик.
Во-первых, пробегусь по этому топику, и посмотрю все варианты, с количеством итераций хеширования, алгоритмами хэширования, с добавлениями солей туда и сюда, перемешиваниями солей, перестановкой символов, xor и прочего. Вариантов сравнимо с тем, что пришлось подбирать брутфорсом.
Коллизии? Ой ли? И сколько же надо записей хранить, что бы покрыть все 160 бит SHA-1? Может таки не зря придумали словари и прочее?
> У атакующего нет цели найти исходный пароль, ему нужно найти строку, которая даст такой же хеш.

Вы не правы: если у атакующего есть база, то скорее всего ему и коллизия не нужна, т.к. с ненулевой вероятностью данные он достанет из базы и так, как уже говорилось выше, поэтому единственная цель «атаки на хеш» в подобном случае — все-таки узнать исходный пароль, т.к. он может подходить к другим ресурсам пользователя. В этом случае найденная коллизия скорее всего не подойдет, если на другом сервисе используется другой алгоритм хеширования.
Я использую sha1(salt+sha1(password)), причём в соль пихаю и непечатные символы, чтобы растянуть диапазон значений
Ответ не верный. Дело в том, что мне достаточно взять вычисленные хеши популярных паролей (а это sha1(password)) и довести их до нужного состояния зная вашу хеш функцию.

Тогда как для sha1(salt+password) у меня нет готовой таблицы. Ну и конечно соль должна быть индивидуальной, иначе толку никакого.
Хм, а и в правду, спасибо
А какая разница, в обоих случаях надо сделать 1 sha1 по всей таблице
Да, вы правы. Таблица с вычисленными хешами хранит и исходный пароль. В общем нужна индивидуальная соль. Ну и конечно sha1(password) в исходной формуле вообще никак не добавляет криптостойкости.
Эм? При чем тут алгоритм подписи?
Ну, как-бы это один из возможных вариантов соления сообщения ключом: HMAC(m,k) = H( k | H( k | m ))
Только сообщением m здесь будет соль, а ключом k — пароль, ибо H( k | m ) можно частичным применением хеш-функции превратить в Hk( m )
>> Как только мы начинаем использовать медленную хэш-функцию, у атакующего начинаются проблемы. Так, например, Bcrypt можно настраивать, делая его быстрее или медленнее.

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

>> Однако обратите внимание, что мы все еще не защищены от атаки по словарю.
А вы вообще от неё не защищены. Вернее пользователи с плохим паролем. Зачем мне сидеть вычислять ваши хеши, когда проще натравить ботнет на форму ввода пароля и подобрать пароль к нескольким юзерам. Мне не нужны все юзеры, этож не соревнование на то кто больше паролей раскроет. Пару паролей мне хватит.
> вас можно задосить на форме проверки пароля

Ну скажем, он не 1ккк хэшей в секунду будет просчитывать, а «всего лишь» 100к. Фиг ты заддосишь :-)

Ибо в любой момент в кластер аутентификации можно машин добавить.
>>Как только вы начинаете использовать медленную хеш-функцию у вас также начинаются проблемы, так как вас можно задосить на форме проверки пароля.
Защитить форму логина капчей и — вуаля.

>>Зачем мне сидеть вычислять ваши хеши, когда проще натравить ботнет на форму ввода пароля и подобрать пароль к нескольким юзерам.
А ботнет обладает средствами OCR и может дать нормальную скорость перебора паролей?
Кроме того, обычно базы хэшей утягивают, для дальнейшей продажи. Если нет целенаправленной атаки на конкретный ресурс/человека, то ваши несколько подобранных логинов/паролей никому нужны не будут.
Из всего прочитанного уяснил, что оптимальным будет SHA1(global_salt+SHA1(user_salt+pwd)), который для пущей надёжности можно ещё несколько раз SHA1 сделать.
Наверное только в том случае, если для злоумышленника добыть одновременно дамп, алгоритм и глобальную соль — не простая задача.

И сразу возникает вопрос, где хранить глобальную соль, если не в коде и не в базе?
Если случай не параноидальный — то хоть в конфиге, лучше в отдельном и неприметном (его могут забыть слить, если даже будут брать код). В других случаях можно вынести всю криптологику в другое место (например другой физический сервер с только локальным входом и закрытыми лишними портами/отключенными лишними службами), сделав некое подобие внутреннего (т.е. не доступного извне) крипто-API, обслуживающего запросы основной системы, и там же хранить свою соль. В любом случае зависит от задачи.
Для большинства систем подойдет формула из этого комментария.
Нет, это для того, чтобы радужные таблицы никакого рода нельзя было использовать (ни готовые, ни с вои посчитать) — только полный прямой перебор. Сейчас действительно часто встречаются описания взломов по таблицам. А в этой статье всё весьма доходчиво систематизировано.
Чтобы не хранить пароли в БД в открытом виде, обычно их хэшируют.
Если бы… Если говорить о сайтах, то добрая их треть имеет ограничения 8-12-20-30 символов на пароль. Что говорит либо о дурости разработчиков, сующих бездумные ограничения где ни попадя, либо тоже о дурости, но заключающейся в хранении паролей в открытом виде в БД.
А почему тогда не использовать неизвестную соль, т.е. добавлять к паролю например n неизвестных символов и при авторизации каждый раз подбирать их, но чревато досами всяческими
Это из серии организуй DDOS на свой сервер сам?
Это не говоря уже о том, что авторизация пользователя начнет занимать достаточно существенное время при n даже не доходящих до 10
Существует схема, которая не боится кражи базы паролей с сервера — Lamport hash chain. Другой вопрос, что мне неизвестны реальные продукты, в которых бы она применялась. Возможно, отпугивает необходимость вычислений на клиентской стороне. Или солёные хэши + многократное хэширование просто привычнее и проще для понимания.
Вот ещё интересная схема habrahabr.ru/blogs/web_security/121021/, хотя считать гораздо больше. Лэмпорт привлекает своей крайней простотой, хотя от MiM и от подбора не защищает.
Не нужно изобретать собственные алгоритмы, нет, правда.

Используйте:
Рекомендованная длина хеша.

Множественное хеширование слегка замедляет подбор пароля, но и снижает криптографическую стойкость (сужает выходное множество значений).
Шнайдер кстати подробно описывает этот постулат и хорошо аргументирует его в своей книжке «Практическая криптография», которую стоит хотя бы бегло пролистать каждому разработчику
За аргументами ходить далеко не надо. Очень часто, когда программист говорит, что он лучше знает, и реализовывает криптографию самостоятельно, находятся ошибки. Даже у экспертов.

Например, автор scrypt недавно ошибся в реализации AES-CTR и поставил под серьёзную угрозу безопасность чужих данных.
Благодарю за познавательный материал!
Sign up to leave a comment.

Articles