Здравствуйте, хабражители!
В далеком декабре прошлого года я впервые столкнулся с Data Protection Application Programming Interface (сокращенно DPAPI). Тогда я изучал способ хранения логинов/паролей в браузере Chrome. Я обещал, что распишу эту систему подробно и на пальцах. Негоже врать, поэтому добро пожаловать под кат!
Начну всё с азов, что же такое DPAPI, зачем он создавался и кому он нужен. И затем уже расскажу, как это работает.
Проблемы информационной безопасности уже давно коснулись всех, и Microsoft был не исключением, офисные ПК, домашние системы, сервера — все в той, или иной степени, требовали защиты от чужих рук.
Хранение данных в открытом виде было уже, как минимум, не солидно. Поэтому с выходом Windows 2000 свет увидел зарождающуюся и сырую версию DPAPI. Её основная цель — защита хранимых паролей и конфиденциальной информации на компьютере. Причем таким способом, чтобы владелец этих данных (пользователь) даже не догадывался о существовании защиты, а взломщику эти данные были недоступны. Идеология системы с той поры не изменилась. Менялись алгоритмы, закрывались дыры, но суть была всё та же.
В итоге появилась полноценная система безопасности, в которой секретные данные были доступны исключительно пользователю-владельцу и никому другому.
Так выглядит тривиальная схема работы с DPAPI.
Приложение обращается к ОС задавая параметры Mysecret(строка/байты, которые нужно засекретить) и Entropy(энтропия, о ней чуть позже. Данный параметр не обязательный).
На выходе получаем BLOB.
BLOB – Binary Large OBject. Расшифровка является бэкронимом. По сути, это массив двоичных данных. «Большое и бесформенное».
Этот BLOB — своего рода контейнер, в котором содержаться в открытом виде данные, необходимые для расшифровки, а так же сам шифр. Приложение сохраняет его (для примера всё тот же Chrome, который записывал этот BLOB в виде массива байт в одно из полей SQLITE базы данных), а в дальнейшем, при необходимости, расшифровывает(вторая половина схемы).
Так выглядит эта же схема, но более подробно.
Криптопровайдер- это набор алгоритмов для хэширования, шифрования, ключевого обмена и ЭЦП в форме модуля. К примеру в России есть наши ГОСТовские алгоритмы и криптопровайдер, который их объединяет, поэтому если дать его системе, то вместо стандартных AES, SHA, RSA будут использоваться наши ГОСТы. Всё это настраивается в реестре. Из этого следует, что самой DPAPI нет разницы с какими алгоритмами работать, они меняются «как перчатки», что делает систему универсальной.
Про LSA и CryptoAPI отвечу цитатой с википедии:
Всё самое интересное происходит в недрах LSA, смертным там делать нечего, поэтому повлиять на работу этого процесса практически невозможно.
Теперь поговорим непосредственно о схеме шифрования/дешифрования.
По сути, это всего 3 функции:
1) Открытие мастер-ключа
2) Шифрование
3) Дешифрование
Неважно что мы хотим сделать — зашифровать, или расшифровать — сначала необходимо открыть мастер-ключ.
Мастер-ключ (далее МК) — это ключ шифрования для симметричного алгоритма шифрования (по умолчанию в Windows 7 это AES). Является так же BLOB'ом, в котором есть открытая (ID, алгоритмы..) и закрытая (сам ключ) информация.
МК — самая главная часть системы, поэтому он находится под надежной защитой.
Тут у разработчиков возникла дилемма. Как сделать так, чтобы пользователя не доставать вводом паролей (USB-ключей), но при этом как то защитить мастер-ключ? Очевидно, что для этого необходимо взять «личную» и уникальную информацию системы. То есть это пароль пользователя на вход в систему. После входа в систему LSA хранит у себя этот пароль и по запросу CryptoAPI выдает его.
Это, собственно говоря, схема расшифровки ключа.
SID — уникальный идентификатор безопасности.
Кэш пароля из LSA — это кэш вашего пароля на вход в систему, если его нет, то берется null.
Потом считываются настройки
HMAC (сокращение от англ. hash-based message authentication code, хеш-код идентификации сообщений).
Если говорить просто – это та же хэш функция, которая даже работает на базе всё тех же MD5, SHA… Только для получения хэша требуется ещё и пароль, то есть вместо 1 параметра — их 2.
PBKDF2 – Password-Based Key Derivation Function. Стандарт формирования ключа на основе пароля. Использует псевдослучайную функцию для получения ключей. Длинна ключа не ограничивается. Фактически, это «усложнение» алгоритма хэширования. Если тот же SHA256 будет вычислен за доли секунды, то тут с его же помощью вычисление затянется до 0.1 секунды. Здесь важный параметр — количество итераций. На моем компьютере их, по умолчанию, 17400. Чем их больше — тем дольше выполняется алгоритм, тем сложнее подбор. Если не вникать в подробности алгоритма, то можно представить, что он 17400 раз выполняет алгоритм SHA256.
SHA(SHA(SHA...SHA(строка))...)
На выполнение подобного требуется время, а так как SHA претендует быть мифологической однонаправленной функцией, то на выходе значение будет уникальным.
0.1 секунды — это ничто, когда алгоритм выполняется 1 раз (с точки зрения пользователя), но это кошмар для перебора.
MasterKey BLOB — это как раз данные с зашифрованным ключом, но в нем так же хранятся и открытые данные, которые доступны для чтения системой, такие как соль, ID мастер-ключа и прочие служебные параметры.
В итоге на выходе мы получаем наш ключ.
Теперь приступим к шифрованию.
Здесь уже всё совсем просто, сначала ключ, HMACKEY1 (генерируется системой случайно) и введенная вами энтропия(ещё немного, и я расскажу про неё подробно) подаются аналогу алгоритма HMAC (теперь у него уже 3 входящих параметра). Полученные данные являются частным ключом для шифруемых данных. Соль так же генерируется случайно. Все эти данные используются при создании BLOB'a, который уже вернется программе на запрос шифрования.
Дешифровка проходит аналогично.
Здесь все нужные данные считываются из самого BLOB'a. На выходе получаем наш секрет.
В BLOB'e мастер-ключа есть много информации, открытой для чтения. Версия DPAPI, его ID, различные флаги, размер МК, соль, количество итераций, алгоритм хэширования, шифрования.
В BLOB'e с зашифрованными данными тоже много информации. Опять же версия, используемый криптопровайдер, ID MK, которым проходило шифрование, описание и даже подпись(хэш-сумма).
Отдельно хочется отметить такую вещь, как CredHistory.
Credential History. На первый взгляд – ненужная вещь, но всё бывает.
Допустим – вы сменили пароль. С точки зрения алгоритма – ваш мастер ключ стал недосягаем. Расшифровывать-то нечем! Но этот нюанс продуман. Система перешифрует мастерключ. Но процесс этот трудоемкий… Мастер ключей может быть много, и перешифровывать их надо все (по умолчанию каждые 90 дней генерируется новый для повышения безопасности, а уже зашифрованные данные привязаны к конкретному ключу). Поэтому Microsoft создали этот алгоритм. Предыдущий пароль не забывается… Он шифруется текущим паролем и сохраняется в стек. Поэтому если вдруг у системы не вышло расшифровать мастерключ, то она не спешит сдаваться. Используя текущий пароль, она расшифровывает первую запись в CredHist. И полученным паролем пытается снова расшифровать мастерключ. Нет? Используя этот пароль, она расшифрует следующий пароль в цепи. Процесс будет продолжаться до тех пор, пока пароли не иссякнут в цепи, либо мастер-ключ не будет расшифрован. Как же может случиться то, что МК не расшифруется? Например, если вы использовали сторонний софт для принудительного сброса пароля. Обычно такой софт не запускает «перешифровку» ключей DPAPI. Так что после такой процедуры вы теряете все ваши сохраненные данной системой пароли. Но если вы поменяете пароль после этого на тот, который есть в CredHist, то все пароли «оживут».
Представьте, что к Вам пришли гости с ребенком. Ребенок взял – и сменил пароль. Используя стороннюю утилиту вы сбрасываете пароль. Все ваши секретные данные стали для вас недоступны, но после вы вернули свой прежний пароль, и данные снова при вас. Если же пароль сбрасывался дискетой для сброса пароля, то здесь система запускает переиндексацию. Кстати говоря, в сбросе пароля дискетой используется система RSA. Открытый ключ для шифрования и сам шифр хранятся в реестре, а закрытый – на дискете. При смене пароля новый пароль шифруется открытым ключом и перезаписывается.
Вот теперь можно рассказать про энтропию. Если вы поняли принцип работы системы, то для Вас стало очевидно, что любые данные, зашифрованные без энтропии (или с одинаковой энтропией) легко расшифровываются любым приложением, запущенным от того же пользователя. То есть информация общедоступна в пределах владений пользователя. Энтропия же, по своей сути, является паролем для конкретных шифруемых данных. Задайте энтропию, и никакое ПО на вашем компьютере без знания этого параметра не сможет расшифровать BLOB.
Microsoft подал интересный пример использования энтропии в IE. Пароли с логинами там хранятся в реестре. Имя ключа — это хэш от ссылки, по которой проходит авторизация, а содержимое — зашифрованные данные. Так вот эта ссылка и является энтропией. То есть, даже перехватив эти данные и имея открытый мастер-ключ, вам придется перебирать ссылки, и, в итоге, владея всеми данными, вы с большой вероятностью не сможете полностью раскрыть украденные данные.
Схема такая:
1) Открывается ссылка mysite.ru/login.php.
2) IE берет хэш от этой ссылки.
3) IE ищет среди имен ключей имя, которое совпадает с данным хэшем.
4) Используя содержимое ключа(BLOB) и ссылку, в качестве энтропии, IE открывает информацию с логинами и паролями.
Если же на пункте 3 не было найдено совпадений, то это означает, что на данной странице пользователь ещё ничего не вводил.
Хочу передать благодарность проекту Passcape и, в отдельности, администратору проекта, который с удовольствием (надеюсь) ответил на все возникшие у меня вопросы по поводу DPAPI. Их приложение «Windows Password Recovery», насколько мне известно — уникальное, оно полностью эмулирует работу DPAPI.
Большое спасибо за внимание, с удовольствием отвечу на ваши вопросы.
В далеком декабре прошлого года я впервые столкнулся с Data Protection Application Programming Interface (сокращенно DPAPI). Тогда я изучал способ хранения логинов/паролей в браузере Chrome. Я обещал, что распишу эту систему подробно и на пальцах. Негоже врать, поэтому добро пожаловать под кат!
Начну всё с азов, что же такое DPAPI, зачем он создавался и кому он нужен. И затем уже расскажу, как это работает.
Коротко о главном
Проблемы информационной безопасности уже давно коснулись всех, и Microsoft был не исключением, офисные ПК, домашние системы, сервера — все в той, или иной степени, требовали защиты от чужих рук.
Хранение данных в открытом виде было уже, как минимум, не солидно. Поэтому с выходом Windows 2000 свет увидел зарождающуюся и сырую версию DPAPI. Её основная цель — защита хранимых паролей и конфиденциальной информации на компьютере. Причем таким способом, чтобы владелец этих данных (пользователь) даже не догадывался о существовании защиты, а взломщику эти данные были недоступны. Идеология системы с той поры не изменилась. Менялись алгоритмы, закрывались дыры, но суть была всё та же.
В итоге появилась полноценная система безопасности, в которой секретные данные были доступны исключительно пользователю-владельцу и никому другому.
Принцип работы
Так выглядит тривиальная схема работы с DPAPI.
Приложение обращается к ОС задавая параметры Mysecret(строка/байты, которые нужно засекретить) и Entropy(энтропия, о ней чуть позже. Данный параметр не обязательный).
На выходе получаем BLOB.
BLOB – Binary Large OBject. Расшифровка является бэкронимом. По сути, это массив двоичных данных. «Большое и бесформенное».
Этот BLOB — своего рода контейнер, в котором содержаться в открытом виде данные, необходимые для расшифровки, а так же сам шифр. Приложение сохраняет его (для примера всё тот же Chrome, который записывал этот BLOB в виде массива байт в одно из полей SQLITE базы данных), а в дальнейшем, при необходимости, расшифровывает(вторая половина схемы).
Так выглядит эта же схема, но более подробно.
Криптопровайдер- это набор алгоритмов для хэширования, шифрования, ключевого обмена и ЭЦП в форме модуля. К примеру в России есть наши ГОСТовские алгоритмы и криптопровайдер, который их объединяет, поэтому если дать его системе, то вместо стандартных AES, SHA, RSA будут использоваться наши ГОСТы. Всё это настраивается в реестре. Из этого следует, что самой DPAPI нет разницы с какими алгоритмами работать, они меняются «как перчатки», что делает систему универсальной.
Про LSA и CryptoAPI отвечу цитатой с википедии:
Сервер проверки подлинности локальной системы безопасности (англ. Local Security Authority Subsystem Service, LSASS) — часть операционной системы Windows, отвечающей за авторизацию локальных пользователей отдельного компьютера. Сервис является критическим, так как без него вход в систему для локальных пользователей (не зарегистрированных в домене) невозможен в принципе.
CryptoAPI — интерфейс программирования приложений, который обеспечивает разработчиков Windows-приложений стандартным набором функций для работы с криптопровайдером. Входит в состав операционных систем Microsoft. Большинство функций CryptoAPI поддерживается начиная с Windows 2000.
Всё самое интересное происходит в недрах LSA, смертным там делать нечего, поэтому повлиять на работу этого процесса практически невозможно.
Ещё дальше в лес
Теперь поговорим непосредственно о схеме шифрования/дешифрования.
По сути, это всего 3 функции:
1) Открытие мастер-ключа
2) Шифрование
3) Дешифрование
Неважно что мы хотим сделать — зашифровать, или расшифровать — сначала необходимо открыть мастер-ключ.
Мастер-ключ (далее МК) — это ключ шифрования для симметричного алгоритма шифрования (по умолчанию в Windows 7 это AES). Является так же BLOB'ом, в котором есть открытая (ID, алгоритмы..) и закрытая (сам ключ) информация.
МК — самая главная часть системы, поэтому он находится под надежной защитой.
Тут у разработчиков возникла дилемма. Как сделать так, чтобы пользователя не доставать вводом паролей (USB-ключей), но при этом как то защитить мастер-ключ? Очевидно, что для этого необходимо взять «личную» и уникальную информацию системы. То есть это пароль пользователя на вход в систему. После входа в систему LSA хранит у себя этот пароль и по запросу CryptoAPI выдает его.
Это, собственно говоря, схема расшифровки ключа.
SID — уникальный идентификатор безопасности.
Кэш пароля из LSA — это кэш вашего пароля на вход в систему, если его нет, то берется null.
Потом считываются настройки
HMAC (сокращение от англ. hash-based message authentication code, хеш-код идентификации сообщений).
Если говорить просто – это та же хэш функция, которая даже работает на базе всё тех же MD5, SHA… Только для получения хэша требуется ещё и пароль, то есть вместо 1 параметра — их 2.
PBKDF2 – Password-Based Key Derivation Function. Стандарт формирования ключа на основе пароля. Использует псевдослучайную функцию для получения ключей. Длинна ключа не ограничивается. Фактически, это «усложнение» алгоритма хэширования. Если тот же SHA256 будет вычислен за доли секунды, то тут с его же помощью вычисление затянется до 0.1 секунды. Здесь важный параметр — количество итераций. На моем компьютере их, по умолчанию, 17400. Чем их больше — тем дольше выполняется алгоритм, тем сложнее подбор. Если не вникать в подробности алгоритма, то можно представить, что он 17400 раз выполняет алгоритм SHA256.
SHA(SHA(SHA...SHA(строка))...)
На выполнение подобного требуется время, а так как SHA претендует быть мифологической однонаправленной функцией, то на выходе значение будет уникальным.
0.1 секунды — это ничто, когда алгоритм выполняется 1 раз (с точки зрения пользователя), но это кошмар для перебора.
MasterKey BLOB — это как раз данные с зашифрованным ключом, но в нем так же хранятся и открытые данные, которые доступны для чтения системой, такие как соль, ID мастер-ключа и прочие служебные параметры.
В итоге на выходе мы получаем наш ключ.
Теперь приступим к шифрованию.
Здесь уже всё совсем просто, сначала ключ, HMACKEY1 (генерируется системой случайно) и введенная вами энтропия(ещё немного, и я расскажу про неё подробно) подаются аналогу алгоритма HMAC (теперь у него уже 3 входящих параметра). Полученные данные являются частным ключом для шифруемых данных. Соль так же генерируется случайно. Все эти данные используются при создании BLOB'a, который уже вернется программе на запрос шифрования.
Дешифровка проходит аналогично.
Здесь все нужные данные считываются из самого BLOB'a. На выходе получаем наш секрет.
В BLOB'e мастер-ключа есть много информации, открытой для чтения. Версия DPAPI, его ID, различные флаги, размер МК, соль, количество итераций, алгоритм хэширования, шифрования.
В BLOB'e с зашифрованными данными тоже много информации. Опять же версия, используемый криптопровайдер, ID MK, которым проходило шифрование, описание и даже подпись(хэш-сумма).
«Back to the beginning»
Отдельно хочется отметить такую вещь, как CredHistory.
Credential History. На первый взгляд – ненужная вещь, но всё бывает.
Допустим – вы сменили пароль. С точки зрения алгоритма – ваш мастер ключ стал недосягаем. Расшифровывать-то нечем! Но этот нюанс продуман. Система перешифрует мастерключ. Но процесс этот трудоемкий… Мастер ключей может быть много, и перешифровывать их надо все (по умолчанию каждые 90 дней генерируется новый для повышения безопасности, а уже зашифрованные данные привязаны к конкретному ключу). Поэтому Microsoft создали этот алгоритм. Предыдущий пароль не забывается… Он шифруется текущим паролем и сохраняется в стек. Поэтому если вдруг у системы не вышло расшифровать мастерключ, то она не спешит сдаваться. Используя текущий пароль, она расшифровывает первую запись в CredHist. И полученным паролем пытается снова расшифровать мастерключ. Нет? Используя этот пароль, она расшифрует следующий пароль в цепи. Процесс будет продолжаться до тех пор, пока пароли не иссякнут в цепи, либо мастер-ключ не будет расшифрован. Как же может случиться то, что МК не расшифруется? Например, если вы использовали сторонний софт для принудительного сброса пароля. Обычно такой софт не запускает «перешифровку» ключей DPAPI. Так что после такой процедуры вы теряете все ваши сохраненные данной системой пароли. Но если вы поменяете пароль после этого на тот, который есть в CredHist, то все пароли «оживут».
Представьте, что к Вам пришли гости с ребенком. Ребенок взял – и сменил пароль. Используя стороннюю утилиту вы сбрасываете пароль. Все ваши секретные данные стали для вас недоступны, но после вы вернули свой прежний пароль, и данные снова при вас. Если же пароль сбрасывался дискетой для сброса пароля, то здесь система запускает переиндексацию. Кстати говоря, в сбросе пароля дискетой используется система RSA. Открытый ключ для шифрования и сам шифр хранятся в реестре, а закрытый – на дискете. При смене пароля новый пароль шифруется открытым ключом и перезаписывается.
Энтропия
Вот теперь можно рассказать про энтропию. Если вы поняли принцип работы системы, то для Вас стало очевидно, что любые данные, зашифрованные без энтропии (или с одинаковой энтропией) легко расшифровываются любым приложением, запущенным от того же пользователя. То есть информация общедоступна в пределах владений пользователя. Энтропия же, по своей сути, является паролем для конкретных шифруемых данных. Задайте энтропию, и никакое ПО на вашем компьютере без знания этого параметра не сможет расшифровать BLOB.
Microsoft подал интересный пример использования энтропии в IE. Пароли с логинами там хранятся в реестре. Имя ключа — это хэш от ссылки, по которой проходит авторизация, а содержимое — зашифрованные данные. Так вот эта ссылка и является энтропией. То есть, даже перехватив эти данные и имея открытый мастер-ключ, вам придется перебирать ссылки, и, в итоге, владея всеми данными, вы с большой вероятностью не сможете полностью раскрыть украденные данные.
Схема такая:
1) Открывается ссылка mysite.ru/login.php.
2) IE берет хэш от этой ссылки.
3) IE ищет среди имен ключей имя, которое совпадает с данным хэшем.
4) Используя содержимое ключа(BLOB) и ссылку, в качестве энтропии, IE открывает информацию с логинами и паролями.
Если же на пункте 3 не было найдено совпадений, то это означает, что на данной странице пользователь ещё ничего не вводил.
Хочу передать благодарность проекту Passcape и, в отдельности, администратору проекта, который с удовольствием (надеюсь) ответил на все возникшие у меня вопросы по поводу DPAPI. Их приложение «Windows Password Recovery», насколько мне известно — уникальное, оно полностью эмулирует работу DPAPI.
Большое спасибо за внимание, с удовольствием отвечу на ваши вопросы.