HL 2018. Конспект доклада «Make passwords great again! Как победить брутфорс и оставить хакеров ни с чем»

в 9:14, , рубрики: argon2, phe, pythia, брутфорс, высокая производительность, информационная безопасность, криптография, Программирование, радужные таблицы, Соль, хеширование

HL 2018. Конспект доклада «Make passwords great again! Как победить брутфорс и оставить хакеров ни с чем» - 1
Картинка: источник

Привет! Меня зовут Ахмадеев Ринат, я Sr. PHP developer.

Представляю вашему вниманию конспект доклада "Make passwords great again! Как победить брутфорс и оставить хакеров ни с чем" с HighLoad++ 2018.
Докладчик: Алексей Ермишкин, Virgil Security, Inc., Chief Product Security Officer.
Тезисы: https://www.highload.ru/moscow/2018/abstracts/3865.
Слайдов в открытом доступе еще нет, поэтому приводится их текстовая расшифровка.

Впечатление

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

В начале доклад казался действительно капитанским, и я даже начал терять интерес, но потом, как оказалось, даже узнал что-то новое.

Мне так понравился доклад, что я подготовил конспект. Всем рекомендую к ознакомлению.

Конспект

Вступление

Всем здравствуйте, всем доброе утро! Я рад всех вас видеть на конференции Highload. Меня зовут Алексей Ермишкин, я работаю в компании Virgil Security. Мы занимаемся разработкой различных криптографических продуктов как для индивидуальных разработчиков, так и для бизнеса. Фокусируемся на end-to-end решениях, это когда вам не нужно доверять сервису для того что бы выполнять какие-то действия как передача данных, аутентификация, и т.д. Наши SDK открыты и доступны всем для использования.

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

Итак, о чем же мы сегодня с вами поговорим?

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

Хеши

В принципе, почему пароли это такая больная тема, почему с ними стоит работать более аккуратно? Проблема в том, что у пароля маленькая энтропия. Что такое энтропия? Это кол-во информации, которая содержится в данных, т.е. например в слове Highload 8 букв — 8 байт, но если мы посчитаем энтропию, оно будет не 64 бита как все слово, а меньше 30-и бит. Когда сегодня говорят о взломе пароля, говорят что можно за такое-то время взломать пароли с энтропией не больше там или не меньше стольких-то бит. Т.е. даже само кол-во паролей не учитывается.

Слайд 1. Хеши
плюсы
— Необратимы

минусы
— Быстро вычисляются

Четыре Nvidia GTX 1080 Ti перебирают около 18 000 000 000 паролей в секунду (SHA-256)
Все пароли с энтропией не более 40 бит переберут приблизительно за 64 секунды.

Как же люди начали с безопасностью паролей работать? Первое что пришло в голову — это использовать однонаправленные криптографические хеши. Их замечательная особенность в том, что их нельзя повернуть назад. Т.е. Если вы в этот хеш передали какую-то информацию, получили на выходе значение, из этого значения обратно эту информацию вы получить не можете. Но, к сожалению, они очень быстро вычисляются. Например, современный кластер из 4-х видеокарт NVidia может перебирать несколько миллиардов паролей в секунду. Т.е. если энтропия вашего пароля меньше 40 бит, то кластер из 4-х видеокарт подберет его там за минуту, а то и того меньше.

Радужные таблицы

Слайд 2. Радужные таблицы
плюсы

— Мгновенный поиск по самым популярным паролям

минусы

— Занимают очень много места

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

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

Соль

Слайд 3. Соль!
плюсы

— Защищает от радужных тиблиц

минусы

— Не защищает от быстрого перебора

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

Как замедлить перебор?

Слайд 4. Как замедлить перебор?
Наивный подход:
SHA256(SHA256(SHA256(...)))

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

Слайд 5. Password hashing functions
SCrypt

Bcrypt

Argon2

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

Слайд 6. Argon2
image
(картинка взята из WikipediA)

К примеру самая современная функция Argon2 работает следующим образом: на схеме можно видеть, что есть очень много различных блоков памяти по которым пробегается хеш. Он это делает различными способами туда-обратно, память используется очень интенсивно, память используется вся. Оптимизировать такую функцию (скорость перебора) довольно сложно.

Слайд 7. Password hashing functions
Специально медленные

И на вашем железе тоже!

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

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

Facebook's password Onion

Слайд 8. А можно не нагружать бэкенд?

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

Слайд 9. Facebook's password Onion
$cur = 'password'
$cur = md5($cur)
$salt = randbytes(20)
$cur = hmac_sha1($cur, $salt)
$cur = remote_hmac_sha256($cur, $secret)
$cur = scrypt($cur, $salt)
$cur = hmac_sha256($cur, $salt)

Archaeological record of FB's struggles
with password security

Одним из первопроходцев в этом был Facebook. Эти строчки, которые вы видите, это исторические этапы Facebook, того как они защищали пароли, сначала были просто пароли, потом они взяли старую функцию md5, которая была уже давно взломана, затем они добавили туда соль и взяли хеш sha1, а затем произошла очень интересная штука, они вынесли вычисление функции hmac (это хеш с ключом) на удаленный сервис.

Слайд 10. Facebook
               Hash(salt, password)
[Web service] ---------------------> [Crypto service]
              <---------------------        ^
                     HMAC(key, hash)        |
                                          [key]

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

Слайд 11. Facebook
плюсы
— Защита от перебора

минусы
— Один ключ навсегда

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

Sphinx

Слайд 12. А можно лучше?

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

Слайд 13. Пароль — число?
p   a   s   s   w   0   r   d
112 97 115  115 119 48  114 100

Число — 8 097 880 544 746 959 460

И решили подойти следующим образом к этой проблеме: что если пароль или хеш от пароля представить представить в виде числа? Если у нас есть слово passw0rd, оно состоит из 8-ми байт. Во всех почти языках программирования есть целочисленные типы восьми байтовые, т.е. в принципе это одно и то же. Т.е. 8 байт, слово passw0rd и мы можем представить его в виде обычного десятичного числа. Что это нам дает? Это нам дает совершенно иную свободу действий. Мы можем пароли или хеши от них складывать, умножать, превращать в какие-то другие числа. Мы можем выполнять с ними настоящие серьезные математические операции.

Слайд 14. Sphinx — "менеджер" паролей

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

Слайд 15. Sphinx — «менеджер» паролей
                    [ домен ]
                        |
                        /
[ мастер-пароль ] -> [ хеш ] -> [ число a ]

Как подошел к этой проблеме Sphinx? Он берет мастер пароль, он берет домен, на который вы хотите зайти, прогоняет все это дело через хеш и превращает в число. А на самом деле там используется эллиптическая криптография, для простоты я буду все это объяснять на обычных числах с обычной математикой. Он превращает это в число (назовем его a) и что же он делает дальше?

Слайд 16. Sphinx — «менеджер» паролей
Маскировка!

[ a ^ (r*1/r) = a ]
r - большое случайное
число

Совершенно замечательная вещь, мы каждый раз можем генерировать большое случайное число r. Если возведем число a в степень r, а когда-то потом возведем это число в степень обратную числу r, то мы получим обратно это же число a, да? Т.е. мы можем с начала замаскировать что-то, а потом демаскировать.

Слайд 17. Sphinx — «менеджер» паролей
                                                [] PRIVATE
                                                  KEY (b)
                                                     |
                        a^r                          /
USER ----------------------------------------> SPHINX SERVICE
  |  <----------------------------------------
  /                  a^(r*b)
a ^ (r * b * 1 / r) = a^b -------------------> Jyiw19O2b5gXJi

И что делает сфинкс? Опять же есть пользователь, есть удаленный сервис. На этот удаленный сервис отправляется замаскированное число. На удаленном сервисе и есть приватный ключ b. Что он делает? Он присланное число a^r домножает на свой секретный ключ b и отправляет обратно. (Примечание автора конспекта: на слайде присланное число не домножается на приватный ключ, а возводится в степень приватного ключа, но тут главное суть). По скольку число r каждый раз разное, то удаленный сервис ничего не может сказать о том, какой пароль и домен были замаскированы, т.е. он каждый раз видит какие-то разные случайные числа. И он домножает просто на свой приватный ключ b и отправляет обратно. Пользователь демаскирует то, что прислал ему сервер и у него получается число — его мастер пароль с доменом умноженный на секретный ключ сервера a^b. Получается секретный ключ сервера он не знает, сервер не знает то, что ему прислал пользователь, но в итоге у него получается тоже какое-то детерминированное число. Каждый раз выполняя этот протокол маскировка будет разная, но результат будет всегда одинаковый и этот результат можно будет потом превратить обратно в какой-то пароль и использовать для входа на различные сайты.

Слайд 18. Sphinx — «менеджер» паролей
плюсы
— Защита от перебора
— Пароли не зависимы друг от друга
— Кража мастер-пароля ничего не дает
— Скорость

минусы
— Сервер не знает, кто к нему обращается
— Клиент не знает, кто ему отвечает
— Секретный ключ все еще статический

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

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

Pythia

Слайд 19.1. А можно лучше?

А можно лучше?

Слайд 19.2. END-TO-END!

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

Слайд 20. Pythia

И придумали такой протокол, который называется Pythia.

Слайд 21. Pythia
Adam Everspaugh et al.

Сервис знает, кто «вводит пароль»

Может доказать, что это — он

Его сделал замечательный человек Adam Everspaugh со своими коллегами. Чем он уникален? Во первых сервис знает, кто вводит пароль, т.е. на сервер по мимо пароля передается идентификатор пользователя. Это может быть какая-то случайная id-шка, которая лежит рядом с ним, или просто user name. Не важно. Но сервис об этом знает. Но мало этого сервер не просто знает, он может строго математически доказать, что он это он.

Слайд 22. Pythia
  [] Public key                            [] Private key (k)
        |                                           |
        /             UserID, a^r                  /
    [BACKEND] ----------------------------> [PYTHIA SERVICE]
        |     <----------------------------
        |       (UserID, a)^(r*k) + Proof
        /
(UserID, a)^(r*k*1/r) =
  (UserID, a)^k = y     ------------------> [   DATABASE   ]

Как это работает? Есть бэкенд (какой-то веб сервис, сайт) и есть сервис Pythia. Что делает бэкенд и что делает сервис? На сервисе есть приватный ключ k, но на бэкенд он так же передает свой публичный ключ. Бэкенд на сервис отправляет не только замаскированное число a^r, как в протоколе Sphinx, но так же отправляет какой-то идентификатор пользователя (UserID). Сервис домножает идентификатор пользователя и пароль на свой секретный ключ и результат (UserID, a)^(r*k) отправляет бэкенду. Так же он отправляет в ответ некий Proof, который может использоваться бэкендом для проверки сервера, что его не взломали, что он отвечает так как должен. Затем происходит демаскировка и число y которое получается в итоге кладется в БД. В базе данных у нас лежит не просто какой-то хеш, а лежит число, точка эллиптической кривой.

Слайд 23. Pythia
(UserID, a) — билинейная операция e(a^x, b^y) = e(a, b)^(x*y)

Schnoorr NIZK proof w/ Fiat-Shamir transformation.
Доказывает, что DL(g^x) == DL((UserID, a)^x)
g^x — Публичный ключ

Schnorr protocol

Здесь есть несколько интересных моментов:

  • Возможность для сервера комбинировать пользовательский идентификатор и пароль в одно число. Называется это билинейная операция или билинейное спаривание. Это сравнительно новая математика, которую не так давно начали использовать. У нее есть все свойства новых математик в том что не прошло еще 30и лет для того, что бы все убедились в том что все с этим нормально.
  • Зато Proof, который отправляет сервис — это довольно старая технология. Это называется протокол Шнорра. Генерация публичного ключа — это умножение базовой точки на какой-то секретные ключ. Протокол Шнорра доказывает, что тот секретный ключ, который использовался для генерации публичного ключа, вот он же и использовался для того что бы умножить пароль пользователя тоже на это же самое число. Этот протокол уже давным давно есть, он используется много где и он позволяет доказать. Это называется доказательство с нулевым разглашением — сервер свой публичный ключ не показывает, но при этом говорит, что ту операцию которую я выполнил, она была произведена именно тем приватным ключом, о котором мы изначально договаривались.

Слайд 24. Плюсы Pythia
— Не нагружает бэкенд
— Защита от перебора
— Сервис может блокировать попытки перебора (UserID)
— Сервис ничего не знает о пароле (blinding)
— Клиент уверен, что ему ответил конкретный сервис (ZKP)
— Бесшовная миграция с существующих решений

Какие у этой системы есть плюсы? А их у нее не много.

  • Система не нагружает бэкенд. Потому что бэкенд все что делает — это превращает пароль в число, маскирует его, отправляет, потом демаскирует так же результат.
  • Если базу с такими числами у вас украдут, то перебирать пароли тоже смысла никакого нет без приватного ключа.
  • Сервис Pythia может блокировать попытки перебора, а значит бэкенду этим в принципе не надо заниматься. Если он видит, что под одним и тем же идентификатором пользователя пытаются выполнить эту операцию трансформации несколько раз, он может просто по rate лимиту это все отсечь и заблокировать.
  • Благодаря маскировке сервис ничего не знает о пароле. Каждый раз ему присылается новое какое-то случайное число. Константой остается только идентификатор пользователя.
  • Благодаря ZKP (Zero-knowledge proof) бэкенд всегда знает, что ему ответил именно тот самый сервис, к которому он когда-то изначально обратился.
  • Если у вас есть база с хешами и с солью например, то вы можете мигрировать на такое решение бесшовно для пользователей. Они даже могут ничего не заметить. Вы вместо пароля пользователя берете его хеш, загоняете его в Pythia и в дальнейшем просто используете этот протокол, получаете число y, кладете опять его в свою базу. Хеш после этого можно удалить. Каждый раз когда пользователь будет заходить в вашу систему, будет выполняться этот протокол, будет получаться в результате какое-то число, которое вы сравните с тем, что в базе. Собственно система аутентификации останется неизменной, т.к. пользователи будут как логинились раньше, так и логиниться, с теми же самыми паролями, даже слабыми. При этом система будет гораздо более защищенной.

Слайд 25. Это ещё не всё
— Можно менять секретный ключ!
— Старый ключ — число k, новый k'
— Update token Δ = k' * 1 / k
— Для каждой записи y' = y * Δ

— Защита от кражи как базы, так и секретного ключа!
— Бесшовное обновление данных в БД
— Мгновенная инвалидация данных базы паролей

Но это не все плюшки. Одной из главных фич является то, что даже если взломают сам сервис Pythia, то можно сгенерировать новый приватный ключ. У нас же в базе хранится число, а не хеш. Если мы представим старый ключ как число k, а новый как число k', то мы можем вычислить число, которое называется Update token. Для этого мы умножаем новое число на число обратное старому. И вот этим вот update токеном можно пройтись по базе по каждому пользователю и умножить это число y на update token. После того, как вы это сделали, у вас система продолжает работать уже с новым приватным ключом на удаленном сервисе. Это все происходит мгновенно. Если случилась беда, у вас украли вашу базу данных с паролями, вы по щелчку пальца выпускаете update token и то, что украли у вас хакеры, становится мгновенно бесполезным. Вы просто потихонечку у себя проходитесь в фоновом режиме по всем записям, обновляете их и у вас они работают с новым секретным ключом. Пользователи вообще даже ничего не замечают. Т.е. бесшовное обновление и мгновенная инвалидация базы паролей, это вот одни из ключевых инновационных функций этой системы.

Слайд 26. Бонус
[BrainKey]
Y можно использовать для генерации ключа!
— Цифровая подпись
— Восстановление аккаунта
— Бэкапы
— etc.

Но и это еще не все. Число, которое лежит в базе, большое y, оно в принципе большое и выглядит довольно псевдослучайно, т.е. его так просто не подобрать. Если мы вот тот функционал, который у нас есть на бэкенде, перенесем, например, на клиентские устройства, на телефоны, то мы можем использовать вот этот y для генерации ключей. Мы называли эту штуку BrainKey. Значит, пользователь вводит пароль у себя где-то на телефоне, так же его маскирует, отправляет на удаленный сервис. Сервис возвращает ему какое-то число y и можно потом этот y использовать для генерации уже каких-то асимметричных ключей. Таким образом пользователь из своего пароля может получить ключевую пару. Это используется во всяких BrainWallet-ах. Это когда вы вводите пароль и получаете сгенерированный для него биткоин кошелек. Но не только криптовалютами ограничивается это применение, это и цифровая подпись, и какие-то бэкапы, и восстановление аккаунта, т.е. везде, где используется асимметричная криптография, где нужны асимметричные ключи. Все это можно использовать, но при этом ключевая пара, а их, в зависимости от необходимости, можно генерировать сколько угодно. Значит они все будут зависеть от пароля пользователя, и это очень удобно.

Слайд 27. Минусы?
— Новая математика (BLS12-381, ZCASH)
— Мало библиотек
— Скорость не совсем highload

Зато уже в Production!
Pythia.VirgilSecurity.com

В бочке меда как бы не без ложечки дегтя. И особенности этой технологии в том, что она очень новая. В ней используется эллиптическая кривая, которая для билинейных операций. Сама математика уже существует некоторое время, но вот эта конкретно кривая, которая используется в частности в нашей имплементации, она кроме нас используется только в ZCash-е. Соответственно библиотек, которые используют эту новую математику можно пересчитать по пальцам одной руки. Что бы вывести это в production состояние, нужно потратить какое-то кол-во времени и сил. Но тем не менее индустрия не стоит на месте и все эти минусы временные. Как следствие первых двух свойств, скорость этих билинейных операций не очень соответствует той современной математике, эллиптической в частности, которую мы сейчас все используем, когда используем протокол TLS, когда используем какие-то сайты. Это где-то несколько сотен операций на сервисе на одно ядро. На самом деле нас это не остановило и мы весной заимплементировали этот протокол, выпустили его в production и перевели все наши записи, защитили их с помощью этого протокола. Нас в принципе устраивает для наших текущих задач производительность, если будет нужно, мы поднимем еще одну ноду с сервисом Pythia и в принципе со всем этим уже можно поиграть.

PHE

Слайд 28. А можно еще лучше?

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

Слайд 29. Simple Password-Hardened Encryption Services (PHE)
     .  .  .                                /
    [ ][ ][ ]                []             _
Russell Lai et al.       Nist P-256         /
    Июль 2018                            Скорость
                                       ~10x Pythia

И буквально в июле этого года ученые выпустили новый протокол, который называется Simple Password-Hardened Encryption Services или сокращенно PHE. Это Russell Lai, ученый из Европы.

В чем преимущество этого сервиса? Во первых он использует стандартную кривую P-256, которая используется везде, во всех браузерах, продуктах, везде кривая по-умолчанию, которой уже много лет. Во вторых эта штука работает примерно раз в 10 быстрее чем Pythia и использует стандартные примитивы. Её как бы сложно, но можно имплементировать собственными руками, не используя какие-то библиотеки непонятные. Можно использовать OpenSSL, или Bouncy Castle, что угодно.

Слайд 30. Simple Password-Hardened Encryption Services (PHE)
    [] PUBLIC KEY             Enroll?             [] PRIVATE KEY (y)
[         []        ] -------------------------> [        []        ]
[      BACKEND      ] <------------------------- [   PHE SERVICE    ]
 [] PRIVATE KEY (x)     sNonce, C0, C1, Proof
                        C0, C1 - точки
                        С0 = y * (sNonce, "0")
                        C1 = y * (sNonce, "1")

HC0 = x * (cNonce, password, "0")  T0 = C0 + HC0      [ DATABASE:              ]
HC1 = x * (cNonce, password, "1")  T1 = C1 + HC1 + MC [ T0, T1, sNonce, cNonce ]
M = random, MC = x * M

Но работает она немножко по другому. Опять же есть бэкенд, есть сервис PHE. На бэкенде есть публичный ключ, на сервисе есть приватный ключ y. В отличии от Pythia, процесс регистрации и процесс проверки пароля проходит немножко по-разному. Когда на сервис приходит новый пользователь и хочет зарегистрироваться, что делает бэкенд? С начала он спрашивает у PHE-сервиса дай мне пожалуйста некоторые данные, которые я могу использовать для регистрации, какую-то Enrollment-запись. Сервис говорит OK и отвечает бэкенду следующими штуками. Он генерирует некую случайную 32-х байтную соль (sNonce). На основе этой соли и своего приватного ключа y он генерирует два числа, назовем их C0 и C1. Так же он генерирует доказательства (Proof) того что эти два числа или там 2 точки были сгенерированы именно с использованием его приватного ключа y, используя протокол Шнорра (как в предыдущих протоколах). Бэкенд проверяет Proof. Пароля здесь пока еще нет. Что делает бэкенд? У него со своей стороны тоже есть свой личный клиентский приватный ключ x и он, получив пароль от пользователя, делает примерно те же самое что делал сервис, только добавляет туда еще пароль. Он берет случайный cNonce (случайную клиентскую соль), пароль и генерирует опять 2 числа HC0 и HC1. Зачем 2? Потому что первое HC0 используется для аутентификации, а во второе число HC1 у нас подмешивается еще некое случайное число M домноженное на приватный ключ x (MC). Число M размером тоже 32 байта и в последствии может использоваться для шифрования пользовательских данных (у нас же Encryption Services) (примечание автора конспекта: ключ шифрования в данном случае будет MC). Число MC будет доступно в качестве ключа только после того, как пользователь ввел правильный пароль. Получается на этапе регистрации вы можете сгенерировать не только запись для авторизации, но и ключ шифрования, уникальный для каждого пользователя, которым можно зашифровать его профиль, какие-то данные, еще что-то. Затем бэкенд просто складывает то что прислал сервис и то что сделал он — складывает эти точки и получает T0 и T1. В первом случае складывает две (C0 + HC0), а во втором три (C1 + HC1 + MC). И кладет в базу 2 соли (sNonce, cNonce), с помощью которых были получены эти числа и 2 числа (T0 и T1), которые получились в результате суммы.

Слайд 31. PHE Login
                             C0, sNonce          [] PRIVATE KEY (y)
[         []       ] -------------------------> [         []       ]
[      BACKEND     ] <------------------------- [    PHE SERVICE   ]
 [] PRIVATE KEY (x)          C1, Proof
HC0 = x * (cNonce, password, "0")                С0 == y * (sNonce, "0")?
C0 = T0 - HC0

HC1 = x * (cNonce, password, "1")
MC = T1 - C1 - HC1                              [ MC - ключ шифрования! ]

Соответственно процесс аутентификации пользователя происходит в обратном порядке. Пользователь вводит свой пароль на бэкенде. Бэкенд вычисляет HC0 и из того, что у него лежит в базе, вычитает HC0 из T0 и отправляет получившееся C0 на сервис вместе с серверной солью. Сервис, зная серверную соль, вычисляет у себя эту же самую точку и смотрит, она совпадает с тем что прислал бэкенд или нет, если она совпадает, то значит пароль верный и можно ответить ему вторым числом C1, которое он вычтет вместе с HC1 из числа T1 и получит ключ шифрования. Таким образом пароль на сервис PHE даже не уходит. Он даже не покидает бэкенд. Он в виде каких-то точек умноженных на приватный ключ бэкенда. Он даже не существует как таковой, но при этом удаленный сервис может сделать строгий вывод о том корректный или нет этот пароль и доказать еще по мимо этого то, что он все вычисления провел с помощью своего приватного ключа y.

Слайд 32. Особенности PHE
  • Пароль не покидает бэкенд!
  • Нужен приватный ключ на клиенте
  • Все основные функции Pythia:
    • Защита от перебора
    • Сервис PHE ничего не знает о пароле
    • Строгие доказательства правильности / неправильности пароля
    • Возможность обновлять базу и ключи

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

  • можно так же выпустить update token если у вас что-то случилось с приватным ключом;
  • можно так же пройтись по всей базе, обновить и все будет как и было;
  • защита от перебора;
  • сервис ничего не знает о пароле;
  • строгие доказательства (Pythia вот, кстати, не знает, пароль правильный не правильный, а PHE знает);
  • возможность обновлять базу и ключи.

Слайд 33. Представляем

И нам так понравилась эта штука...

Слайд 34. passw0rd.io
    []                 []                []
Бесплатный      CLI для основных     Open-source
сервис PHE          операций             SDK

… что мы взяли и запилили сервис. Буквально вот ребята ночью его доделывали. Называется он passw0rd.io с ноликом. Во первых слово password с ноликом, это вот самый 18-й по популярности пароль в мире среди всех паролей, во вторых нолик символизирует, то что это zero trust, т.е. сервису можно не доверять. Так же это бесплатный сервис, абсолютно, т.е. как Let's encrypt. Можно прийти, зарегистрироваться и пользоваться. У него есть CLI для основных операций для регистрации, для создания приложений. Мы на сегодняшний день успели выпустить 2 SDK, это GO и .Net, которые работают с этим сервисом.

Слайд 35. PASSWORDS are like UNDERWEAR
1. Change them regularly
2. Don't leave them on your desk
3. Don't loan them to anyone

Ну и напоследок хочется сказать что пароли это как нижнее белье:

  1. Стоит их регулярно менять.
  2. Не стоит их оставлять на столе.
  3. Не надо их никому отдавать.

Слайд 36. РЕСУРСЫ
[] VirgilSecurity.com
[] @VirgilSecurity
[] GitHub.com/VirgilSecurity

[] NoiseSocket.com
[] passw0rd.io

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

ВОПРОСЫ?

Слайд 37. ВОПРОСЫ?

Возможно у вас есть вопросы.

Q: Здравствуйте, большое спасибо за доклад! Такой небольшой вопрос. Если у нас есть злоумышленник, который получил доступ к сервису Pythia и используя те данные выпустит свой update token, то у нас не потеряются абсолютно все пароли? Потому что мы не будем знать какой private key он использовал. Сможем ли мы их восстановить используя еще один update token? Или нет?
A: Да, update token-ы можно обновлять сколько угодно раз.
Q: Тогда собственно другой вопрос. Если этот злоумышленник остается с каким-то снифером в нашей сети и слушает новые update token-ы, то он может бесконечно обновлять свой Private key и мы никогда не сможем защитить от него базу?
A: Нет, ну процесс выпуска update token-ов, он как бы не автоматический, если что-то случается, происходит нотификация всех, нас взломали, мы будем выпускать update token. И если это сделает злоумышленник, т.е. разошлет всем почту.
Q: Нет, спасибо, если он не автоматически, то все понятно.
A: Т.е. тут есть возможность ручного управления.

Q: Здравствуйте, у меня вопрос, там вы говорили бесшовно мигрировать, если у вас используется какой-то хеш в Pythia и что-то я не очень понимаю, если у нас есть миллион сессий активных, соответственно бэкенд не знает пароли, мы можем бесшовно?
A: Да конечно.
Q: Мы заставим их заново вводить пароли?
A: Нет, мы просто вместо паролей в Pythia будем передавать хеш. Т.е. вы оставляете у себя соль, но когда пользователь логинится вы вычисляете опять хеш.
Q: (Не разборчиво) Так bcrypt все равно придется вычислять на бэкенде?
A: Хеш, который был у вас в базе, его придется вычислять, ну это не абы какая сложность.

Q: Доброе утро, у меня фанские вопросы. Какой пароль самый популярный все таки? Раз тот, который…
A: password без нуля
Q: password без нуля? Огонь! Вообще.
A: 123456 еще вот тоже, там в зависимости от года они там 12345, 123456.
Q: Хорошо. И вот минусы Pythia были отмечены, минусы PHE я не увидел.
A: А мы не нашли, мы собственно по этому как бы и закончили на этом доклад.
Q: Понятно. И третий вопрос. Вот сейчас кроме вас кто вообще использует такие штуки? В production для своих сервисов?
A: Никто пока. А! Яндекс использует Pythia.
Q: Яндекс использует Pythia, а он для чего, известно?
A: Для паролей.
Q: В каких сервисах, во всех?
A: Понятия не имею.
Q: Ок, понятно, спасибо!
A: Но они не выпустили SDK, и не показали это никому.

Q: Здравствуйте, вот скажите, вы говорили, что исключается возможность подбора пароля, т.е. там настраивается какое-то количество попыток, после которого замедляется подбор паролей? И сервис что делает? Перестает отвечать или как?
A: Нет, ну это настраивается же, в зависимости от потребности, т.е. сейчас у нас например на сервисе PHE, который мы недавно подняли, там то ли 5 паролей в 2 секунды, то ли 2 пароля в 5 секунд можно. Главное преимущество в том, что вы можете регулировать это. Можно например для PHE (он знает, что пароль ввели неправильно), если ввели неправильный пароль, то сделать блок на 10 секунд, или там на минуту.
Q: Т.е. вы помимо этого еще используете какие-то метрики, что бы словить алерты и какие-то действия предпринимать? Подразумевается ли такое?
A: Это можно сделать. Сейчас пока сделан просто rate limiting, а в принципе, в дальнейшем мы внедрим туда политики и вы сами сможете настраивать как реагировать на эти события.
Q: Т.е. момент подбора пароля к разным аккаунтам или к одному будет обнаружен таким образом, да?
A: Да.

Q: Здравствуйте. Подскажите, т.е. в итоге если украдут ключ с Pythia и украдут вашу базу паролей (хешей), то пароли я так понимаю все равно можно будет забрутфорсить, да? Подобрать?
A: Да, но проблема в том, что это надо сделать одновременно.
Q: До того, как выйдет update на вашу базу?
A: Да, если мы рассматриваем Pythia как сервис, который не стоит у вас же в вашей инфраструктуре, а какой-то другой удаленный сервис в какой-то другой компании, например у нас, то нужно будет взломать одновременно вас и нас, ну это как бы удачи)

A: Все? Спасибо всем большое! Надеюсь вам понравилось. У нас еще есть квест, кстати, на тему PHE, можно побрутфорсить хеши, приходите.

Выводы

На мой взгляд у сервиса PHE (как и у остальных сервисов) все же есть минус по сравнению с классическим подходом хеш+соль — добавляются точки отказа (сеть до сервиса, сервер с сервисом, сам сервис) и скорость выполнения операции увеличивается (как минимум за счет сетевого взаимодействия). Если использовать PHE сторонней компании как совершенно внешний сервис, то сюда добавляется еще сеть между датацентрами как точка отказа и дополнительное время на установление соединения и пересылку байтиков.

Тем не менее плюсы все же выглядят довольно вкусно:

  • перебирать пароли как заверяют будет невозможно (или очень долго) без приватных ключей;
  • в случае утечки базы или ключа достаточно обновить ключ и данные в базе (при должном умении это можно сделать бесшовно).

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

Спасибо Алексею Ермишкину и компании Virgil Security за то, что исследуете эту тему, делитесь информацией и публикуете исходные коды!

А как вы защищаете пароли (если не секрет)?

Автор: mougrim

Источник

Поделиться

* - обязательные к заполнению поля