Как расшифровать хеш 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
По уверениям создателей, в базу включены все слова из англоязычной версии Википедии и большинство популярных паролей, собранных из общедоступных списков. Среди них есть и хитрые варианты со сменой регистра, литспиком, повтором символов, зеркалированием и прочими ухищрениями. Однако случайные пароли даже из пяти символов становятся проблемой — в моем тесте половина из них не была найдена даже по LM-хешам.
«Крэк‑станция» с трудом вскрывает случайные пароли длиной от пяти символов даже по LM-хешам
«Облачный крэкер» мгновенно находит словарные пароли по их хешам
Собственного поиска на сайте пока нет, но пароль или его хеш можно написать прямо в адресной строке браузера, добавив его после адреса сайта и префикса /encrypt/.
Сервис MD5Decode знает все типы хешей от словарных паролей
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. Особенно впечатляет мгновенный поиск паролей по их дайджестам с помощью Гугла. Это самый простой, быстрый и совершенно бесплатный вариант.
Читайте также: