Pull to refresh

Comments 227

Да хоть с солью. Толку от них, если половина — словарные или распространённые.
С солью нужно только брутить, пусть и по словарю. Без соли вполне можно юзать готовые «радужные таблицы».
Хеши паролей без примеси (соли) уникального ключа.
Вообще странно, что им стоило сделать вместо sha1(password) -> sha1(sha1(salt)+password)?
sha1(salt+sha1(password)), не?
а почему по другому нельзя?
А смысл соль в sha1 загонять?
Чтобы простые пароли по рейнбоу-таблицам не кололись.
Соль то зачем шифровать? Это же только ресурсы процессора зря расходовать :-)
А-а-а, вы об этом. Недопонял. Да, sha1(solt+pass) было бы минимально достаточно. Для параноиков — sha1(solt+sha1(pass)) :-)
Не знаю как sha1, но md5 лучше не оборачивать друг в друга, иначе коллизии могут быть
md5 нынче уже не кошерен. Его желательно и вовсе не использовать.

Там про бикрипт чуть ниже пишут правильные вещи.
С чего вдруг у MD5 появятся коллизии если её оборачивать друг в друга? Это чушь, друг мой :-). Хотя коллизий там и так достаточно. Но всё равно в данном случае стойкость не уменьшится от добавления лишней итерации алгоритма.
Хотя вру, стойкость конечно уменьшится если у тебя пароль длиннее 32 символов и содержит различные цифры и буквы :-).
Еще как стойкость уменьшиться! Чем больше раз вы оборачиваете md5 в md5, тем больше вероятность того, что хэш вашего мега-пароля совпадет с хэшом простого пароля из радужных таблиц. Ну а его (просто пароля) будет достаточно для входа в систему. ведь в базе хранится только хэш, а не пароль.
С чего это вдруг эта вероятность больше?) Ну урезали пароль до 32х шестнацатиричных цифр, да дописали к нему соль. Вероятность наткнуться на коллизию с коротким паролем не изменилась абсолютно.
Для параноиков — salsa20(salt+salsa20(pass)).
Для параноиков — только scrypt или PBKDF2 c параноидальными параметрами. :)
Чтобы увеличить длину пароля. Экономить на этом это экономить на спичках.

salt = hash('sha256', email); // user_id может даже лучше. Так как мыло может поменяться и надо будет дополнительно перехешировать ==> писать дополнительный код. 
pwd_hash = hash('whirlpool', salt .password);

Вот пример элементарной, нормальной соли

А почему whirlpool кстати?
Есть несколько хороших алгоритмов шифрования. Whirpool один из них.

Посмотрите на эту таблицу.

Почему сначала SHA-256? Чтобы соблюдать длину. Надо чтобы длина пароля была короче чем хэш. А whirpool дает на выходе 512 символов.

Почеме whirpool, а не SHA512?

В будущем, если сломают алогоритм SHA-2 (тоесть SHA256 SHA512), то оборону будет держать вирп.
Если сломают whirpool, то оборону будет держать SHA256. Если оба — я сделал все что мог, кто может, пусть сделает лучше.

Как-то так (:
Да, ясно, логично и хорошо. Не параноидально, но хорошо. :)
Да и простое как лопата. Просто знай себе поменяй с:

salt = hash('md5', email); 
pwd_hash = hash('md5', salt .password);


на:
salt = hash('sha256', email); 
pwd_hash = hash('whirlpool', salt .password);

и в результате имеем сильно устойчивый хеш.
Пароли не нужно хэшировать. Пароли нужно шифровать.
Да хоть какую-то соль бы дали.
Тоже, мто помешало использовать brcypt и альтернативные варианты.
Пф. Им просто использовать соль было лень, а вы говорите — bcrypt.
Ну не все так однозначно, есть много подобных bcrypt хешей: PBKDF2, scrypt и т.д.
Для мультимилионных корпораций не проблема дописать нужный функционал. Я пишу в основном на Руби, там есть соответствующий джем. Для Пайтона есть нужный пакет.
Ну, про мультимиллионные корпорации мы все в курсе — LinkedIn хранит несолёный SHA1, Sony вообще хранила plaintext… К сожалению, безопасностью склонны интересоваться более мелкие компании.
На самом деле разница между bcrypt, scrypt и PBKDF2 на данном этапе развития технологии не очень существенна.
Основной тезис при выборе, например, между PBKDF2 и bcrypt в том, что первый хорошо изучен и долгое время исследовался на наличие коллизий и уязвимостей а также использовался в коммерческом ПО (вроде FileVault).
Просто PBKDF2 — это стандарт (PKCS #5 v2.0 (RFC 2898)), а bcrypt и scrypt — просто хорошие алгоритмы.
И если кстати говорить про «исследованность» — то AFAIK bcrypt исследован гораздо лучше чем scrypt.
У scrypt'а другой плюс — гораздо большие траты памяти при переборе, скажем так в десятки раз, с другой стороны это минус для продакшена — частая авторизация (как успешная, так и нет) может стать своеобразной формой DoS'а.
Да я в курсе, в курсе.
Логично что компании должны использовать PBKDF2 как наиболее простой и легкореализуемый стандарт — ан нет, не тут то было.
Может, правильнее, Use bcrypt(bcrypt(bcrypt(bcrypt(bcrypt(bcrypt(bcrypt(password)))))))
Минусуют наверно обиженные сотрудники linkedin'а :-). Или просто чуваки с убогим чуством юмора.
А ещё, afaik, хеш от хеша хуже чем просто хеш. Число коллизий увеличивается. Хеш от хеша от хеша хуже их обоих. Ну и т.д.
Ох, ещё один. И где вас такому учат?.. Хеш от хеша ни чем не хуже хеша от пароля в плане наличия коллизий. В нормальных криптосистемах, например bcrypt, используется не одна, а большое количество итераций (50, 100, 1000, зависит от сложности алгоритма, мощности сервера и паранои админа). Это позволяет увеличить в N раз сложность перебора.
Щас я объясню на своём детском математическом :)

f() — хеш функция
P — множество всех паролей
H — множество всех хешей

f(P) -> H
f(H) -> H1

f(f(P)) не хуже чем f(P) только тогда, когда H = H1. Т.е. хеш функция переводит свои хеши в хеши без коллизий.

С точки зрения безопасности принято считать верным пессимистичный вариант. Поэтому пока не доказано, что хеш функция переводит хеши в хеши без коллизий считается, что они там есть. А значит в хеше от хеша от хеша от хеша… они накапливаются.

Где ошибся?
> f(f(P)) не хуже чем f(P) только тогда, когда H = H1

Ммм? Когда f(f(p)) = f(p)? f это хеш-функция которая не делает ничего?

И что должно значить «хеш функция переводит хеши в хеши без коллизий»? Что хеш-функция должна магическим образом избавляться от коллизий если вычисляет хеш от хеша? Хеш ничем не лучше и не хуже пароля от которого он получен в плане коллизий.

> они накапливаются

Нет, не накапливаются. Нам всё равно, какие были коллизии на промежуточных итерациях, они никак не помогут сломать хеш. Полезны только коллизии на N'ном этапе.
Не на N-ном а на 1-ом этапе, конечно.
> Ммм? Когда f(f(p)) = f(p)? f это хеш-функция которая не делает ничего?

моя условная запись «H = H1» — означает что там одно и то же число разных вариантов. Это вроде бы называют мощность множества. К примеру в первом 2^160, значит и во втором тоже 2^160. Т.е. любой хеш из H переводится в свой собственный хеш из H1.

Очевидно мощность H1 может быть или равна или меньше мощности H. Больше, не может.

И только если мощность равна, только тогда f(f(P)) выдаст тоже самое число разных вариантов, что и f(P), а значит и тоже самое число коллизий.

> Что хеш-функция должна магическим образом избавляться от коллизий если вычисляет хеш от хеша? Хеш ничем не лучше и не хуже пароля от которого он получен в плане коллизий.

Вот в этом и суть. Каждая последующая f() работает с результатом от предыдущих вызовов (т.е. уже накопившиеся коллизии никак не уменьшатся) и при этом добавляет свои.

Коллизии на каждом этапе суммируются.
О, спасибо, там более правильно описывается, почему мощность снижается. И что количество коллизий(!!) у хеша от хеша больше, чем просто у хеша.

Но также я согласен, что с точки зрения как бы посильнее затруднить брутфорс, можно разменять мощность множества на время вычисления.
Я не очень силён в математке, но мне кажется что моё объяснение проще:
Если
P — множество всех паролей
H — множество всех хешей
f() — хеш функция
и f(P) -> H — множество значительно уже чем P, потому априори вероятны колизии.
f(H) — получим множество T которое ещё уже.
А дальше простая логика, если в H возможны колизии, то в T их будет ещё больше, так как P проэцируется в ещё меньшее множество и вероятность колизий растёт.

Как-то так, если неправ поправьте.
Бесконечная итерация, написанная правильно, может работать условно бесконечно, а вот бесконечная рекурсия — обычно ограничена памятью. Видимо этот недостаток предложенного варианта оскорбляет истинных параноиков ;-)
Компилятор такие вложенные вызовы разворачивает линейно, никакой рекурсии тут нет.
Это если код написан грамотно в виде tail recursion. Но вообще, зачем отдавать такую координальную оптимизацию компилятору? Лучше самому написать итерацию, чтобы всё было более явно. // питонист
Ээээ. Какая к чёрту хвостовая рекурсия? Вы вообще хорошо понимаете, что такое рекурсия? Это когда функция вызывает сама себя. Здесь же налицо набор последовательных вызовов функции извне с использованием результата предыдущих. Т. е. что-то типа
Тут — нет, рекурсия в самой идее )
Вот кстати не понимаю я на счет соли.
Видел реализации разных юзер-классов, где для паролей используется соль, но она храинтся в базе же, в соседней колонке. Какой смысл-то в этом? В том, что неизвестно, как эта соль добавлена к паролю?
В том, что таких хэшов не будет в радужных таблицах
имеет смысл погуглить «радужные таблицы» и все станет понятно
Есть таблицы, которые уже содержат пары вида «хэш»=«пароль» (как правило, самые распространенные). И если у вас сольют базу, то будет трудно расшифровать даже пароль «qwerty», только брутфорсом.
Да, я через несколько минут догадался, что вы имели ввиду)
Надо больше спать, а то совсем торможу)
Вот тут пишут, что радужные таблицы щас малоактуальны — на первое место все таки выходит скорость брутфорса, а в этом последнее время сильно помогают GPU — а значит, нужно увеличивать сложность хеша — bcrypt, scrypt, PBKDF2 etc.
Хотя с другой стороны — кто мешает использовать GPU для составления радужных таблиц?..
Проблема с радужными таблицами в том что они очень большие их нужно где то хранить, а любой IO на порядки медленей CPU/GPU.
Нет. Смысл, что для одинаковых паролей — хеш будет разным.
А это значит, что нельзя будет для каждого qwerty сразу найти всех пользователей с таким паролем
А, ясно. Т.е. криптоустойчивость не увеличивается, но «массовость атаки» снижается.
Спасибо
еще увеличивается длина пароля — если он станет больше 30 символов, никакие радужные таблицы не спасут
Это если солить с помощью какого-то случайного числа или хотя бы даты и времени…
Это следует из определения соли. Максильмальная энтропия.
Мда. Chief Technology Officer, интересуетесь хайлоуд проектами и т.д.

И вы спрашиваете, в чем разница между добавлением соли и ее отсутствием?

* пауза *

Ну, разница том, что без соли, словарь можно прогнать ОДИН раз и дальше смотреть, есть ли такой хеш в базе:

sha1(dict_word1);
sha1(dict_word2);
...
sha1(dict_wordn);

База готова, мы знаем пароли всех пользователей, со словарными паролями.

В случае соли:
sha1(user1salt+dict_word1);
sha1(user1salt+dict_word2);
...
sha1(user1salt+dict_wordn);
//User 2
sha1(user2salt+dict_word1);
sha1(user2salt+dict_word2);
...
sha1(user2salt+dict_wordn);


Ура, мы возможно подобрали пароли к двум пользователям.
Я так понимаю, минус в пост и минус в карму это от автора, да? ;)
смотря кого вы в данном случае назіваете автором. если меня – то нет. мне, кстати, тоже вкатили))
======
нет, вы не подумайте, я не храню пароли в чистых хешах)) я с ними по-своему заморачиваюсь. но смысл рандомной соли мне почему-то не открывался (я рассматривал ее всегда с точки зрения единичного пароля, а не подбора по всей базе).
короче, и на старуху бывает проруха)
Ну я думал вы обиделись)
==
Ну как для бы да. С точки зрения одного пароля, — один хрен. С точки зрения базы, уже совсем другие расклады (:
спасибо за внятное объяснение)
Можно было бы сделать:

$salt = '$2a$10$'.substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(),mt_rand()))), 0, 22). '$';
$hashed_password = crypt($password, $salt);

И всё, суперпрочно зашифровано.
Мдас… несоленый sha-1 на подобном ресурсе — это просто «двойка» разработчикам.
Мда, определенно bad day для LinkedIn.

Сначала наехали, что конфиденциальную инфу с айфонов стягивает, а теперь и пароли юзеров просрали :(
Было бы веселее, если бы они потеряли базу паролей от почты пользователей.
Они при регистрации просят дать им пароль от почты, что бы просканировать записную книжку. К счастью, опционально.
маловероятно, что этот пароль сохраняется и не удаляется после сканирования.
по крайней мере, я бы так не делал.
«а ещё я бы пароли солил». Но при всей маловероятности их «несоления» — выпал именно такой расклад. Вероятность чего-то таки не значит факт чего-то, особенно если вероятность строится по параметрам напрямую совершенно не связанным с предметом оценки.
пойду-ка и на почту сменю пароль :)
В очередной раз убеждаюсь, как же хорошо иметь двухэтапную аутентификацию в gmail и одноразовые пароли для сторонних сайтов и програм.
там утекло пароли/логины? или только пароли?
Ну наверное и логины тоже, иначе как пользователи могут подтверждать, что это их хэш.
Может так?
grep -qF `sha1 -s mypassword` passwords.txt && echo Found
«Такой пароль уже использует пользователь Misha. Пожалуйста, придумайте другой пароль.»
У хакеров угнавших БД они наверняка есть.
UFO just landed and posted this here
Даже я, относительно новичок в вебе делаю так:
function hashUserPassword($nick, $pass) {
	$salt = "C++0x FOReVEr i LovE_iT";
	return md5( sha1($nick)+sha1($pass.$salt) );
}


Незнаю, насколько это правильно, может подскажите?
Соли для пользователей должны различаться
Ясно что некрасиво, но по коду соли как раз различаются для пользователей.
имел в виду хеши, при одном и том же пароле у разных пользователей
как это зачем? Иначе оно в радужных таблицах будет. Смотри комментарии выше
Расскажите мне, где взять радужную таблицу для постоянной соли вида C++0x FOReVEr i LovE_iT.
Если соль одинаковая, то это таблицу, ну, может, за час сделать можно. А если соль разная, то уже только грубым брутфорсом.
за час? ну-ну. поищите на хабре статью по времени генерации радужных таблиц, — года там, а не часы.

и кстати, в данном случае за соль можно считать ник пользователя, вполне надежно, хотя и как-то не красиво.
Очевидно, что зависит от размера таблицы. Для средних масштабов хватит и часов
очевидно, что таблицы «средних размеров» абсолютно бесполезны, вероятность содержать нужные строки (то бишь чьи-то пароли) для них около нуля.

и для одного частного случая генерить таблицы всегда дольше, чем прогнать прямой перебор по тем же строкам, в не зависимости от «масштабов».
Ну для такого таблиц конечно нет.
Радужную таблицу для такой соли никто строить не будет. Брутфорс эффективнее.

Другой вопрос, что при одинаковой соли одинаковые хэши у одинаковых паролей — вот это проблема для юзеров с простыми паролями.
Ну так в примере кода еще и никнейм пользователя добавляется — поэтому пароли одинаковыми не будут. Зачем там в таком случае еще и просто соль добавляется — другой вопрос. :)
Сам себя опровергну.
Точнее так — статическая соль лучше чем ее отсутствие (хотя и ненамного), юзернейм в качестве соли лучше статической соли, но плох для тривиальных юзернеймов, поэтому лучше всего случайная соль на каждого пользователя.
(в серверных делах не силён)
Как хранить базу солей?
Количество использований хэш функций не усиливает защиту пароля. А если уж, тогда хотябы раз 50, что бы на один пароль в 50 раз больше вемени ушло.
Если верно помню, то чем больше вложенность md5 тем больше риск коллизии.
Ты уже третий в этом топике говоришь это весьма спорное утверждение. Откуда информация? :-)
Но по сути конечно же вы правы — для затруднения пароля нужно использовать многократное хеширование. Криптостойкость хеша снижается, но медленне чем нарастает сложность брутфорса.
50 итераций MD5 вроде бы использовалось когда-то давно в какой-то операционной системе как стандартный алгоритм хеширования паролей. 50 это лучше чем 1.
Можно предположить, что риск коллизии увеличивается незначительно по сравнению с трудоёмкостью подбора
Это неправильно потому что нужно использовать стандартные средства, а не изобретать велосипед. Но вообще вроде бы вполне себе хеш-функция с ником в роли соли.
Скачал, проверил, свой хэш не нашёл.
disk.yandex.net?
А это вообще точно яндекс?
По whois'у похоже, что нет.
Я думаю это все — увод яндекс-аккаунтов.

Аккуратнее, не авторизируйтесь в форме по ссылке!
[REGISTRANT]
Organisation Name: YANDEX LLC
Contact Name: Tatiana Bakharevskaya
Address Line 1: 16 Lva Tolstogo str.,
Address Line 2:
City / Town: Moscow
State / Province:
Zip / Postcode: 119021
Country: RU
Telephone: +7.4957397000
Fax:
Email: noc@yandex.net

???
Странно, у меня другое:

Domain Name: YANDEX.NET
Registrar: SAFENAMES LTD
Whois Server: whois.safenames.net
Referral URL: www.safenames.net
Name Server: NS1.YANDEX.NET
Name Server: NS2.YANDEX.NET
Status: clientDeleteProhibited
Status: clientTransferProhibited
Updated Date: 03-may-2012
Creation Date: 14-nov-2000
Expiration Date: 14-nov-2013

Не нашел никаких YANDEX LLC, и слегка напрягает другой регистратор.
Да ладно!
Whois Server Version 2.0

Domain names in the .com and .net domains can now be registered
with many different competing registrars. Go to http://www.internic.net
for detailed information.

   Domain Name: YANDEX.NET
   Registrar: SAFENAMES LTD
   Whois Server: whois.safenames.net
   Referral URL: http://www.safenames.net
   Name Server: NS1.YANDEX.NET
   Name Server: NS2.YANDEX.NET
   Status: clientDeleteProhibited
   Status: clientTransferProhibited
   Updated Date: 03-may-2012
   Creation Date: 14-nov-2000
   Expiration Date: 14-nov-2013

>>> Last update of whois database: Wed, 06 Jun 2012 14:30:00 UTC <<<

NOTICE: The expiration date displayed in this record is the date the 
registrar's sponsorship of the domain name registration in the registry is 
currently set to expire. This date does not necessarily reflect the expiration 
date of the domain name registrant's agreement with the sponsoring 
registrar.  Users may consult the sponsoring registrar's Whois database to 
view the registrar's reported date of expiration for this registration.

TERMS OF USE: You are not authorized to access or query our Whois 
database through the use of electronic processes that are high-volume and 
automated except as reasonably necessary to register domain names or 
modify existing registrations; the Data in VeriSign Global Registry 
Services' ("VeriSign") Whois database is provided by VeriSign for 
information purposes only, and to assist persons in obtaining information 
about or related to a domain name registration record. VeriSign does not 
guarantee its accuracy. By submitting a Whois query, you agree to abide 
by the following terms of use: You agree that you may use this Data only 
for lawful purposes and that under no circumstances will you use this Data 
to: (1) allow, enable, or otherwise support the transmission of mass 
unsolicited, commercial advertising or solicitations via e-mail, telephone, 
or facsimile; or (2) enable high volume, automated, electronic processes 
that apply to VeriSign (or its computer systems). The compilation, 
repackaging, dissemination or other use of this Data is expressly 
prohibited without the prior written consent of VeriSign. You agree not to 
use electronic processes that are automated and high-volume to access or 
query the Whois database except as reasonably necessary to register 
domain names or modify existing registrations. VeriSign reserves the right 
to restrict your access to the Whois database in its sole discretion to ensure 
operational stability.  VeriSign may restrict or terminate your access to the 
Whois database for failure to abide by these terms of use. VeriSign 
reserves the right to modify these terms at any time. 

The Registry database contains ONLY .COM, .NET, .EDU domains and
Registrars.
Safenames - Experts in Global Domain Management and Online Brand Protection

Domain Registration in over 760 different extensions
Enterprise Domain Management since 1999
Mark Protect™ Online Brand Monitoring and Enforcement
Domain Consulting and Strategy
Domain Name Acquisition
Domain Disputes and Recovery

Visit Safenames at www.safenames.net
+1 703 574 5313 in the US/Canada
+44 1908 200022 in Europe

Domain Name: YANDEX.NET

  [REGISTRANT]
    Organisation Name: YANDEX LLC
    Contact Name:      Tatiana Bakharevskaya
    Address Line 1:    16 Lva Tolstogo str.,
    Address Line 2:    
    City / Town:       Moscow
    State / Province:  
    Zip / Postcode:    119021
    Country:           RU
    Telephone:         +7.4957397000
    Fax:               
    Email:             noc@yandex.net

  [ADMIN]
    Organisation Name: Safenames Ltd
    Contact Name:      International Domain Administrator
    Address Line 1:    Safenames House, Sunrise Parkway
    Address Line 2:    
    City / Town:       Milton Keynes
    State / Province:  Bucks
    Zip / Postcode:    MK14 6LS
    Country:           UK
    Telephone:         +44.1908200022
    Fax:               +44.1908325192
    Email:             hostmaster@safenames.net

  [TECHNICAL]
    Organisation Name: International Domain Tech
    Contact Name:      International Domain Tech
    Address Line 1:    Safenames House, Sunrise Parkway
    Address Line 2:    
    City / Town:       Milton Keynes
    State / Province:  Bucks
    Zip / Postcode:    MK14 6LS
    Country:           UK
    Telephone:         +44.1908200022
    Fax:               +44.1908325192
    Email:             tec@safenames.net

The Data in the Safenames Registrar WHOIS database is provided by Safenames for
information purposes only, and to assist persons in obtaining information about
or related to a domain name registration record.  Safenames does not guarantee
its accuracy.  Additionally, the data may not reflect updates to billing
contact information.

By submitting a WHOIS query, you agree to use this Data only for lawful purposes
and that under no circumstances will you use this Data to:

(1) allow, enable, or otherwise support the transmission of mass unsolicited,
commercial advertising or solicitations via e-mail, telephone, or facsimile; or
(2) enable high volume, automated, electronic processes that apply to Safenames
(or its computer systems).  The compilation, repackaging, dissemination or
other use of this Data is expressly prohibited without the prior written
consent of Safenames.  Safenames reserves the right to terminate your access to
the Safenames Registrar WHOIS database in its sole discretion, including
without limitation, for excessive querying of the WHOIS database or for failure
to otherwise abide by this policy.  Safenames reserves the right to modify
these terms at any time. By submitting this query, you agree to abide by this
policy.
У LinkedIn больше пользователей больше чем 6.5 миллионов.
У меня есть такое предположение, что у многих пользователей может быть одинаковый пароль, и поэтому паролей в базе меньше. Во всяком случае в этом файле все хэши разные:

$ wc -l combo_not.txt
6458020 combo_not.txt
$ sort combo_not.txt | uniq | wc -l
6458020


P.S. Ох и странно себя ведут горячие клавиши на Хабрахабре!
UFO just landed and posted this here
Черт, мой пароль и правда есть. Неприятно.
А насколько сложный, если не секрет, он был? Могло ли так получиться, что это не ваш пароль?
Я свой нашёл.

Пароль был в ввиде:

«Xxxxxxyyyyyyyynn»
Ну, на 6.5 миллионов вполне мог совпасть. Ладно, послушаем остальных :-)
Не думаю. Xxxxxx — довольно индивидуальная фраза, как «LiFu2d».
А, я думал всего 2 буквы и 1 цифра.
Там три отдельных фразы.
Если верить YC — мой пароль не сломали.
Пароль был G%M«1$PNE@

Есть вероятность, что у кого-то еще стоял такой же, но я не думаю, что она велика.
И конечно, этот пароль у меня был только на linkedin.com
напротив, очень даже есть, даже без нулей в префиксе, целиком.
хеш — 083ed3f0843c71b7517e19dc3a31746b10d896f8, если считать, что хабр умело заменил открывающую двойную кавычку.
Мдаа, и я свой нашёл. Пароль был не самый простой.
А теперь нашёл. В общем, ищите последние символы хеша, многие первые затёрты нулями.
Поясняю: допустим, ваш пароль «secret», sha1(«secret») == «e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4». Ищем в файле строчку «ecd1ae84f75caaa474f3a663f05f4» и находим:

% grep ecd1ae84f75caaa474f3a663f05f4 combo_not.txt
00000a1ba31ecd1ae84f75caaa474f3a663f05f4
Вообще, очень странные там хеши. Они не похожи на sha1, больше напоминает md5 с каким-то префиксом.
Скорее всего, в архиве много хешей за разные периоды. Сначала использовался MD5, потом SHA1.
Хотя, так и есть, похоже, просто первые символы убрали, чтобы отличать.
правдоподобно, хотя какой-то очень извращенный способ «помечать» найденные пароли, нет бы просто в отдельный файл из записать.

без префикса, кстати, прекрасно брутятся, как честный SHA1.
Моего хеша нет. :)
Удивляет большое количество хешей начинающихся на 00000 — возможно это только часть всей базы.
Аналогично, отсутствует, но пароль на всякий случай сменил
Не, не находит и так.
Но вообще не удевительно, а Линкедина более 100 млн пользователей вроде, а тут всего 6 миллионов паролей.
а мой присутствует. Он нетривиальный, так что риск точно есть.
Интересно, а где файлик с логинами-паролями?
свой пароль нашел.
в файле он не целиком, первые 5 символов хеша — нули.

pass=$(echo -n password | sha1sum | awk '{print $1}' | cut -b6-40)
grep --color "${pass}" combo_not.txt


сменить-сменил, где гарантии, что опять не утечет?
Кстати, интересно, можно почти что любое слово подставить, и там найдётся соответствующий хэш:

grep $(echo -n trolling | sha1sum | awk '{print $1}' | cut -b6-40) combo_not.txt

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

import hashlib,sys
try:
  pwd = sys.argv[1]
  hash = hashlib.sha1()
  hash.update(sys.argv[1])
  hash = hash.hexdigest()[5:]
  for str in open('combo_not.txt','r'):
    if str.count(hash):
      print(str)
except IndexError:
  sys.exit('usage: %s password' % sys.argv[0])
А зачем продолжать продвигаться по циклу, когда хэш уже найден?

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

Конкретно на моём ноутбуке он выполняется 3.214 секунд (python -m cProfile file.py hello!).

Зато можно сделать вот так, например:

import hashlib, sys

try:
    pwd = sys.argv[1]
except IndexError:
    sys.exit('Usage: %s password' % sys.argv[0])

hash = hashlib.sha1()
hash.update(sys.argv[1])
hash = hash.hexdigest()[5:]

if hash in open('combo_not.txt').read():
    print "Hash found"
else:
    print "No such hash"


И вот такой вариант выполняется уже за 0.153 секунды.

Кстати, если вам интересно ещё почитать на тему оптимизации производительности программ на Python, то можете посмотреть вот эту мою статью, например. Там, кстати, в конце приведена цитата разработчика grep. Можете там пройти по ссылке и почитать целиком его сообщение в той рассылке.
А зачем продолжать продвигаться по циклу, когда хэш уже найден?
это был промежуточный вариант, изначально хотел найти все интересующие меня пароли.
как насчет такого?

import hashlib,sys
def sha1(pwd):
  hash = hashlib.sha1()
  hash.update(pwd)
  return hash.hexdigest()[5:]
if len(sys.argv) > 1:
  hashes = [ [pwd,sha1(pwd)] for pwd in sys.argv[1:] ]
  for str in open('combo_not.txt','r'):
    for pwd,hash in hashes:
      if str.count(hash):
        print('%s %s' % (str[:-1],pwd))
        hashes.remove([pwd,hash])
    if len(hashes) == 0:
      break
else:
  sys.exit('usage: %s pwd1 [ pwd2 .. ]' % sys.argv[0])

на мой взгляд, неэффективно используется

if len(hashes) == 0:
  break

и так, по идее, правильнее, но почему-то медленнее:

for pwd,hash in hashes[:]:


я в питоне — падаван, можно сказать. развлекаюсь в свободное время :)
за статейку спасибо, обязательно почитаю.
Как насчет intersection? У меня так получилось быстрее всего.

import hashlib

db = file('SHA1.txt', 'r').read().splitlines()
plist = file('plist.txt', 'r').read().splitlines()

hashes = {}
for pwd in plist:
    hash1 = hashlib.sha1(pwd).hexdigest()
    hash2 = '00000' + hash1[5:]
    hashes[hash1] = pwd
    hashes[hash2] = pwd

found = set(db).intersection(set(hashes.keys()))

for r in found:
    print r, hashes[r]

splitlines ведь загружает весь файл в память, нет?
ваш код схавает полгига ram уже на

plist = file('plist.txt', 'r').read().splitlines()

мой — ~3 MB ;)
Это совершенно очевидно, разве нет? А скорость я бы всё-таки попробовал сравнить.
А мне сейчас в голову вот такая идея пришла.

Что, если вообще не хранить базу с паролями пользователей (будь то хэши или хэши с солью, не важно) на том же сервере, где находится сайт? А, например, хранить её на отдельном сервере в той же локальной сети. И всякий раз, когда пользователь заходит на сайт (или регистрируется), сервер, на котором расположен сайт, отправляет запрос на сервер с паролями: {«user»: «vasya», «password»: «kr39ve21f5»}. А сервер с паролями отвечает: {«status»: «ok»} (либо bad_password, либо server_error). Причём доступен этот сервер с паролями только из локальной сети и на нём открыт только один порт (и всё, что он на него принимает — это подобные запросы). В данном случае система получается настолько проста, что её можно очень хорошо оттестировать и безопасность будет приближена к идеальной.

Интересно, наверняка ведь что-то подобное уже используется для некоторых сервисов? Кто-нибудь знает?
У нас что-то подобное используется в проекте. Думаю многие сервисы так делают: зачем грузить сервера с БД, если можно использовать более-менее простой сервер с быстрой базой для выборки пару значений по ключу.
Угу. Тут главное реализовать это так, чтобы этот сервер мог отвечать, правильный пароль, или нет, но при этом не высылал пароли по запросу. То есть чтобы проверка пароля в любом случае была с той стороны, а получить оттуда хэш пользователя было нельзя.
Это понятно… Получить можно только новый пароль пройдя по ссылке подтверждения сброса пароля.
Есть и используется, особенно в банковской среде. Но тут как с бэкапами — «Люди делятся на тех кто еще не делает бэкапы, и на тех кто уже делает бэкапы».
Используется. Я знаю по крайней мере один такой сервис. Но насколько такая схема популярна сказать не берусь.
Очень популярна. SASL так умеет. Например, так делает saslauthd, аутентифицирующий по базе PAM.
отправляет запрос на сервер с паролями: {«user»: «vasya», «password»: «kr39ve21f5»}.

Именно в таком виде реализовывать это дело не следует. Будете пересылать логины с паролями по сети (пусть даже локальной) открытым текстом?

Но в принципе, LDAP, RADIUS и иже с ними именно так и работают.
Да, в открытом виде действительно не стоит. Я такую реализацию скорее как пример привёл (для упрощения), но о хэшировании, конечно, тоже подумал. Но тут лучше всего, мне кажется, сделать так, чтобы тот хэш, который хранился на сервере с паролями, отличался от того хэша, который на него передаётся. Потому что в этом случае, если не будет взломан сервер с паролями, то не будет известен алгоритм создания хэшей, которые там хранятся (а, допустим, только алгоритм создания хэшей, которые туда передаются).
«сделать так, чтобы тот хэш, который хранился на сервере с паролями, отличался от того хэша, который на него передаётся.»
Конечно.
К примеру, клиент (на котором авторизируются) передает на сервер SHA2(passwd). Тот добавляет к хешу соль, считает SHA2 от результата и сравнивает со значением в базе. Не идеально, но прилично.
RADIUS не пересылает пароли открытым текстом. У сервера и NAS есть общий секрет, который используется для защиты пароля при передаче по сети:

RFC 2865
3. Packet Format

The NAS and RADIUS server share a secret. That shared secret
followed by the Request Authenticator is put through a one-way
MD5 hash to create a 16 octet digest value which is xored with
the password entered by the user, and the xored result placed
in the User-Password attribute in the Access-Request packet.
See the entry for User-Password in the section on Attributes
for a more detailed description.


(ну и продолжение с подробностями, п. 5.2. User-Password)
Конечно не пересылает, как и LDAP… У радиуса есть недостаток — хешируется лишь пароль. Мой любимый TACACS+ от данного позорного недуга избавлен.

Я имел в виду следующее: «LDAP, RADIUS и иже с ними используют сторонний сервер авторизации, как и было предложено автором». Может, коряво выразился…
RADIUS-сервер обычно может в какую-нибудь CHAP-аутентификацию, так что можно пароль вообще не пересылать.
аналогичная схема работает в одной крупной российской компании ;)
Да исспользуєтся наверное на всех больших приложениях, вы «изобрели» SOA, «всё есть сервис».
Авторизация/Автентификация у больших сайтов, отдельная служба с отдельными базами и ресурсами.
Проверил, моего пароля нет, хух. Можно спать спокойно :)
Лучше все таки сменить, так как многие себя нашли, то есть есть шанс что злоумышленники утянули всю БД, а выложили в открытый доступ только часть.
вряд ли, базу ведь необязательно всю выкладывать?
На самом деле опасность тут не в том, что кто-то захватит аккаунт LinkedIn, а в том, что такой же пароль может быть, например, у почты.
И мозги такие на полочке рядышком лежат. :)
А что там лежит у юзеров с паролями password, secret и linkedin?
На полках, таким юзерам, я бы советовал иметь валидол. Ну и церебролезин.
UFO just landed and posted this here
А моего там нет =)
Хотя зарегистрирован там довольно давно.
Вставайте в шорт-позы по акциям ЛинкедИн, пока не вышел выпуск Wall Street Journal с неприятной новостью :-))
Трейдеры, конечно, интернетов не читают :)
Своей не нашел. Linkedinу большой жирный минус.
Yandex ссылка с хэшами больше не работает.
Ссылка на файл умерла, кто-нибудь, перезалейте пож. Хочу свой поискать.
UFO just landed and posted this here
Свой не нашел, даже с учетом
Немного полегчало, но сменить пароль схожу.
Печально узнавать про такие события.
Но зато пока такое происходит, у меня будет работа.
Свой не нашел, искал и полностью, и по последним символам.
UFO just landed and posted this here
Linkedin подтвердила, что «некоторые из скомпрометированных паролей относятся к аккаунтам на Linkedin» (как они осторожно-то) и деактивировала старые пароли для тех, что в базе, разослав письма с инструкцией по их смене.

И оцените слог:
Стоит отметить, что затронутые этим пользователи, которые обновят свои пароли, а также пользователи, чьи пароли не были скомпрометированы, извлекут пользу от улучшенных мер безопасности, которые мы только недавно ввели в действие, включая хэширование и добавление соли ко всем текущим базам данных с паролями"

(It is worth noting that the affected members who update their passwords and members whose passwords have not been compromised benefit from the enhanced security we just recently put in place, which includes hashing and salting of our current password databases)
Как мне кажется — надо было сделать рассылку для всех… пусть не деактивировать пароли… но хотя-бы уведомить пользователей…

Линкед пал в моих глазах…
UPD2. Появился сайт leakedin.org/, на котором можно проверить есть ли ваш пароль в той самой базе хэшей

Сервис «расшифруй сам свой пароль»? Ооок!
Действительно фейк какой то. Ввел туда SHA1 своего пароля — написал что нашел. Скачал файл с хешами — там нету.
Гениально же! Зачем расшифровывать хеши пользователей? Немного PR, и пользователи сами введут ответы. Даже те, чей пароль не утёк.
В данном случае там действительно передаётся только хэш (плюс есть возможность вводить сразу хэш, а не пароль). Хотя мало ли, какой у автора может быть умысел — может быть, он возьмёт, да и подменит JS.

Опять же, неизвестно, что он с этими полученными хэшами потом делает.
то есть проверять небезопасно?
Смотря как.

Сломали сайт? Всегда считайте этот пароль скомпрометированным, не разбираясь что там утекло. Меняйте этот пароль везде, где он использовался, а потом уже свой бывший пароль можете проверять где угодно, хоть на хабр писать.

А вот если вы вошли на какой-то левый сайт, ввели свой текущий пароль, увидели «не найдено» и успокоились, это вы зря. Даже если проверка работает без ошибок, а база полная, всё равно вы только что отдали непонятно кому свой пароль или хеш сумму от него. (даже обрезанная хеш сумма всё равно является хеш суммой и годится для брутфорса)
leakedin.org лежит похоже
Мысль сделать такой сервис была, но подумалось что ни один нормальный пользователь не введет туда свой пароль.
:)
он передает SHA1 пароля, а не пароль. SHA1 генерируется через javascript
Ага, открылся.
Странно. То есть, убедиться по коду странички что хеш вычисляется на сайте и пароль не не передается пользователь в состоянии, а вычислить хеш самостоятельно и проверить наличие хеша в файле — нет?
Ну я в файле проверял.

они написали:

Just provide your password (which we hash with JavaScript; view source to verify) or a SHA-1 hash of your password below, and we'll check.

Можете верить, но лучше не верить а проверять. Здоровая параноя еще никому не навредила
Часть хешей начинается с 00000… Я надеюсь вы учли сей факт?
cut -b6-40

вообщеьто сервис не мой и я не знаю как они там проверяют :)
Я про вашу проверку в файле :)
LinkedIn:

Dear xxxxxxxxxxx,

In order to ensure that you continue to have the best experience using LinkedIn, we are constantly monitoring our site to make sure your account information is safe.

We have recently disabled your account for security reasons. To reset your password, follow these quick steps:

Go to the LinkedIn website
Click on «Sign In»
Click on «Forgot Password?» and follow the directions on the website
Thank you,
The LinkedIn Team"
То есть, получается, они просят сменить пароль, но не пишут, почему.
Я уж не говорю о том, что сначала там видишь верхнюю кнопку Sign In (которая не активна, пока не введёшь Email и пароль), и только потом находишь ссылку мелким кеглем, под формой регистрации (Already on LinkedIn? Sign in).

То есть весьма сомнительная с точки зрения удобства инструкция.

Да и к тому же они могли дать ссылку сюда:

www.linkedin.com/uas/request-password-reset
Значит чуваки из 1Password опять напишут письмо всем пользователям с фразой «молодцы, что пользовались 1Password, вам ничего не грозит» =)
UPD2. Появился сайт leakedin.org/, на котором можно проверить есть ли ваш пароль в той самой базе хэшей

Только мне одному показалось, что этот сайт может быть «брутфорсом» на основе социальной инженерии?

Поясняю — сейчас все ломанутся и непонятно кому вобьют свои пароли, которые автоматически станут словарными :)
Ну пароли там на сервер не передаются — только хеши.
На этот раз обошлось…
Но в следующий раз может быть по-другому :)
О! Спасибо! Я наконец-то смог вспомнить свой пароль на линкедине.
Pass the salt, please. Except if you're LinkedIn. In that case, salt the pass, please.
Sign up to leave a comment.

Articles