[Из песочницы] Аппаратный менеджер паролей или как перестать вводить пароли и начать жить
Меня зовут %username%, мне n лет и я параноик. И каждый день информационный мир усложняет мне жизнь. Технологий становится больше, порог вхождения в IT снижается, и мы получаем действительность, где грубые ошибки в безопасности это нормально. А еще и мощность вычислительной техники растет с каждым годом. В итоге наши пароли, хранимые как получится, становятся достоянием общественности.
Безопасность не мертва, но инкапсулирована и агонизирует. И с каждым годом стук по крышке черного ящика все тише, а сдавленные вопли и вовсе больше не слышны. Уж больно много абстракций поверх.
Мы не знаем как хранит наши пароли очередной сервис, поэтому мы сами должны заботиться о своей безопасности, но и это становится все сложнее с каждым годом. А количество необходимых для комфортной жизни сервисов только растет. И для каждого надо иметь свой стойкий и уникальный пароль. Не на это я свою личную жизнь променивал.
Поэтому мы придумали свой хакерский подход к хранению и вводу паролей.
Кратко: телефон связан через Bluetooth со специальным девайсом, который эмулирует клавиатуру. Утеря девайса и телефона не позволяют получить паролей. Утеря девайса и мастер-пароля тоже не страшны. Как так? Добро пожаловать под кат (там 7 картинок, но они красивенькие).
PSD НЕ является заменой криптографическим токенам. Это совершенно разные области. Здесь идет речь только о символьных паролях, которые будут вводиться автоматически через эмуляцию клавиатуры.
Какую проблему я решаю
Символьные пароли являются наследием, которое будет использоваться большим количеством сервисов достаточно продолжительное время. Я не буду сейчас даже начинать про то, что далеко не все люди_которые_программируют используют правильные техники хранения паролей на сервере.
hash (hash (pass)+user_id+salt)
По большей части я решаю проблему удобства ввода пароля. И это важнее, чем кажется.
Когда вы придумываете пароль, вы всегда держите в голове, что потом его может быть нужно ввести руками. Например, если это пароль для шифрованного диска с ОС. Или для авторизации в вашу любимую операционную систему. Даже тот же ввод пароля с телефона будет болью в пальцах для 16-ти символьного пароля с символами и буквами в разных регистрах. И все это может вынудить использовать какое-то упрощение, которое снизит стойкость пароля.
Пользователей ICloud легко вычислить по их паролям, так как они часто имеют заглавной первую или последнюю букву. Часто используются имя и дата рождения/возраст
Как проблему решали до меня
Некоторые менеджеры паролей позволяют заполнять некоторые поля автоматически. Но ни один программный менеджер не будет работать без загруженной, позволяющий выполнять чужие бинари, операционной системы. Мало того, невозможно собрать код менеджера под все существующие ОС. Что приводит к проблеме невозможности автоматизированного ввода паролей в большом количестве юзкейсов.
Вот некоторые из них:
- ОС еще не загружена
• диск с ОС зашифрован
• разделы с ОС зашифрованы - Требуется авторизация в ОС
- ОС не разрешает использовать запоминающие устройства (корпоративная политика)
- ОС запрещает выполнение любого пользовательского кода (корпоративная политика)
- ОС не поддерживается менеджером паролей
• малораспространенная ОС
• устаревшая ОС
PSD с точки зрения пользователя
Собственно, был придуман аппаратный менеджер паролей с возможностью хранить и вводить пароли до 128-ми символов. Если не рассматривать принципов работы системы (которые обеспечивают безопасность в случае утери устройств), то аппаратный менеджер эмулирует клавиатуру и вводит пароль, выбранный с телефона. Связь между устройствами через Bluetooth.Чуть подробнее
Система состоит из трех устройств.
Домашнего компьютера (MAIN_PC) с программой на нем:
Телефона с Bluetooth (PHONE) и программой:
Специального девайса (PSD):
PSD расшифровывается как Paranoia Satisfaction Device
Как внести пароли в систему:
- Подключить PSD и телефон к главному компьютеру
- С помощью специальной программы записать свои пароли в базу
- Перенести одну из полученных баз на телефон
База дублируется. После записи паролей в программу будет создано 2 файла базы и еще одна база записана в PSD. Первая база остается на компьютере для предотвращения утери паролей. Вторую надо перенести на телефон.
Как этим всем пользоваться:
- Подключить PSD к usb любого компьютера, на который надо внести пароль (FOREIGN_PC)
- В приложении на телефоне выбрать пароль, который хотим ввести
После этого, PSD введет пароль. Компьютер будет думать, что пароль вводится с подключенной хардварной клавиатуры.
PSD с точки зрения безопасности
А теперь действительно интересная часть. Надо сделать это все безопасным. Конечно, нельзя сделать невзламываемую систему, но можно максимально сократить количество векторов атак, чем мы и займемся.
Цели, которые я ставлю для системы:
- Утеря PSD, телефона или обоих девайсов не раскроет паролей пользователя и не позволит дешифровать перехваченный bluetooth трафик
- Незаметно для пользователя достать базу с PSD невозможно
- Если утек мастер-пароль, то утеря одного из девайсов не раскроет пароли
Если перефразировать, то придем к концепции: надо иметь все данные и устройства, что имеет пользователь, чтобы получить пароли. Менеджер никогда не должен понижать безопасность.Хранение
Начнем с базы на компьютере. Это первое что создает пользователь и в ней все банально. Это всего-лишь шифрованный JSON. Шифрование — AES256/CBC/PKCS7Padding. В скором времени планируем перейти на формат KeePass.
Не стоит забывать, что с любого устройства можно считать память. Поэтому хранить пароли в открытом виде на PSD нельзя ни в коем случае. Но и шифрование слабо поможет, так как тогда пароль будет храниться в той же памяти. Поэтому было выбрано решение не хранить полноценные пароли вообще (кроме запасной базы на MAIN_PC).
Алгоритм хранения паролей очень прост:
- Записываем в password_part_1 128 рандомных байт
- Делаем XOR пользовательского пароля с password_part_1 и получаем password_part_2
В итоге получим для каждого пароля по 2 части (password_part_1, password_part_2), XOR которых даст нам исходный пароль (с паддингом из \0 в конце). Так как паролей у нас много, то password это массив. Соответственно, мы будем иметь по массиву частей паролей на каждом устройстве.
password_part_1[i] ⊕ password_part_2[i] == password[i]
Мы будем хранить первые части (password_part_1) на телефоне и password_part_2 на PSD. Для ввода пароля будем слать password_part_1[PassId] через Bluetooth и XOR-ить их с password_part_2[PassId] на PSD. Таким образом мы получим пароль по индексу PassId, который введем на компьютер (FOREIGN_PC), эмулируя хардварную клавиатуру.
Шифрование трафика
Но что если хакер решит перехватить трафик и украсть PSD. Он все еще сможет прочитать память с EEPROM и получить пароли, части которых он достал из трафика. Значит трафик надо шифровать (не особо оригинально, да).
Трафик надо зашифровать так, чтобы при утере PSD нельзя было расшифровать пакеты. Проблема в том, что хакер знает все, что знает PSD. Если PSD умеет расшифровывать трафик за счет информации на нем, то и хакер сможет расшифровать трафик. Мы будем использовать одноразовые ключи, обновляющиеся с каждым новым пакетом. PSD будет иметь ключ только для следующего пакета, но не для полученного ранее. Изначально одинаковые ключи задаются компьютером (MAIN_PC) при записи баз.
BtKey и HBtKey — ключи для шифрования и проверки целостности пакета. Они оба меняются с каждым сообщением. Для проверки целостности применяется HMAC на основе SHA256. Ключом для него является HBtKey[i]. Для шифрование самого пакета применяется AES256/CBC/PKCS7Padding. В пакете передается password_part_1 и PassId. Так же в пакете есть и ключи для дешифрования следующего пакета (HBtKey[i+1], BtKey[i+1]).
Как только пакет попадает на PSD и дешифруется, сразу же генерируется ответ телефону. Это sha256(HBtKey[i]). HBtKey[i] — предыдущий ключ для HMAC. Далее пароли в памяти PSD заменяются на новые (i+1). И происходит ввод пароля на FOREIGN_PC.
После этого телефону отправляется ответ, что все введено корректно (sha256(HBtKey[i])) и телефон удаляет старые ключи, заменяя их новыми.
Больше списков богу списков:
- Телефон генерирует BtKey[i+1] и HBtKey[i+1]
- EncryptedPayload = AES256(key: BtKey[i], input: PassId + password_part_1+ BtKey[i+1] + HBtKey[i+1])
- EncryptedMessage = IV + EncryptedPayload + HMACsha256(key: HBtKey[i], input: EncryptedPayload)
- телефон отправляет пакет EncryptedMessage на PSD
- PSD расшифровывает EncryptedMessage, используя BtKey[i] и проверяет целостность с помощью HBtKey[i]
- PSD генерирует ответ телефону (но не отправляет). Response = sha256(HBtKey[i])
- PSD меняет свои HBtKey[i] и BtKey[i] на новые, полученные из пакета (i+1). Старые удаляются
- PSD собирает пароль (password_part_1 ⊕ password_part_2[PassId]) и вводит его на компьютер (FOREIGN_PC), притворяясь клавиатурой
- PSD отправляет Response телефону
- Телефон проверяет респонс и меняет ключи на новые
- i++
В итоге получается, что паролей для дешифрования уже посланных пакетов больше не существует. Существуют только пароли для дешифрования следующего пакета.
Заключение
Получилась достаточно удобная, интересная и безопасная штука.
К сожалению, я не могу описать всю систему в рамках одной статьи. Я уже вышел за 13к символов, а рассказал только основную концепцию общей системы. Если эта статья была кому-то интересна, то я могу написать еще одну, которая покроет остальные аспекты безопасности. Там есть достаточно интересные подходы.
Приложение на телефоне тоже имеет несколько интересных особенностей, помогающих держать баланс между безопасностью и удобством (доступ к шифрованной базе имеет только сервис, что позволяет вводить пароль один раз и применять разные политики его сброса. Например, через 30 минут после ввода).
А девайс будет иметь возможность запуска кастомных прошивок, чтобы реализовывать любой функционал, который потребуется (например, bluetooth usb-клавиатура). И там есть тоже несколько интересных вещей в подходах к соблюдению безопасности.
Сейчас у нас есть рабочий прототип устройства, прошивки на устройство, программа на Android и две программы (gui и консольная) на компьютер.
Программы для компьютера написаны на .net и хорошо работает под mono. Но под Linux системами библиотека, которую я использую для связи с PSD, не видит девайсов, но я планирую это исправить.
Весь код для телефона и для компьютера открыт. Его можно найти на гитхабе.
В планах у нас следующее:
- По результатам вашей реакции оценить нужность девайса и какие компоненты мы сможем позволить там использовать
- Поддержка установки паролей со всего, что имеет mono (Linux, Mac OS)
- Перейти на формат KeePass для базы на MAIN_PC
- Bluetooth 4.0
- Возможность собирать базу, имея только телефон и PSD
- Возможность добавлять пароли с телефона
- Возможность синхронизировать пароли без MAIN_PC
Мы собираемся продолжить заниматься проектом, но было бы очень интересно узнать мнение хабрасообщества о перспективах. Среди моих знакомых достаточно много людей, которые хотели бы подобное устройство себе в пользование, поэтому у меня есть предпосылки, чтобы провести небольшой опрос.
Поиск уязвимостей
Кстати, в описанном протоколе есть таки логическая уязвимость. Ее невозможно эксплуатировать удаленно (проще поставить кейлоггер) и она исправляется без костылей. Вы можете попробовать свои силы в поиске этой уязвимости (уязвимость логическая, а не на уровне кода) и первому человеку, который ее найдет, мы обещаем подарить готовый девайс (в случае если мы начнем массовое производство).
Естественно, в случае релиза, эта уязвимость будет закрыта.
- Ж п ю н р с P
- В P п о с с т
- С т
- Д п д п с P и д п с
- ?
- P