Приветствую читателей Хабра! Меня зовут Александр Чикайло, я разрабатываю межсетевой экран уровня веб-приложений PT Application Firewall в Positive Technologies и специализируюсь на защите веба. Сегодня речь пойдет о беспарольной аутентификации и ее безопасном применении в приложениях. В этом материале я освещу систему passwordless-аутентификации, уже работающую «из коробки», например, в Windows 11 и Chrome.

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

История аутентификации на одном слайде
История аутентификации на одном слайде

Ненадолго углубимся в историю компьютерных паролей. В 1961 году Фернандо Хосе Корбато — американский ученый, сотрудник Массачусетского вычислительного центра — разработал первую систему компьютерных паролей. ПК тогда было мало, время их использования было ограничено, и Корбато выдавал каждому пользователю его пароль. В то время пароли хранились в открытом виде на листочке.

На излете 60-х для защиты паролей были придуманы хеш-функции (одно из значений слова hash — рубить, крошить). В 70-х стали «солить» хеш-функции, так как стало понятно, что радужные таблицы хешей постоянно пополняются, и вычислить простой хешированный пароль не составляет труда. В середине 70-х стали развивать ассиметричную криптографию, но до паролей она добралась, по историческим меркам, совсем недавно.

В 80-х, 90-х и нулевых были придуманы OTP (One Time Password — одноразовый пароль), технология единого входа (англ. Single Sign-On) SSO и мультифакторная аутентификация (MFA).

Несмотря на многочисленные трюки с паролями, долгое время уровень защищенности не сильно отличался от 1961 года, разве что злоумышленнику приходилась тратить чуть больше времени на взлом. В ранние 2010-е появилась биометрическая, а в поздние 2010-е — поведенческая аутентификация. 

В 2013 году образовался альянс FIDO (от англ. Fast Identity Online — быстрая онлайн-идентификация), в который входят более 250 организаций. Его цель — полный и повсеместный отказ от паролей. В 2014 году эксперт Gartner Авива Литан говорила, что пароли умерли еще несколько лет назад. Но они живы до сих пор, спустя 10 лет.

Что такое беспарольная аутентификация

Passwordless authentication означает, что пользователь может подтвердить доступ к приложению или IT-системе, не предоставляя пароль и не отвечая на секретные вопросы. К беспарольным методам относится, например, биометрия (вход в систему по отпечатку пальца, сердцебиению, походке, клавиатурному почерку, сетчатке, голосу, лицу и так далее). 

Какая бывает биометрическая аутентификация
Какая бывает биометрическая аутентификация

Беспарольная аутентификация может быть также по QR-коду (как в Telegram) или с помощью push-сообщения. Если мы пытаемся войти в Gmail и уже залогинены в телефоне, то нам прилетит «пуш» для подтверждения того, что мы это мы.

Аутентификация по QR-коду (как в Telegram) или с помощью push-сообщения
Аутентификация по QR-коду (как в Telegram) или с помощью push-сообщения

Существуют также SMS- и email-коды, а также Magic link (для аутентификации на некоторых сервисах можно использовать не пароль, а имя и ссылку в электронной почте), смарт-карты и SRPP (хотя этот метод не совсем беспарольный, поговорим об этом позже).  

Что же не так с паролями?

По статистике HackerOne (восьмая строка на скриншоте ниже) выплаты за найденные баги растут, а значит, с аутентификацией есть проблемы. Пароли утаскивают с помощью фишинга, инъекций, кейлоггеров, вследствие использования одинаковых паролей и так далее.

Более миллиона долларов выплатили на HackerOne исследователям проблем аутентификации за год
Более миллиона долларов выплатили на HackerOne исследователям проблем аутентификации за год

С одной стороны, парольные политики не идеальны, хотя без них повсеместно применялись бы пароли вида 123 и ситуация с защищенностью была бы еще хуже. С другой стороны, множеством сложных паролей тяжело управлять. Для этого пользователи начинают записывать их на листочках или хранят в password-менеджерах, защищенных единым мастер-паролем (кража которого приводит к компрометации остальных).

Ниже в левой части графика мы видим практически непрерывный рост количества CVE-уязвимостей по ключевым словам plain text, brute force и «проблема с аутентификацией» (данные за середину 2023 года, поэтому в 2023 году уязвимостей меньше).

Число CVE-уязвимостей по ключевым словам plain text, brute force и «проблема с аутентификацией» неуклонно растет
Число CVE-уязвимостей по ключевым словам plain text, brute force и «проблема с аутентификацией» неуклонно растет

Как принято обходить веб-аутентификацию

У OWASP в «Руководстве по тестированию веб-безопасности» (Web Security Testing Guide, WSTG) перечислены 11 пунктов, касающихся тестирования защищенности веб-приложений. Для полноты картины добавим еще четыре подсказки из OWASP Authentication Cheat Sheet, которые не пересекаются с WSTG. Самая большая боль для специалистов — это, наверное, Default Credentials (пароли, используемые по умолчанию, или инженерные пароли).

Рекомендации OWASP по тестированию проблем аутентификации в веб-приложениях
Рекомендации OWASP по тестированию проблем аутентификации в веб-приложениях

Первый блин в виде SRPP

Одна из попыток прийти к passwordless была связана с Secure Remote Password Protocol (SRPP). На сервер в данном случае улетает соль, верификатор и логин, что позволяет пользователю хранить пароль в браузере, используя только логин. Однако пароль в этой схеме аутентификации все же используется, несмотря на применение доказательства с нулевым разглашением (zero-knowledge proof). А значит, сохраняются и недостатки: возможность фишинга, атаки на повторяющиеся пароли (password reuse) и так далее.

Secure Remote Password Protocol (SRPP) уязвим для фишинга
Secure Remote Password Protocol (SRPP) уязвим для фишинга

Настоящая беспарольность в виде WebAuthn

Следом появился стандартизированный механизм веб-аутентификации — WebAuthn. Он позволяет аутентифицироваться без паролей, так как их здесь в принципе нет. Тут взаимодействуют следующие участники: наше приложение и его бэкенд, фронтенд и аутентификатор. При этом аунтентификатор может быть платформенным (например, Windows Hello) или аппаратным — в виде бесконечного количества токенов. Схему генерации токенов можно найти в Сети или запрограммировать самому. Также для создания WebAuthn-приложения можно воспользоваться инструкцией Google.

Далее в таблице можно посмотреть, какие браузеры поддерживают WebAuthn. Красный цвет — отсутствие поддержки, зеленый — полная совместимость, а горчичный — частичная поддержка.

Какие браузеры поддерживают WebAuthn
Какие браузеры поддерживают WebAuthn

Как работает WebAuthn

Процесс регистрации для беспарольной аутентификации — это ввод имени пользователя на сайте. Затем эти данные отправляются на бэкенд, там генерируется JSON (слева на схеме ниже, PublicKeyCredentialCreationOptions) — это будет нужно в дальнейшем для создания JS-объекта и передачи его в аутентификатор. В этот JSON входят хеш origin нашего приложения, challenge. Мы получили эти данные, JS создает объект и отправляет запрос на аутентификатор. Аутентификатор генерирует пару ключей, причем приватный ключ он хранит внутри себя. Параметр challenge, подписанный этим приватным ключом, аутентификатор отдает обратно в браузер, и браузер формирует объект, которой передает обратно на наш бэкенд. 

Приведем пример процесса регистрации при использовании WebAuthn.

Регистрация клиента WebAuthn
Регистрация клиента WebAuthn

На скриншоте — код, который отправляет клиентское приложение, и ответ ему со стороны бэкенда. Большой блок в центре кода в правой части — настройки алгоритмов.

 

Регистрация клиента WebAuthn, первый запрос и ответ
Регистрация клиента WebAuthn, первый запрос и ответ

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

Регистрация клиента WebAuthn, второй запрос и ответ
Регистрация клиента WebAuthn, второй запрос и ответ

Процесс аутентификации не сильно отличается от привычной схемы. Мы вводим логин, и он улетает на бэкенд. Там по id имени пользователя вытаскивают PublicKeyCredentialCreationOptions — параметр, хранящийся и на бэкенде, и в аутентификаторе. Далее это все собирается в JSON, отдается в браузер, JS собирает объект и кидает запрос на аутентификацию в наш аутентификатор. Он все проверяет, просит нас отсканировать палец, дотронуться до устройства (как в случае YubiKey) или ничего не делать. Подписал, вернул, сервер верифицирует все подписи, проверяет значение origin, которое тоже хранится в ответе аутентификатора. Если все хорошо — значит мы залогинились. 

Аутентификация клиента в WebAuthn
Аутентификация клиента в WebAuthn

Большой разницы в запросах и ответах нет: clientData вместо createGet и отличие в signature, где хранится подписанный сhallenge. А в поле userHandle хранится наш пользователь.

 

Аутентификация клиента в WebAuthn
Аутентификация клиента в WebAuthn

Настройка WebAuthn

Продемонстрируем, как сконфигурировать нашу беспарольную аутентификацию. Надо ввести два поля: user name и display name. Затем остается добавить платформозависимый аутентификатор, в нашем случае Windows Hello. Все, мы зарегистрированы, и нам не нужны никакие пароли. Это система аутентификации работает «из коробки» как минимум в Windows 11 и в современных редакциях Google Chrome.

Настраиваем WebAuthn
Настраиваем WebAuthn

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

Еще немного настроек
Еще немного настроек

Для тех случаев, когда нам важно, кто пришел в приложение (например, в банке), можно добавить обязательный запрос информации о токене в поле Attestation conveyance preference. То есть мы можем получить версию, модель и другие параметры токена и одобрить использование только сертифицированных в FIDO Alliance Metadata Service токенов.

Здесь можно добавить обязательный запрос информации о токене в поле Attestation conveyance preference
Здесь можно добавить обязательный запрос информации о токене в поле Attestation conveyance preference

Чуть ниже — варианты для выбора аутентификаторов. Первый — это платформозависимый аутентификатор, привязанный к платформе (on bound (platform) authenticator). В Windows это Hello, в Linux по умолчанию его нет. Другой вариант — кроссплатформенный аутентификатор. Это аппаратный аутентификатор, например смартфон или специальная флешка с биометрическим сенсором (например, YubiKey). Они позволяют отличить легитимного пользователя от программного бота, укравшего токен.

В Windows Hello, если вы не боитесь скармливать Windows свою биометрию, беспарольная аутентификация работает «из коробки», без дополнительных устройств. Замечу, впрочем, что YubiKey спокойно работает с Linux, а также со всеми видами виртуальных машин, с которыми я встречался (VirtualBox, VMware, Proxmox).

Варианты для выбора аутентификаторов
Варианты для выбора аутентификаторов

Обратная сторона платформозависимого аутентификатора, такого как Windows Hello, — невозможность быстрого входа в систему на другом железе, так как ключи хранятся только на конкретной машине. А токен я могу носить с собой и подключать на разных ПК.

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

QR-код при выборе другого смартфона
QR-код при выборе другого смартфона

В Google Chrome есть программный эмулятор WebAuthn — можно его создать и посмотреть, что в нем хранится. Это id «кредов», который мы скормим в аутентификатор, а также user name, алгоритм и публичный ключ. Даже если атакующие получат доступ к этим данным, это не поможет им аутентифицироваться.

Программный эмулятор WebAuthn в Google Chrome
Программный эмулятор WebAuthn в Google Chrome

Если у нас нет пароля, мы его не потеряем и он не будет скомпрометирован, поэтому благодаря WebAuthn часть атак, перечисленных в первой части этого материала, отваливается. 

Какие проблемы в списке OWASP закрывает беспарольная аутентификации WebAuthn

Посмотрим еще раз на список WSTG (Web Security Testing Guide) и на то, как WebAuthn справляется с проблемами, упомянутыми в нем.

Какие проблемы в списке WebAuthn закрывает WebAuthn
Какие проблемы в списке WebAuthn закрывает WebAuthn
  1. Передача паролей по незашифрованному каналу не работает, так как для функционирования WebAuthn нужен исключительно протокол HTTPS.

  2. Нет паролей, значит нет и дефолтных учетных записей. Конечно, можно выстрелить себе в ногу и для тестирования добавить обходной путь, а потом его забыть и «задеплоить».

  3. Слабый механизм блокировки тоже зачеркиваем. Нет смысла что-то блокировать, когда нечего брутфорсить. 

  4. Провести байпас (обход) беспарольной аутентификации можно, потому что WebAuthn — только для веба. Для мобильных приложений придется создавать некую другую «дверь» без магии с ключами.

  5. Нет пароля — значит не нужно его восстанавливать.

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

  7. Слабая парольная политика нас не беспокоит: паролей нет.

  8. Угроза эксплуатации секретных вопросов сохраняется: токен или ключ можно утратить. Может также пропасть или сломаться компьютер, где была создана учетная запись WebAuthn.

  9. При незащищенной процедуре смены пароля может возникнуть ситуация, аналогичная восьмому пункту. 

  10. Тут речь идет о каналах аутентификации, альтернативных вебу. WebAuthn заточен под веб и поэтому не особо применим к этому пункту.

  11. MFA-аутентификация сама по себе — достаточно защищенная технология, хотя и не полностью.

Теперь рассмотрим советы для пентестеров и веб-разработчиков OWASP Cheat Sheet. Напомню: выбранные четыре пункта относятся к веб-аутентификации и не дублируют рекомендации из OWASP WSTG. Насколько хорошо беспарольная аутентификации WebAuthn закрывает эти проблемы?

  1. OWASP советует рассмотреть возможность строгой аутентификации (в том числе использование двухфакторной аутентификации). Но если нет паролей, то нет проблем с их слабостью. Webauthn не подвержен этой проблеме.

  2. Эксперты рекомендуют включать повторную аутентификацию для конфиденциальных операций. Это помогает снизить вероятность реализации межсайтовой подделки запроса (Cross-site request forgery). Актуально ли это для WebAuthn? В общем случае, если пользователь авторизован в каком-то личном кабинете (например, банка) и нет защиты от CSRF, злоумышленник может сформировать страничку, заманить на нее пользователя и послать из его браузера запрос в личный кабинет от имени пользователя. Но если применяется WebAuthn, причем корректно, тогда для атаки потребуется совершить некоторые дополнительные действия от имени жертвы: воткнуть токен в USB или аутентифицироваться по отпечатку пальца. Для этого необходима социальная инженерия, что сильно затрудняет атаку.

  3. Автоматические атаки, иначе говоря брутфорс, не сработают: брутфорсить в WebAuthn нечего.

  4. Использование паролей в открытом виде (Plain Text) тоже отпадает, так как с публичным ключом в WebAuthn ничего нельзя сделать, механизм Webauthn защищен ассиметричным шифрованием.

Как можно заметить, WebAuthn решает многие, но не все проблемы защищенности аутентификации.

Почему WebAuthn не серебряная пуля

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

Кроме того, если злоумышленник получил доступ в базу, он может создать своего пользователя с нашим токеном и скопировать все данные, кроме username, а затем войти в административный аккаунт с этим токеном.

Как правило, самая большая проблема WebAuthn — в восстановлении токена, если доступ будет утрачен. Но есть обходной путь: дать пользователю создать несколько токенов для одной учетной записи. В этом случае, конечно, возникает проблема управления этими токенами в приложении, но она не такая сложная, как та, что возникает при потере единственного токена.

Хотите узнать больше? Полезные ссылки по теме WebAuthn:


Александр Чикайло

Старший специалист группы экспертизы защиты приложений Positive Technologies.

Комментарии (16)


  1. rak_track
    26.04.2024 08:01
    +5

    "В 1961 ... В то время пароли хранились в открытом виде на листочке. "

    2024 год - пароли хранятся в открытом виде на листочке.


    1. KEugene
      26.04.2024 08:01
      +1

      Чем сложнее пароль, тем выше вероятность оказаться на листочке.


  1. srzybnev
    26.04.2024 08:01

    Могли упомянуть magic link. Но давайте объективно, логины и пароли до сих пор нормально использовать. Заходить каждый раз в почту менее удобно, чем вставлять креды из парольного менеджера. Да и magic link менее безопасный способ. Потому что при компрометации почты аккаунт 100% смогут захватить. Если говорить про вход только с помощью OTP, то потеря девайса = потере доступа к аккаунту. А включать восстановление по почте будет очередным костылём


    1. xSVPx
      26.04.2024 08:01

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


    1. ptsecurity Автор
      26.04.2024 08:01
      +2

      Про Magic link есть в статье.


    1. Kenya-West
      26.04.2024 08:01

      Если говорить про вход только с помощью OTP, то потеря девайса = потере доступа к аккаунту

      Не всегда. Даже скорее наоборот, если мы говорим про TOTP. Многие вендорные приложения-аутентификаторы (Google, Microsoft) умеют бекапить в облако, а Authy и Ente Auth апрори облачные, последний ещё и бекапиться умеет в открытые форматы. Пользуюсь именно последним. Так что потеря устройства не сильно большая проблема нынче.

      А включать восстановление по почте будет очередным костылём

      Тоже так считаю. Поэтому считаю лучшей компромиссной реализацией следующую:

      • Вход по логину и паролю с запоминанием устройства (чтобы не выходило требование про второй фактор), они будут записаны в KeePass (его база в облаке, а файл-ключ только оффлайн в зашифрованном диске, копия на флешке судного дня);

      • TOTP записан в Ente Auth;

      • Восстановление только по резервным кодам, которые записаны в сервисе хранения секретов. Я, правда, не придумал ничего лучше, как поднять Ansible Vault на VPS'ке для шифровки одного-единственного файла. Так и смотрю коды по SSH, благо требуется это очень редко.

        Есть способы много проще, есть много безопаснее, а этот мой пайплайн где‑то посередине.

        Плюсы: кросс-платформа, яйца лежат в разных корзинах

        Минусы: нет защиты от раскаленного паяльника в жопе. Да я уже и на этапе бутылки всё выдам под чистýю...


  1. Sindiano
    26.04.2024 08:01

    Далее в таблице можно посмотреть, какие браузеры поддерживают WebAuthn. Красный цвет — отсутствие поддержки, зеленый — полная совместимость, а горчичный — частичная поддержка.

    Сколько ни смотрел - не увидел в таблице этих цветов


    1. ptsecurity Автор
      26.04.2024 08:01

      Спасибо за замечание, вы правы. Заменили картинку.


  1. inkelyad
    26.04.2024 08:01
    +2

    А еще где-то по дороге к дню сегодняшнему (и в статье) потерялись клиентские X.509 TLS/https сертификаты. Которое, в общем, тоже 'без паролей'. И которые с минимальной доработкой браузеров можно было бы заставить работать приблизительно по той же схеме, что в WebAuthn применяется.

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


    1. ThingCrimson
      26.04.2024 08:01

      Клиентские сертификаты это было бы очень здорово! Но — дорого (если нужна валидация стандартными CA), или хлопотно / небезопасно (если использовать самоподписную CA).


      1. inkelyad
        26.04.2024 08:01
        +1

        если нужна валидация стандартными CA

        Не нужна. Т.к. пользы от этого конкретному сайту - довольно мало.

        или хлопотно / небезопасно (если использовать самоподписную CA).

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

        If the validation process succeeded, the server would then store the publicKeyBytes and credentialId in a database, associated with the user.

        Точно так же можно было сделать и с X.509 сертификатами. Хочешь сделать учетку - браузер делает Certificate Request, сайт его подписывает, отдает сертификат браузеру, браузер складывает его в локальное хранилище и в следующий раз этот сертификат можно предъявить для захода в учетку.


        1. ThingCrimson
          26.04.2024 08:01

          Насколько я знаю, в WebAuthn не нужно прописывать свою CA в списки доверенных на каждом клиентском устройстве. А с самоподписанными клиентскими сертификатами — нужно. Что и хлопотно (если только это не организация казарменного типа, где используются только выданные в пользование устройства, с групповыми политиками и т.п., а всякая вольность типа личного планшета недопустима), и небезопасно (сторожевые системы современных ОС очень возбуждаются на самподподписные CA в списке доверенных; а если заткнуть им рот, то есть шанс пропустить чужую CA — и здравствуй, MiTM).


          1. inkelyad
            26.04.2024 08:01
            +1

            Ну так на доверенность CA, подписавшего клиентский сертификата на стороне клиента можно более-менее не обращать внимание. Пускай сервер разбирается, верит он предъявляемому или нет. Клиенту важно, чтобы серверный сертификат был тот (т.е вот все то, что сейчас в стандартном соединении https делается).

            И вносить в глобальный системный список 'доверяем для всех подряд целей' все эти серверные само подписанные CA тоже совершенно не обязательно.

            Нужно только браузер доработать (А для WebAuthn его еще как доработали), чтобы описанный сценарий срабатывал как надо и тупо показывать "Сертификат XYZ, пописан тем сайтом, на котором вы сейчас находитесь для учетки ABCD, предъявить для авторизации?"


            1. ThingCrimson
              26.04.2024 08:01

              Вот! Когда (если) такое будет, и браузеру будет достаточно положить в какое-то своё локальнрое хранилище сертификат, и chain of trust до самых верхних корневых CA будет не важна — тогда это будет хорошее, надёжное и прозрачное для пользователя решение.


              1. inkelyad
                26.04.2024 08:01

                Вот! Когда (если) такое будет

                ...

                тогда это будет хорошее, надёжное и прозрачное для пользователя решение.

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


  1. iliya2004
    26.04.2024 08:01
    +2

    Серьёзная проблема регистрации только по webauthn. Одно устройство - один аккаунт. На компьютере windows hello, на андроиде подтверждение от сканера отпечатка пальца, на айфоне face id. Представляете создавать и иметь новый аккаунт в телеграмме при переходе на другое устройство?

    Всё ещё невозможно использовать биометрию для авторизации. Все сканеры отпечатков пальцев отдают не чистую биометрию, а токен результат сравнения заранее зарегистрированного пальца и отсканированного. У face id скорее всего тоже так. Только когда получится хранить в базе данных биометрию (конечно, в максимально безопасном формате) и сравнивать её с восходящей от пользователя, тогда это будет настоящая замена пароля и появится возможность входить на разных устройствах.

    Да, можно использовать физические ключи, но этим не лень заниматься 5% пользователей.