Comments 100
Обратите внимание, повышая сложность вычисления хеша, вы увеличиваете нагрузку на сервер, на котором он будет считаться. т.е. можно будет весьма эффективно досить портал, через логин форму.
Эта проблема решается очень просто — принимать не более 3/5/10 запросов на регистрацию в час/сутки с одного ip.
я и не говорил, что это нерешаемая проблема, а лишь обратил внимание на неё.
А принимая не более 3/5/10 запросов в t, вы можете прикрыть юзеров за проксями.
а мне думается что только после 1-й неудачной попытки нужно включать эту защиту на конкретный ID, с которого пытаешься логиниться, дабы злоумышленнику было сложнее подбирать.
Проблема будет не столько в регистрации, сколько в авторизации — ведь в ней вы используете ту же самую функцию
А что мешает поставить такое-же ограничение на количество авторизаций с одного ip?
Нужно понимать, что IP — это не ID конкретного пользователя.
Речь же вроде о вредительской нагрузке на сервер? Обычным пользователям такое ограничение не повредит, а вот блокировка по ip убережет сайт от ддоса через форму регистрации/авторизации если не на 100%, то на число близкое к нему. А юзать тысячи временных ip ради ддоса через форму авторизации — зачем? Есть более удобные цели для атак.
Ок, признаю ошибку.
С одного IP и одного ID юзера.

И блокировать только при очень большом количестве запросов за маленькое время. Начиная со второго-третьего входа в час использовать капчу.
По IP нельзя ограничивать регистрацию. Пользователи, сидящие через серые IP (wifi — adsl — свистки от сотовых операторов) после таких приколов могут и не суметь зарегаться.
Че не так?
Вот сидим мы втроем на одном сером айпишнике, я тетя Маша и дядя Вова. И эдакий гипотетический кулхацкер я запросы регистрации постоянные шлю. А тетя Маша и дядя Вова добропорядочные граждане, сидят и удивляются: а что это нас не пускает, какой-такой постоянный таймаут?!
Раньше мы хранили пароли через md5, но озаботившись проблемой обеспечения безопасности пользовательских данных (т.к. ввели систему платежей), решили использовать crypt(sha1*100)

Рост нагрузки был в пределах погрешности измерения.

А если вы собрались бороться с ddos, то просто отключите страницу, на которую идет атака.
Как вариант можно попросить пользователя ввести его логин/e-mail на который прийдет ссылка с входом по токену
это в случае с логином или у злоумышленика есть база e-mail пользователей сайта
ссылку на сайте поменяйте и перекиньте форму логина на другую страницу.

делов на 5 минут.
я думаю что в 99.99% случаев злоумышленнику проще будет выбрать другую страницу с более сильной нагрузкой на сервер где даже не нужно будет моделировать пост запрос
Вычислительные мощности современных серверов таковы, что при ддосе нужно не о load overage заботиться, а о ширине канала.
Хм, благодарю, очень интересно, не видел, потому что искал только PHP-реализацию
UFO landed and left these words here
Собственно, мои пять копеек
H = AES(K, IV, SHA(login)), где K — ключ равный SHA256(password), IV — вектор инициализации, равный MD5(login).
Да, CMAC-подобно.
а что, ссылка на этот ресурс приходила ко всем на почту? или может гугл на главной странице размещал эту информацию? Или все разработчики знают этот сайт? Какова причина по которой люди должны были прочитать эту статью?
Ну мне она попадалась бессчетное количество раз за последние два года.
Я использую хеш от пароля, соли пользователя, и соли сервера которая храниться в файле. Таким образом слив только базы не даст доступа к паролю.
он может слить базу не имея доступа к файлам например через инъекцию.
упоминать в контексте хранения паролей crc32 — это конечно позор…
В бою пользовался конструкцией:

$salt = hash('sha256', $email);
$hashingString = $salt. $password;
$pwdHash = hash('whirlpool', $hashingString);

Когда-то посчитал, что это одно из самых безопасных решений. А выбор алгоритмов далеко не случайный.
Сейчас слабо помню, но когда выбирал, выбирал таким образом, чтобы
а) каждый по отдельности был защищенным и не было возможности взломать его по таблицам или подобной фигне.
б) подбирались по длине. whirpool хорошо хеширует даже очень длинные пароли. А популярный мд5 быстро расходует свою вариативность. Или как оно там правильно называется.
А не проще чем замедлять генерацию пароля просто сделать таймаут некий полечком в базке например, прикрутить к пользователю и при неверной попытке авторизации выставлять его в N-секунд, скажем 5. А при следующих авторизацию просто читать таймаут этот, и если он еще не прошел — сразу отлуп давать.
Так и сервер грузить не будете излишними вычислениями 1кк хэшэй.
1кк хэшей и прочие замедляторы нужны не для того, чтобы замедлить авторизацию, а на тот случай, если злоумышленник сольёт базу с хэшами и начнет ее брутить. Тогда он будет вынужден на каждую попытку потратить не 1 мкс (условно), а 1 секунду.
Собственно, почему?
Все описанные в статье механизмы направлены на защиту как раз в случае утечки базы.
Потому что вероятность слить базу с хэшами и не слить все остальное стремится к нулю :)

Потому что если злоумышленник слил базу с хэшами — вы об этом не узнаете, и ничего не предпримите (в отличии от попытки брутфорса логина). Узнаете когда он ее поломает, а он ее поломает. Социальная инженерия убедительно побеждает любую криптостойкость. Ведь у истоков создания пароля стоит тетя Маша, которая или выдумывает пароли из головы, или записывает выданный ей не читаемый набор букв-цифр-спецсимволов на бумажку.

Хотите безопасности — отключите сервер от сети. Или накупите вот такого рутокен-web и всем пользователя раздайте. И SMS-КИ шлите с временным токеном при логине, как это банкиры практикуют. И таймауты сделайте, и 1000к генерацию хэшей подписей, и капчи. Но все равно гарантий нет. Хотите гарантий — купите тостер :)
Всегда считал, что нужно исходить из наихудших условий — того что у хакера есть полный рутовый доступ на сервер. И если с тем что он сделает в порыве бессильной ярости, после неудавшегося брутфорса паролей, мы ничего поделать не можем, то уж пароли наших юзеров хотя бы убережем.
А вам не кажется, что имея полный рутовый доступ на сервер хакер может например вписать код в ваш авторизационный скрипт (мы ведь про php говорим), который будет все входы пользователей в какой-нибудь лог складывать? И ему в таком случае вообще ничего подбирать не нужно.
Ну, с этим программно невозможно бороться.
Разве что написать:
<?php define ('true', false); ?>

где-нибудь в хорошо запрятанном файле, и писать весь код учитывая это. У постороннего человека, пытающегося что-то отредактировать ничего, соответственно работать не будет. ;)
И как вы это будете использовать?
<?php define ('true', false); var_dump(true);

Результат:
Notice: Constant true already defined in file.php on line 1
bool(true)
/$ php -r "define('0', true); var_dump(0);"
int(0)

Вы код в тетрадке пишете? Запускать его вообще пробовали?
По-моему, весь этот топик со всеми вашими комментариями — большая, хорошо продуманная шутка. Если так, поздравляю — шутка удалась. Если нет… печально, да.
Еще один этап защиты будет если при авторизации/регистрации сам пароль на сервак вообще не отправляется, а шлется уже хеш от него.
Я например делал так: джаваскриптом вычислял easyHash = md5( pass + easySalt ) и запросом на сервак отправлялся уже easyHash. На серваке же уже после создания в бд пользователя делал примерно finishHash = md5( userId + strongSalt + easyHash ) и уже его хранил в бд.
Это немного спасет от сниффалок трафика. А вынеся js файл отвечающий за отправку логина пароля на какой нить code.google.com мы усложним жизнь чуваку получившему рут на нашем серваке, по крайней мере ему придется потрудится чтобы написать свою форму и свой обработчик и чтобы старая схема не сломалась и пользователи ничего не заподозрили.
Вы правы, это в любом случае безопаснее.
Еще безопаснее если сравнение идет не по запрошенному из базы хэшу, а путем вызова хранимой процедуры, в которой и сама база еще хэш от того что ей дает сервак вычисляет и лишь затем сравнивает.

Но в данном случае речь шла о рутовом доступе, и про считывание пароля я привел в качестве примера. В этом случае хэш не поможет, поскольку если я на стороне сервера считал хэш, ничто не мешает мне на стороне клиента слать вам прямо хэш напрямую через POST запрос (минуя промежуточные вычисления из оригинального пароля). Да, я не буду знать оригинальный пароль, но доступ получу.
Для того чтобы не взломали пароли на других сайтах. Для этого и делаем
Не нужно изобретать собственные алгоритмы. Используйте:

bcrypt,
PBKDF2 с HMAC-SHA256 (рекомендовано NIST в SP 800-132),
scrypt.

Рекомендованная длина хеша.

Множественное хеширование слегка замедляет подбор пароля, но и снижает криптографическую стойкость (сужает выходное множество значений).
Статическая соль и тому подобные конструкции могут служить достаточно хорошо… пока структура этих конструкций и соль хранятся в тайне. Если же злоумышленник вызнает секрет хэширования — он с легкостью сможет модифицировать под него свою «радужную таблицу»
Что подразумевается под лёгкостью? Как можно модифицировать таблицу быстрее, чем повторным вычислением хеша для всех значений (т.е. быстрее того же брутфорса)?
Видимо автор подразумевает что со статической солью все же проще, чем с динамической. Наверное имеется в виду относительная легкость.
Имелся в виду конечно язык «Каннада»

Примерно так:
ನಾನು ಈ ಬರೆಯಲು ಗೂಗಲ್ ಅನುವಾದಕ ಬಳಸಿ
Как-то вы неаккуратно о crc32: не стоит ставить его в один ряд со всякими md5, sha1 и проч. — они являются криптографическими хэш-функциями, а crc32 вроде как для контроля целостности данных. Если его кто-то использует не по назначению, это его проблема. И здесь не только проблема в том, что он 32-х битный, а то, что легко подвержен атакам на критрохэш-функции. Да и вроде не устаревший он, а вовсю применяется по назначению. Несмотря на солидный возраст, crc32 все еще обнаруживает одиночные ошибки, двойные ошибки и ошибки в нечетном числе битов.
Это будет называться не брутфорс а поиск коллизии, это раз. Уникальная соль это бред — где вы будете её хранить? в базе? С crc32 вы тоже загнули.

Далее «использование алгоритма Blowfish» — брееед. Хеш на то и любим разработчиками, что занимает фиксированное место в базе. Blowfish это симметрический шифр, результат которого мало того что может конфликтовать с кодировкой базы, так ещё и вовсе не поместится в строку.

Самый простой и проверенный временем вариант — md5($password. $sault). Однако надо знать, что часто через SQL-инъекции можно получить доступ даже к файловой системе.
Далее «использование алгоритма Blowfish» — брееед.


А ничего, что реализация bcrypt основана на blowfish?
где вы будете её хранить? в базе?

В ней, родимой. А что?

Blowfish это симметрический шифр, результат которого мало того что может конфликтовать с кодировкой базы, так ещё и вовсе не поместится в строку.

На основе блочного шифра элементарно делается хеш-функция.
MD5 вообще-то тоже 16 байт выдает, которые в кривых руках будут конфликтовать с кодировкой базы.

md5($password. $sault)

Не, стаття, конечно, целиком из баянов состоит, но это не повод размахивать в комментариях своей губной гармошкой как последним словом аккордеоностроения.

Однако надо знать, что часто через SQL-инъекции можно получить доступ даже к файловой системе.

А еще в огороде бузина и в Киеве дядька.
for ($i = 0; $i < 1000; $i++) {
$hash = sha1($hash);
}

Что за бред?

Если вы хотите замедлить авторизацию не страдайте херней, а делайте увеличивающийся таймаут, записываемый в доп поле таблицы. Правда тогда есть риск, что юзера тупо заддосят, чтобы он не мог авторизоваться.
Если вашу базу и код слили, то это замедление не спасет ну ни разу.
Почти 200 человек добавили статью в Избранное.
Удивительный Хабр.
Респект за статью! Уровень вовлеченности в тему сильно больше, чем у многих «маститых» авторов Хабра.

PS: Гляньте на дату рождения топикстартера в профиле! Горжусь, что у нас такая молодежь осталась, а не только «сходить за клинским»…
Два небольших замечания.

1. К безопасности собственно сайта безопасность хранения паролей имеет весьма опосредованное отношение. И выстрелит раззве что в случае, если злоумышленнику удалось получить дамп БД. Разумеется, это не повод не хэшировать пароли, но просто почему-то всегда в разговоре о паролях подразумевается безопасность сайта, а не сохранность собственно паролей.

2. Множество «короткие и простые пароли» НЕ тождественно множеству «8-символьный пароль, который будут ломать 7 лет». Пароль «12345» будут ломать пару секунд. Так что все эти «тыщу раз захешируем» НЕ являются альтернативой запрету простых паролей.
2. При наличии соли и медленного алгоритма даже перебор словарных паролей сильно затянется. Как пример можно привести запароленные rar-архивы, которые крайне медленно брутятся.

И за это время, если на сервере настроено крутое логирование озаглавливающее подозрительные запросы, можно успеть принудительно поменять пароли всем пользователям и залатать дыру.
Наличие [известной] соли вообще никак перебор не замедляет. И словарные пароли, при скорости 1000 паролей в секунду, подбираются как раз за секунду.

Плохой пароль защитить никаким хэшированием НЕВОЗМОЖНО.
А зачем тысячу раз переписывать хэш? Не лучше ли дать процессу поспать с точки зрения быстродействия — тогда нагрузка на сервер будет меньше. Я не спец в ПХП, но здравый смысл подсказывает…
Нет. Тогда злоумышленник зная процес хеширования просто уберёт функциию sleep из алгоритма. А так — он реально будет тратить бОльшее время на взлом каждого пароля.

Процитирую себя же:
Перебор 1000 паролей на компьютере средней мощности должен занимать больше 1 секунды.
Всё равно не совсем понял (извините, туплю), можете ответить в ЛС? Я так понимаю по условию задачи у злоумышленника нет доступа к коду на стороне сервера и, соответственно, возможности его имзенить — он просто стучится в веб-сервис, который записывает пароль в базу, предварительно обработав аглоритмом F(password). В данном случае ведь неважно как замедлять, разве нет?

Ещё раз, простите если вопрос слишком глупый — но очень хочется разобраться.
Ну я думал, что у злоумышленника есть база и известный алгоритм. Тогда выходит так:
Можно взять как пример какой-то известный движок, код которого злоумышленник может найти.
Тут становится известен алгоритм генерации хеша пароля.

Далее, сливается база с уязвимого сайта и используя известный алгоритм нужные хеши перебираются, что бы узнать исходный пароль. Часто нужен пароль, например, админа, что бы открыть себе бОльшие возможности, чем просто копия базы.

А если так как у вас, то тогда лучше даже не замедлять, а просто ограничивать кол-во запросов на авторизацию в минуту с одного ip, например.
Хороший получился пост! Тут тебе и всевозможные методы защиты беспечных пользователей (да и что говорить — сайтов в целом), и методы защиты от хакеров, и методы взлома, куча полезных ссылок! Нет, ну однозначно в избранное!
Беспечных пользователей этот пост не защищает никак, сайты — весьма опосредованно, а первая ссылка вообще никакого отношения к теме не имеет.
Ну я имел в виду не только пост автора но и (даже в большей степени) все комментарии к нему.
Вопрос: ведь если слить базу, с паролями и с солью, то нам ведь все равно нужен алгоритм хеширования пароля, чтобы производить брутфорс?
То есть если я напишу, что-то типа: md5($p. sha1(md5($p). md5($salt)). $salt), то нам необходим ещё и этот алгоритм и доступ к файлам, а просто база нам ничего не даст?
А чего мелочиться, можно еще и символы хеша местами поменять. Допустим, сначала все четные, потом все нечетные. И после пятого — восьмой вставить. «Никто ведь не допетрит, Гендальф!»(с)
То, что вы предлагаете, называется Security through obscurity — безопасность через неизвестность.
использую, sha256, ИМХО соль уже лишнее подобрать коллизию на такой хеш в данный момент практический нереально
Такое чувство, что комментарии пишут одни люди (у которых уже голосов не осталось, а голосуют совсем другие.
Всё просто — ставить задержку в одну секунду перед попыткой авторизации (т. е. банальный sleep(1) в пхп). И тогда никто и никогда не забрутфорсит ни одного пароля.
непонимание как обсуждаемого вопроса, так и технологии в целом детектед
Only those users with full accounts are able to leave comments. Log in, please.