Как расшифровать хеш sha512 с солью

Обновлено: 04.07.2024

Этичный хакинг и тестирование на проникновение, информационная безопасность

Оглавление

Взлом итерированных, солёных и произвольных хешей на основе MD5, SHA1 и прочих сырых хешей

John the Ripper и Hashcat поддерживают большое количество хешей для брут-форса паролей. Список поддерживаемых в John the Ripper хешей можно посмотреть командой:

Списки поддерживаемых хешей внушительный у обеих программ.

Виды хешей

Хеши можно разделить на следующие группы:

  • Сырые (md2, md4, md5, sha1, sha224, sha256, sha384, sha512, tiger, sha3_224, sha3_256, sha3_384, sha3_512, keccak_256, keccak_512, ripemd128, ripemd160, ripemd256, ripemd320, whirlpool, gost, skein224, skein256, skein384, skein512, panama, haval_128_3, haval_128_4, haval_128_5, haval_160_3, haval_160_4, haval_160_5, haval_192_3, haval_192_4, haval_192_5, haval_256_3, haval_256_4, haval_256_5). Это самостоятельные алгоритмы хеширования, вычисления контрольных сумм
  • Солёные хеши. Основываются на сыром хеше, но к строке пароля добавляется соль, например, md5($pass.$salt)
  • Итерированные. Также основываются на сырых хешах, но результат хеширования затем вновь подвергается хешированию — это может происходить много раз. Пример: md5($salt.sha1($salt.$pass))

Кроме этих основных групп, можно разделить хеши по области применения:

В этих группах какие-то хеши являются самостоятельными, то есть они рассчитываются по собственным алгоритмам), но также довольно часто, особенно в веб-приложениях, операционных системах, хранящих пароли в хешированном виде, применяются солёные и итерированные хеши, которые основаны на сырых хешах, например:

  • sha1($s.sha1($s.sha1($p)))
  • sha1($s.sha1($p))
  • sha256(sha256($p).$s)

Если это популярное приложение, то поддержка его типа хеша обычно добавляется в John the Ripper и Hashcat и нам, на самом деле, не нужно знать, по какому именно алгоритму рассчитывается хеш.

Но представьте ситуацию, вы получили хеш от узкоспециальной программы, разобрались, что хеш вычисляется, например, по следующему алгоритму: md5(md5(md5($p).$s).$s2). Но поддержка этого алгоритма (этого типа хеша) отсутствует и в John the Ripper, и в Hashcat, то что делать в данной ситуации?

Ответу на этот вопрос как раз и посвящена данная часть — мы научимся взламывать хеши, вычисленные с использованием сырых, солёных и итерированных алгоритмов.

Dynamic в John the Ripper

Динамический «самостоятельно описывающий» формат (a.k.a. Динамический компилятор выражений (dynamic expression compiler)). Это режим в котором пользователь без использования программирования описывает формулу, по которой хешируются пароли.

Допустим, мы добыли хеш пароля:

С помощью обратной инженерии выяснено, что хеш высчитывается по следующей формуле:

Нам нужно записать хеш в файл в следующем формате:

То есть хеш и соль разделяются знаком доллара.

Создаём файл hash.txt и записываем:

Создадим крошечный словарик, назовём его wordlist.txt и запишем в него:

Пароль успешно взломан, это «hackware»:


В данном примере мы использовали нашу собственную формулу, по которой вычислялся хеш, но в John the Ripper много встроенных динамичных форматов. Более того, вы можете записать ваш динамический формат в конфигурационном файле и использовать его по присвоенному имени, вместо того, чтобы каждый раз вводить формулу. Сначала мы познакомимся со встроенными форматами, а затем вернёмся к синтаксису динамических форматов, которые вы можете составить сами.

Хотя нет, чтобы понимать обозначения встроенных форматов, нужно знать синтаксис — поэтому начнём всё-таки с синтаксиса написания пользовательских форматов dynamic.

Синтаксис форматов режима dynamic

Выражение ДОЛЖНО быть единичным выражением вычисления крипто хеша. Это означает, что последним действием является вычисление хеша, но не нескольких хешей, объединённых друг с другом. То есть md5($p) это верно, а md5($p).md5($p) это НЕ верно.

Изменение регистра букв (примечание: изменение регистра букв применяется только для некоторых вещей).

  • lc($u) для нижнего регистра имени пользователя (правильный нижний регистр Unicode)
  • uc($u) для верхнего регистра имени пользователя (опять же, правильный верхний регистр Unicode)
  • lc($p) и uc($p) предназначены для нижнего/верхнего регистра пароля.

ВАЖНО: Если uc($u) или lc($u) используются в выражении, тогда ВСЕ $u должны быть сделаны в одном ключе. Это также относится и к паролю. Поэтому md5($u.$p.$) это верно, а md5(uc($u).$p.$u) это неверно. Это ограничение динамического формата в целом.

При использовании констант они должны быть добавлены через запятую в конец выражения. ВАЖНО: если используются символы «:» (двоеточие) в константах, то их нужно записывать в шестнадцатеричной форме. Например: md5($c1.$p),c1=test_\x3a_test. Из этого получится md5("test_:_test".$p)

Проблемным символам будет посвящён раздел ниже. Сейчас же просто упомянем, что имеется утилита raw2dyna (входит в пакет John the Ripper). Для конвертации любой строки в шестнадцатеричную, используется опция -2h, например, следующая команда выведет шестнадцатеричную запись для двоеточия:

Необязательно кодировать всю строку — можно кодировать отдельные символы, как это показано выше.

Эта же программа с помощью опции -2r может конвертировать шестнадцатеричную запись в сырые данные:

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

Группирование. Все выражения должны быть единичным «внешним» выражением, но внутри внешнего выражения, может быть множество сгруппированных данных. Функции начинаются с имени функции и используют ( и ) для группирования данных, присутствующих в хеше. Поэтому такие вещи как md5($p) или md5(md5(md5($s.$p))) или md5(md5($p).$s.md5($s.$p)) являются верными, поскольку они имеют единое внешнее (последнее) выражение и все необходимые символы для правильного синтаксиса.

У функций хеширования есть несколько «разновидностей», которые делают несколько разные вещи. Например:

Вариант записи в нижнем регистре (такой как md5(…)) вернёт результаты в виде base16 числа, записанного в нижнем регистре. То есть md5("password") вернёт 5f4dcc3b5aa765d61d8327deb882cf99,

md5_64("password") вернёт mime base-64 результат, то есть X03MO1qnZdYdgyfeuILPmQ (это сырые байты хеша в кодировке base64)

md5_64c("password") возвращает строку crypt alphabet base64, для нашего примера является LorACpebNRMRUmTSi69DaE.

Обычно _64 и _64c используются в качестве внешней функции, информируя john о том, как «выглядит» тип входного хеша (т.е. хеши находятся в base64). То же самое и с верхним регистром. Если внешняя функция имеет верхний регистр, то будут действительны только шестнадцатеричные строки в верхнем регистре правильной длины.

Функции хеширования (каждая из которых имеет версию в нижнем регистре, верхнем регистре, а также с добавлением _raw, _64 и _64c):

Примеры использования настраиваемых форматов dynamic в john

1. Хеш вычисляется как MD5 от пароля:

2. Хеш вычисляется как MD5 от пароля, а затем полученная строка хешируется ещё раз с помощью MD5:

3. Хеш вычисляется как MD5 от пароля, а затем полученный хеш кодируется в Base64 и эта новая строка хешируется ещё раз с помощью MD5:

4. К паролю добавляется соль, для полученной объединённой строки считается MD5 хеш:

5. Пароль хешируется алгоритмом sha1:

6. Пароль хешируется алгоритмом MD5, а затем полученная строка хешируется алгоритмом sha1:

7. Пароль объединяется с солью, полученная строка хешируется алгоритмом sha512, затем берётся соль, полученный хеш и пароль, и все они объединяются в одну строку, которая хешируется алгоритмом sha512:

Константы и соли

Выше были упомянуты константы — их функции похожи на функцией солей, тогда для чего они нужны? В принципе, константа это и есть соль, но она передаётся в John the Ripper другим способом. Соль указывается вместе с хешем, а константа указывается в формуле (которая используется с опцией -form или хранится в конфигурационном файле).

Пример использования константы:

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

Как указать пользовательский формат хеша dynamic в командной строке

Обратите внимание, что кавычки являются обязательными и должны использоваться именно одинарные кавычки!

Вы можете убедиться в этом сами — возьмите своё выражение, поместите в двойные кавычки и выведите его в терминал с помощью echo, например:

От выражения осталось следующее:

То есть именно в таком виде его и увидела бы программа.


Как правильно записать хеш с солью и именем пользователя для John the Ripper

Общая формула записи хешей для dynamic следующая:

Кроме хеша, все остальные данные для большинства хешей не требуются.

Пример хеша с солью (соль отделена от хеша символом $):

Пример хеша с именем пользователя:

Встроенные форматы dynamic

Чтобы просмотреть список встроенных форматов введите команду:

Пример первых строк:


Строки dynamic_* это имена форматов, их нужно использовать при выборе того или иного формата. Также вы можете увидеть формулы по которым вычисляется каждый формат. Для некоторых форматов имеется краткий комментарий.

Вы можете обратить внимание, что выведены строки с двумя разными началами:

Они отличаются тем, что Format — это встроенные в John the Ripper форматы, а UserFormat, в принципе, это тоже встроенные форматы, но от сообщества. В файле dynamic.conf (может быть расположен по пути /usr/share/john/dynamic.conf) вы можете увидеть и добавить свои собственные UserFormat.

Как сохранить пользовательский формат хеша dynamic в конфигурационном файле

Свои собственные форматы dynamic можно записать в файлы john.conf (john.ini), dynamic.conf (включён в john.conf) или john.local.conf.

Недостаточно просто записать формулу — разработан язык примитивов, который довольно близок уже к программированию.

Документацию вы найдёте в файлах:

Как записывать соли со специальными символами

Соли могут содержать проблематичные символы. Некоторыми из них могут быть такие символы как: : \r \n \ NULL и так далее.

Символ : (двоеточие) используется в JtR как разделитель полей. Если он существует в соли, то он разобьёт соль на несколько полей (что неправильно).

Символ возврата каретки или перевод строки приведёт к разбиению строчки и JtR прочитает её неправильно.

NULL байты это проблема в любой C программе, использующей нормальные «строковые» функции.

Символ \ используется для экранирования символов внутри dynamic и может стать причиной проблем.

Из-за всех этих проблем, в dynamic была добавлена поддержка шестнадцатеричной записи соли.

В этом формате если соль была 1234, тогда эквивалентным значением будет $HEX$31323334.

Это позволяет кодировать и использовать соли вроде таких:

Даже такую соль МОЖНО использовать, после кодирования она пример следующий вид:

Кодировать символы и конвертировать соли можно с помощью уже упомянутой программы raw2dyna. Она позволяет делать различные модификации с хешами — посмотрите её справку.

Самое простое использование показано выше — конвертировать отдельные символы:

Здесь старая версия урока, которая больше не обновляется.

Итак, ты решил сделать авторизацию и регистрацию через пароли. Как максимально обезопасить пароли пользователей от взлома и от своих же любопытных сотрудников (если ты работаешь не один, а в большой компании)?

Для начала, никогда не храни открытые пароли. Храни соленые хеши от них. Хеш-функция, например md5, sha1 (про них написано в вики, почитай) — это практически необратимая функция. То есть получить хеш по паролю просто, а вот восстановить пароль, имея хеш практически невозможно — надо перебирать все возможные варианты паролей и сравнивать получившиеся хеши.

Какой смысл в хэше, если md5 все равно можно расшифровать? Пусть даже перебором?

Это займет много или очень много времени. Может, взломщик устанет ждать или пароли потеряют актуальность. Например, если хорошо шифровать, то годы (по идее там перебирать можно и 100 лет, но я думаю скоро изобретут какую-нибудь штуку для ускоренного перебора), вместо того чтобы взять и увидеть пароли в открытую.

Ок, достаточно ли использовать хеширование и хранить только хеши?

Нет! Без так называемой «соли» многие пароли можно подобрать за секунду если там использовать просто md5(pass). Не веришь? Читай ниже.

Что такое соль? Что значит «соленый хеш»?

Соль — случайно сгенерированная последовательность символов, которая хранится рядом с хешем. Дан пароль $pass = "123456" , мы генерируем случайную соль например $salt = 'A&%6t*(k:' и получаем хеш от «соль + пароль»: $hash = md5($salt . $pass) . В базу сохраняется отдельно использованная соль (она для каждого пользователя своя), отдельно хеш.

Теперь попробуем применить математику и посчитать насколько надежны разные способы хеширования. Сейчас подбор пароля делается 2 способами:

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

Считаем число вариантов.

36^6 — значит 36 в 6-й степени, то есть 36*36*36*36*36*36 если что.

  • Если в пароле 12 цифр 0-9 : число комбинаций = 10^12 = 1000 миллиардов = 100 секунд перебора на 1 видеокарте (1 секунда на 100 карточках параллельно).
  • Если 6 букв a-z или цифр 0-9 . Число вариантов = 36^6 (считаем гуглом) = 2 млрд. Хехе, меньше секунды.
  • Если 6 букв a-zA-Z (добавим маленькие и большие буквы) и 0-9 . Комбинаций 62^6 = 56 млрд. 6 секунд перебора.
  • Если в пароле 8 букв a-zA-Z и цифр 0-9 . Комбинаций уже 62^8 = 218 триллионов. Это 22000 секунд перебора (в часе 3600 секунд, так что выходит 6 часов) на 1 карточке или 220 секунд на 100 карточках. Ого, не очень-то надежно.
  • Если в пароле 10 символов a-zA-Z0-9 + 20 знаков вроде минус, плюс.. то выходит 82^10 комбинаций

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

В общем, видишь, без добавления соли пароли подберутся на раз. И не все же ставят 10-символьные пароли, у многих там просто слово или цифры.

Заметь что в будущем компьютеры будут мощнее, и значит подбираться пароли будут быстрее. Теперь подумаем как защититься и усложнить жизнь взломщикам:

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

в вашем случае нарушение хэш-алгоритма эквивалентно обнаружению столкновения в хэш-алгоритме. Это означает, что вам не нужно искать сам пароль (который был бы прообраза), вам просто нужно найти выход хэш-функции, который равен хэшу действительного пароля (таким образом, "столкновение"). Поиск столкновения с помощью день рождения атака принимает O(2^(n/2)) Время, где n-выходная длина хеш-функции в битах.

SHA-2 имеет выходной размер 512 бит, поэтому поиск столкновения займет O (2^256) времени. Учитывая, что нет умных атак на сам алгоритм (в настоящее время никто не известен для семейства хэшей SHA-2), это то, что нужно, чтобы сломать алгоритм.

чтобы почувствовать, что на самом деле означает 2^256: в настоящее время считается, что количество атомов в (целом. ) Вселенная примерно 10^80, что примерно 2^266. Предполагая 32-байтовый вход (что разумно для ваш случай - 20 байт соли + 12 байт пароля) моя машина принимает

2^-2s) для 65536 (=2^16) вычислений. Таким образом, 2^256 вычислений будет сделано в 2^240 * 2^16 вычислений, которые будут принимать

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

Так что забудь грубое принуждение SHA-256 здесь. Следующий вопрос был о словарных словах. Чтобы получить такие слабые пароли радужные таблицы традиционно использовались. Радужная таблица обычно является просто таблицей предварительно вычисленных хэш-значений, идея заключается в том, что если вы смогли предварительно вычислить и сохранить каждый возможный хэш вместе с его входом, то вам потребуется O(1), чтобы найти данный хэш и получить действительный предварительный образ для него. Конечно, это невозможно на практике, так как нет устройства хранения может хранить такие огромные объемы данных. Эта дилемма известна как памяти-время компромисс. Поскольку вы можете хранить только так много значений, типичные радужные таблицы включают некоторую форму хэш-цепочки с промежуточными функциями сокращения (это подробно объясняется в статье Википедии), чтобы сэкономить место, отказавшись от некоторой экономии времени.

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

низкая энтропия типичных паролей делает возможным относительно высокую вероятность того, что один из ваших пользователей использует пароль из относительно небольшой базы данных общих паролей. Если вы google для них, вы в конечном итоге найти торрент-ссылки для таких баз данных паролей, часто в категории размера gigabyte. Успех с таким инструментом обычно находится в диапазоне от минут до дней, если злоумышленник не ограничен в каких-либо путь.

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

словарь паролей

примерная цифра: существует около 1,000,000 английских слов, и если хакер может вычислить около 10,000 SHA-512 хэшей в секунду (обновление: см. комментарий CodesInChaos, эта оценка очень низкая), 1,000,000 / 10,000 = 100 секунд. Так и будет потратьте чуть более минуты, чтобы взломать пароль словаря одного слова для одного пользователя. Если пользователь присоединяет два словарные слова, вы находитесь в районе нескольких дней, но все еще очень возможно, если злоумышленник заботится достаточно. Более того, это становится все труднее.

случайный пароль

если пароль представляет собой действительно случайную последовательность буквенно-цифровых символов, верхний и нижний регистр, то число возможных паролей длины N равно 60^N (осталось 60 символов). На этот раз мы сделаем расчет в другом направлении; мы спросим:какую длину пароля мы могли бы взломать, учитывая определенный промежуток времени? просто используйте эту формулу:

N = Log60(t * 10,000) где t - время, затраченное на вычисление хэшей в секундах (опять же, предполагая 10 000 хэшей в секунду).

таким образом, учитывая 3 дня, мы сможем взломать пароль, если он длиной 5 символов.

Это все очень бал-парк, но вы поняли идею. Update: см. комментарий ниже, на самом деле можно взломать гораздо более длинные пароли, чем это.

давайте проясним некоторые заблуждения:

соль не замедляет вычисление хэшей, это просто означает, что они должны взломать пароль каждого пользователя индивидуально и предварительно вычисленные хэш-таблицы (buzz-word:радужные таблицы) сделаны совершенно бесполезный. Если у вас нет предварительно вычисленной хэш-таблицы, и вы взламываете только один хэш-пароль, соление не имеет никакого значения.

SHA-512 не предназначен, чтобы быть трудно грубой силы. Лучшие алгоритмы хэширования, такие как BCrypt, PBKDF2 или SCrypt можно настроить так, чтобы вычислять намного дольше, и средний компьютер может вычислять только 10-20 хэшей в секунду. Читать это отличный ответ о хэширования паролей, Если вы еще этого не сделали.

update: как написано в комментарии CodesInChaos, даже пароли с высокой энтропией (около 10 символов) могут быть bruteforced, если использовать правильное оборудование для вычисления хэшей SHA-512.

примечания к принятому ответу:

принятый ответ от сентября 2014 года неверно и опасно неправильно:

В вашей случай, нарушение хэш-алгоритма эквивалентно нахождению столкновения в хэш-алгоритме. Это означает, что вам не нужно найти сам пароль (который будет прообраза). Поиск столкновения с помощью атаки на день рождения занимает O (2^n/2) времени, где n-выходная длина хеш-функции в битах.

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

Да, пожалуйста, используйте алгоритм, который медленно вычисляется,но что такое "энтропия"? Ввод пароля с низкой энтропией через хэш не увеличивает энтропию. Он должен!--9-->сохранить энтропия, но вы не можете сделать пароль мусора лучше с гашишем, он так не работает. слабый пароль поставил через PBKDF2 с еще слабый пароль.

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

чтобы дать представление о том, сколько хэшей можно сделать за секунду, я думаю, что биткойн-достойный пример. биткоин использует SHA256 и, чтобы сократить его, чем больше хэшей вы генерируете, тем больше биткойнов вы получаете (которые вы можете торговать на реальные деньги) и как такие люди мотивировано использовать GPUs для этой цели. Вы можете видеть в обзоре оборудования что средняя графическая карта, которая стоит всего $ 150, может рассчитать более 200 миллионов хэшей/ С. Чем дольше и сложнее ваш пароль, тем больше времени это займет. Расчет на 200 м / с, чтобы попробовать все возможности для 8 символов буквенно-цифровой (капитал, ниже, цифры) займет около 300 часов. В реальном времени, скорее всего, меньше, если пароль является чем-то подходящим или общим английским слово.

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

одна вещь, которую вы можете сделать, это также добавить дополнительную защиту грубой силы замедление процедура хэширования. Поскольку вы только хэш-пароли один раз, и злоумышленник должен делать это много раз, это работает в вашу пользу. Типичный способ сделать это-взять значение, хэшировать его, взять вывод, хэшировать его снова и так далее для фиксированного количества итераций. Вы можете попробовать что-то вроде 1000 или 10 000 итераций на примере. Это сделает его во много раз медленнее для злоумышленника, чтобы найти каждый пароль.


В мире сущес­тву­ет нес­коль­ко зет­табайт циф­ровых дан­ных, но далеко не вся эта информа­ция уни­каль­на: пов­торы раз­бро­саны по мил­лиар­дам носите­лей и сер­веров. Незави­симо от типа дан­ных, для работы с ними тре­бует­ся решать одни и те же прин­ципи­аль­ные задачи. Это сни­жение избы­точ­ности за счет час­тично­го устра­нения пов­торов (дедуп­ликация), про­вер­ка целос­тнос­ти, инкре­мен­тное соз­дание резер­вных копий и авто­риза­ция поль­зовате­лей. Конеч­но, пос­ледний аспект инте­ресу­ет нас боль­ше все­го, одна­ко все эти тех­ничес­кие при­емы базиру­ются на общих методах обра­бот­ки дан­ных с исполь­зовани­ем хеширо­вания. Сущес­тву­ют облачные сер­висы, которые поз­воля­ют исполь­зовать эту про­цеду­ру быс­трее — с хорошо извес­тны­ми целями.

На пер­вый взгляд кажет­ся стран­ным, что в раз­ных задачах при­меня­ется общая про­цеду­ра вычис­ления и срав­нения кон­троль­ных сумм или хешей — битовых пос­ледова­тель­нос­тей фик­сирован­ной дли­ны. Одна­ко этот метод дей­стви­тель­но уни­вер­сален. Кон­троль­ные сум­мы слу­жат сво­еоб­разны­ми циф­ровыми отпе­чат­ками фай­лов, клю­чей, паролей и дру­гих дан­ных, называ­емых в крип­тогра­фии messages — сооб­щения. Хеши (или дай­джес­ты, от англ. digest) поз­воля­ют срав­нивать их меж­ду собой, быс­тро обна­ружи­вать любые изме­нения и обе­зопа­сить про­вер­ку дос­тупа. Нап­ример, с помощью хешей мож­но про­верять соот­ветс­твие вве­ден­ных паролей, не переда­вая их в откры­том виде.

Ма­тема­тичес­ки этот про­цесс выпол­няет­ся одним из алго­рит­мов хеширо­вания — ите­раци­онно­го пре­обра­зова­ния бло­ков дан­ных, на которое раз­бива­ется исходное сооб­щение. На вхо­де может быть что угод­но — от корот­кого пароля до огромной базы дан­ных. Все бло­ки цик­лично дописы­вают­ся нулями или уре­зают­ся до задан­ной дли­ны до тех пор, пока не будет получен дай­джест фик­сирован­ного раз­мера.

Пре­дель­ный объ­ем исходных дан­ных, который может обра­ботать хеш‑фун­кция, опре­деля­ется фор­мой их пред­став­ления в алго­рит­ме. Обыч­но они записы­вают­ся как целое 64-бит­ное чис­ло, поэто­му типич­ный лимит сос­тавля­ет 2 64 бит минус еди­ница, или два экса­бай­та. Такое огра­ниче­ние пока не име­ет прак­тичес­кой зна­чимос­ти даже для очень круп­ных дата‑цен­тров.

Обыч­но хеши записы­вают­ся в шес­тнад­цатерич­ном виде. Так их гораз­до удоб­нее срав­нивать на вид, а запись получа­ется в четыре раза короче дво­ичной. Самые корот­кие хеши получа­ются при исполь­зовании Adler-32, CRC32 и дру­гих алго­рит­мов с дли­ной дай­джес­та 32 бита. Самые длин­ные — у SHA-512. Кро­ме них, сущес­тву­ет с десяток дру­гих популяр­ных хеш‑фун­кций, и боль­шинс­тво из них спо­соб­но рас­счи­тывать дай­джес­ты про­межу­точ­ной дли­ны: 160, 224, 256 и 384 бит. Попыт­ки соз­дать фун­кцию с уве­личен­ной дли­ной хеша про­дол­жают­ся, пос­коль­ку чем длин­нее дай­джест, тем боль­ше раз­ных вари­антов может сге­нери­ровать хеш‑фун­кция.

Неповторимость — залог надежности

Уни­каль­ность хеша — одно из его клю­чевых свой­ств, опре­деля­ющее крип­тостой­кость сис­темы шиф­рования. Дело в том, что чис­ло вари­антов воз­можных паролей теоре­тичес­ки бес­конеч­но, а вот чис­ло хешей всег­да конеч­ное, хоть и очень боль­шое. Дай­джес­ты любой хеш‑фун­кции будут уни­каль­ны лишь до опре­делен­ной сте­пени. Сте­пени двой­ки, если быть точ­ным. К при­меру, алго­ритм CRC32 дает мно­жес­тво все­го из 2 32 вари­антов, и в нем труд­но избе­жать пов­торений. Боль­шинс­тво дру­гих фун­кций исполь­зует дай­джес­ты дли­ной 128 или 160 бит, что рез­ко уве­личи­вает чис­ло уни­каль­ных хешей — до 2 128 и 2 160 соот­ветс­твен­но.

Стро­го говоря, к хеш‑фун­кци­ям в крип­тогра­фии предъ­явля­ются более высокие тре­бова­ния, чем к кон­троль­ным сум­мам на осно­ве цик­личес­кого кода. Одна­ко эти понятия на прак­тике час­то исполь­зуют как синони­мы.

Сов­падение хешей от раз­ных исходных дан­ных (в том чис­ле паролей) называ­ют кол­лизи­ей. Она может быть слу­чай­ной (встре­чает­ся на боль­ших объ­емах дан­ных) или псев­дослу­чай­ной — исполь­зуемой в целях ата­ки. На эффекте кол­лизии осно­ван взлом раз­ных крип­тогра­фичес­ких сис­тем — в час­тнос­ти, про­токо­лов авто­риза­ции. Все они сна­чала счи­тают хеш от вве­ден­ного пароля или клю­ча, а затем переда­ют этот дай­джест для срав­нения, час­то при­меши­вая к нему на каком‑то эта­пе пор­цию псев­дослу­чай­ных дан­ных, или исполь­зуют допол­нитель­ные алго­рит­мы шиф­рования для уси­ления защиты. Сами пароли ниг­де не сох­раня­ются: переда­ются и срав­нива­ются толь­ко их дай­джес­ты. Здесь важ­но то, что пос­ле хеширо­вания абсо­лют­но любых паролей одной и той же фун­кци­ей на выходе всег­да получит­ся дай­джест оди­нако­вого и заранее извес­тно­го раз­мера.

Псевдореверс

Про­вес­ти обратное пре­обра­зова­ние и получить пароль непос­редс­твен­но из хеша невоз­можно в прин­ципе, даже если очис­тить его от соли, пос­коль­ку хеширо­вание — это одно­нап­равлен­ная фун­кция. Гля­дя на получен­ный дай­джест, нель­зя понять ни объ­ем исходных дан­ных, ни их тип. Одна­ко мож­но решить сход­ную задачу: сге­нери­ровать пароль с таким же хешем. Из‑за эффекта кол­лизии задача упро­щает­ся: воз­можно, ты никог­да не узна­ешь нас­тоящий пароль, но най­дешь совер­шенно дру­гой, дающий пос­ле хеширо­вания по это­му же алго­рит­му тре­буемый дай­джест.

Для это­го надо сде­лать все­го ничего — рас­счи­тать 2 128 пар вида пароль — хеш или на порядок‑дру­гой боль­ше — в зависи­мос­ти от дли­ны дай­джес­та выб­ранной фун­кции. Одна­ко все эти двой­ки в чер­тов­ски боль­шой сте­пени отпу­гива­ют, толь­ко если думать о скром­ных воз­можнос­тях собс­твен­ной машины. Хорошо, что ско­рость нахож­дения пароля по его хешу сегод­ня необя­затель­но зависит от вычис­литель­ной мощ­ности компь­юте­ра самого ата­кующе­го, пос­коль­ку во мно­гих слу­чаях для это­го уже не тре­бует­ся выпол­нять дол­гий перебор. Мно­гое уже сде­лано до нас.

Ме­тоды опти­миза­ции рас­четов появ­ляют­ся бук­валь­но каж­дый год. Ими занима­ются коман­ды HashClash, Distributed Rainbow Table Generator и дру­гих меж­дународ­ных про­ектов крип­тогра­фичес­ких вычис­лений. В резуль­тате на каж­дое корот­кое сочета­ние печат­ных сим­волов или вари­ант из спис­ка типич­ных паролей хеши уже вычис­лены. Их мож­но быс­тро срав­нить с перех­вачен­ным, пока не най­дет­ся пол­ное сов­падение.

Рань­ше на это тре­бова­лись недели или месяцы про­цес­сорно­го вре­мени, которые в пос­ледние годы уда­лось сок­ратить до нес­коль­ких часов бла­года­ря мно­гоядер­ным про­цес­сорам и перебо­ру в прог­раммах с под­дер­жкой CUDA и OpenCL. Адми­ны наг­ружа­ют рас­четами таб­лиц сер­веры во вре­мя прос­тоя, а кто‑то арен­дует вир­туаль­ный клас­тер в Amazon EC2.

Искать XOR вычислять

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

В девянос­тых годах край­не популяр­ным стал алго­ритм MD5, написан­ный Рональ­дом Ривес­том. Он стал широко при­менять­ся при авто­риза­ции поль­зовате­лей на сай­тах и при под­клю­чении к сер­верам кли­ент­ских при­ложе­ний. Одна­ко его даль­нейшее изу­чение показа­ло, что алго­ритм недос­таточ­но надежен. В час­тнос­ти, он уяз­вим к ата­кам по типу псев­дослу­чай­ной кол­лизии. Ины­ми сло­вами, воз­можно пред­намерен­ное соз­дание дру­гой пос­ледова­тель­нос­ти дан­ных, хеш которой будет в точ­ности соот­ветс­тво­вать извес­тно­му.

Пос­коль­ку дай­джес­ты сооб­щений широко при­меня­ются в крип­тогра­фии, на прак­тике исполь­зование алго­рит­ма MD5 сегод­ня при­водит к серь­езным проб­лемам. Нап­ример, с помощью такой ата­ки мож­но под­делать циф­ровой сер­тификат x.509. В том чис­ле воз­можна под­делка сер­тифика­та SSL, поз­воля­ющая зло­умыш­ленни­ку выдавать свой фейк за доверен­ный кор­невой сер­тификат (CA). Более того, в боль­шинс­тве наборов доверен­ных сер­тифика­тов лег­ко най­ти те, которые по‑преж­нему исполь­зуют алго­ритм MD5 для под­писи. Поэто­му сущес­тву­ет уяз­вимость всей инфраструк­туры откры­тых клю­чей (PKI) для таких атак.

Из­нуритель­ную ата­ку перебо­ром устра­ивать при­дет­ся толь­ко в слу­чае дей­стви­тель­но слож­ных паролей (сос­тоящих из боль­шого набора слу­чай­ных сим­волов) и для хеш‑фун­кций с дай­джес­тами боль­шой дли­ны (от 160 бит), у которых пока не наш­ли серь­езных недос­татков. Огромная мас­са корот­ких и сло­вар­ных паролей сегод­ня вскры­вает­ся за пару секунд с помощью онлай­новых сер­висов.

Бойцы облачного фронта

1. Про­ект «Убий­ца хешей» сущес­тву­ет уже поч­ти восемь лет. Он помога­ет вскрыть дай­джес­ты MD5, SHA-160 и NTLM. Текущее количес­тво извес­тных пар сос­тавля­ет 43,7 мил­лиона. На сайт мож­но заг­ружать сра­зу нес­коль­ко хешей для парал­лель­ного ана­лиза. Пароли, содер­жащие кирил­лицу и сим­волы дру­гих алфа­витов, кро­ме англий­ско­го, иног­да находят­ся, но отоб­ража­ются в невер­ной кодиров­ке. Еще здесь про­водит­ся пос­тоян­ный кон­курс взло­ма паролей по их хешам и дос­тупны ути­литы для облегче­ния этой задачи — нап­ример, прог­раммы для объ­еди­нения спис­ков паролей, их перефор­матиро­вания и устра­нения пов­торов.

HashKiller не дру­жит с кирил­лицей, но зна­ет кирил­личес­кие пароли «Убий­ца хешей» нашел три пароля из пяти за пол­секун­ды

2. «Крэк‑стан­ция» под­держи­вает работу с хешами прак­тичес­ки всех реаль­но исполь­зуемых типов. LM, NTLM, MySQL 4.1+, MD2/4/5 + MD5-half, SHA-160/224/256/384/512, ripeMD160 и Whirlpool. За один раз мож­но заг­рузить для ана­лиза до десяти хешей. Поиск про­водит­ся по индекси­рован­ной базе. Для MD5 ее объ­ем сос­тавля­ет 15 мил­лионов пар (око­ло 190 Гб) и еще при­мер­но по 1,5 мил­лиона для каж­дой дру­гой хеш‑фун­кции.

«Крэк-станция» находит многие словарные пароли даже по хешам NTLM

«Крэк‑стан­ция» находит мно­гие сло­вар­ные пароли даже по хешам NTLM

По уве­рени­ям соз­дателей, в базу вклю­чены все сло­ва из англо­языч­ной вер­сии Википе­дии и боль­шинс­тво популяр­ных паролей, соб­ранных из обще­дос­тупных спис­ков. Сре­ди них есть и хит­рые вари­анты со сме­ной регис­тра, лит­спи­ком, пов­тором сим­волов, зер­калиро­вани­ем и про­чими ухищ­рени­ями. Одна­ко слу­чай­ные пароли даже из пяти сим­волов ста­новят­ся проб­лемой — в моем тес­те полови­на из них не была най­дена даже по LM-хешам.

«Крэк-станция» с трудом вскрывает случайные пароли длиной от пяти символов даже по LM-хешам

«Крэк‑стан­ция» с тру­дом вскры­вает слу­чай­ные пароли дли­ной от пяти сим­волов даже по LM-хешам

«Облачный крэкер» мгновенно находит словарные пароли по их хешам

«Облачный крэ­кер» мгно­вен­но находит сло­вар­ные пароли по их хешам

Собс­твен­ного поис­ка на сай­те пока нет, но пароль или его хеш мож­но написать пря­мо в адресной стро­ке бра­узе­ра, добавив его пос­ле адре­са сай­та и пре­фик­са /encrypt/.

Сервис MD5Decode знает все типы хешей от словарных паролей

Сер­вис MD5Decode зна­ет все типы хешей от сло­вар­ных паролей

MD5Decrypt находит составные словарные пароли, но хеши на анализ принимает только по одному

MD5Decrypt находит сос­тавные сло­вар­ные пароли, но хеши на ана­лиз при­нима­ет толь­ко по одно­му

Ищем хеши Гуглом


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

Вмес­то того что­бы рек­ламиро­вать здесь чес­тные сер­висы, я пред­ложу исполь­зовать дру­гой под­ход —находить пары хеш — пароль в популяр­ных поис­ковых сис­темах. Их роботы‑пауки ежед­невно про­чесы­вают веб и собира­ют новые дан­ные, сре­ди которых есть и све­жие записи из радуж­ных таб­лиц.

По­это­му для начала прос­то напиши хеш в поис­ковой стро­ке Google. Если ему соот­ветс­тву­ет какой‑то сло­вар­ный пароль, то он (как пра­вило) отоб­разит­ся сре­ди резуль­татов поис­ковой выдачи уже на пер­вой стра­нице. Еди­нич­ные хеши мож­но погуг­лить вруч­ную, а боль­шие спис­ки будет удоб­нее обра­ботать с помощью скрип­та BozoCrack.

Универсальный подход

Сре­ди десят­ка хеш‑фун­кций наибо­лее популяр­ны MD5 и SHA-1, но точ­но такой же под­ход при­меним и к дру­гим алго­рит­мам. К при­меру, файл реес­тра SAM в ОС семей­ства Windows по умол­чанию хра­нит два дай­джес­та каж­дого пароля: LM-хеш (уста­рев­ший тип на осно­ве алго­рит­ма DES) и NT-хеш (соз­дает­ся путем пре­обра­зова­ния юни­код­ной записи пароля по алго­рит­му MD4). Дли­на обо­их хешей оди­нако­ва (128 бит), но стой­кость LM зна­читель­но ниже из‑за мно­жес­тва упро­щений алго­рит­ма.

Пос­тепен­но оба типа хешей вытес­няют­ся более надеж­ными вари­анта­ми авто­риза­ции, но мно­гие эту ста­рую схе­му исполь­зуют в исходном виде до сих пор. Ско­пиро­вав файл SAM и рас­шифро­вав его сис­темным клю­чом из фай­ла SYSTEM, ата­кующий получа­ет спи­сок локаль­ных учет­ных записей и сох­ранен­ных для них кон­троль­ных зна­чений — хешей.

Да­лее взлом­щик может най­ти пос­ледова­тель­ность сим­волов, которая соот­ветс­тву­ет хешу адми­нис­тра­тора. Так он получит пол­ный дос­туп к ОС и оста­вит в ней мень­ше сле­дов, чем при гру­бом взло­ме с помощью баналь­ного сбро­са пароля. Напоми­наю, что из‑за эффекта кол­лизии под­ходящий пароль не обя­затель­но будет таким же, как у реаль­ного вла­дель­ца компь­юте­ра, но для Windows раз­ницы меж­ду ними не будет вов­се. Как пела груп­па Bad Religion, «Cause to you I’m just a number and a clever screen name».

Ана­логич­ная проб­лема сущес­тву­ет и в дру­гих сис­темах авто­риза­ции. Нап­ример, в про­токо­лах WPA/WPA2, широко исполь­зуемых при соз­дании защищен­ного под­клю­чения по Wi-Fi. При соеди­нении меж­ду бес­про­вод­ным устрой­ством и точ­кой дос­тупа про­исхо­дит стан­дар­тный обмен началь­ными дан­ными, вклю­чающи­ми в себя handshake. Во вре­мя «рукопо­жатия» пароль в откры­том виде не переда­ется, но в эфир отправ­ляет­ся ключ, осно­ван­ный на хеш‑фун­кции. Нуж­ные пакеты мож­но перех­ватить, перек­лючив с помощью модифи­циро­ван­ного драй­вера при­емник адап­тера Wi-Fi в режим монито­рин­га. Более того, в ряде слу­чаев мож­но не ждать момен­та сле­дующе­го под­клю­чения, а ини­циали­зиро­вать эту про­цеду­ру при­нуди­тель­но, отпра­вив широко­веща­тель­ный зап­рос deauth всем под­клю­чен­ным кли­ентам. Уже в сле­дующую секун­ду они попыта­ются вос­ста­новить связь и нач­нут серию «рукопо­жатий».

Сох­ранив файл или фай­лы с хен­дшей­ком, мож­но выделить из них хеш пароля и либо узнать сам пароль, либо най­ти какой‑то дру­гой, который точ­ка дос­тупа при­мет точ­но так же. Мно­гие онлай­новые сер­висы пред­лага­ют про­вес­ти ана­лиз не толь­ко чис­того хеша, но и фай­ла с записан­ным хен­дшей­ком. Обыч­но тре­бует­ся ука­зать файл pcap и SSID выб­ранной точ­ки дос­тупа, так как ее иден­тифика­тор исполь­зует­ся при фор­мирова­нии клю­ча PSK.

По­ка с помощью онлай­новых сер­висов и радуж­ных таб­лиц находят­ся далеко не все пары хеш — пароль. Одна­ко фун­кции с корот­ким дай­джес­том уже побеж­дены, а корот­кие и сло­вар­ные пароли лег­ко обна­ружить даже по хешам SHA-160. Осо­бен­но впе­чат­ляет мгно­вен­ный поиск паролей по их дай­джес­там с помощью Гуг­ла. Это самый прос­той, быс­трый и совер­шенно бес­плат­ный вари­ант.

Читайте также: