• [ Регистрация ]Открытая и бесплатная
  • Tg admin@ALPHV_Admin (обязательно подтверждение в ЛС форума)

Статья Разбираемся со стандартами и будущим беспарольной аутентификации

stihl

Moderator
Регистрация
09.02.2012
Сообщения
1,179
Розыгрыши
0
Реакции
510
Deposit
0.228 BTC
stihl не предоставил(а) никакой дополнительной информации.
В этой статье мы с тобой проследим историю идей беспарольной аутентификации. Разберемся в том, что такое FIDO2, как работают протоколы WebAuthn и CTAP, а также обсудим их внутренние механизмы защиты и существующие атаки. Между делом раскроем заговор массовой утечки биометрических данных, посмотрим, при чем здесь Passkeys, и попытаемся понять, насколько близко беспарольное будущее.

Идея отказаться от паролей — чуть ли не ровесница самих паролей. Однако первые серьезные обсуждения этой темы начались примерно в 2004 году, когда Билл Гейтс на конференции по безопасности RSA Для просмотра ссылки Войди или Зарегистрируйся: «Нет никаких сомнений, что со временем люди будут полагаться на пароли все меньше и меньше. ...[пароли] просто не отвечают задаче защитить что‑либо действительно ценное». Затем был дружный хор голосов из IBM, Google и прочих компаний, проповедующих скорую кончину паролей. Но с того выступления Гейтса прошло уже двадцать лет, а воз и ныне там — пароли по‑прежнему живы.

Перед тем как мы двинемся дальше, освежим несколько базовых понятий:


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

  • Люди часто не следуют рекомендациям безопасности: используют снова и снова один и тот же пароль или делают пароли слишком легкими для перебора. По данным Для просмотра ссылки Войди или Зарегистрируйся за 2022 год, каждый пользователь имеет в среднем четыре готовых пароля, причем у каждого третьего это вариации одного и того же пароля.
  • Пароли должны безопасно храниться, как на стороне пользователя, так и на стороне сервисов. По Для просмотра ссылки Войди или Зарегистрируйся LastPass, современный пользователь имеет в среднем 191 учетную запись, что намекает на потребность в Для просмотра ссылки Войди или Зарегистрируйся, но люди используют бумажки и таблицы. С компаниями не лучше — вспомнить хотя бы историю о том, как Для просмотра ссылки Войди или Зарегистрируйся.
  • Поскольку пароли стали стандартным средством аутентификации, у злоумышленников уже накопился опыт и методы их подбора (словари, правила, утилиты), которыми может воспользоваться даже скрипт‑кидди. А добавив сюда возможности социальной инженерии, злоумышленники получают просто огромную поверхность атаки. По данным Для просмотра ссылки Войди или Зарегистрируйся Для просмотра ссылки Войди или Зарегистрируйся, от 80 до 90% всех атак включают использование скомпрометированных учетных данных.
Да и вообще, что говорить, когда Фернандо Корбато, впервые реализовавший механизм паролей в 1961 году, Для просмотра ссылки Войди или Зарегистрируйся, что он не предназначался для веба и на текущий день превратился в кошмар.


Беспарольная эволюция​

С паролями все ясно, возможно, они действительно стали больше риском, чем защитой, но что предлагается взамен?

Все началось в 1980-х, когда компания Security Dynamics Technologies (сейчас RSA Security) создала первый аппаратный токен, генерирующий одноразовые пароли (OTP). В 1998 году компания AT&T получила Для просмотра ссылки Войди или Зарегистрируйся на двухфакторную аутентификацию, совместив пароль с OTP-кодом. В 2000-х получила распространение система SSO. В 2011 году в Motorola выпустили первый смартфон со сканером отпечатка пальцев, а еще через два года то же сделали и в Apple, снабдив iPhone датчиком Touch ID.

Для просмотра ссылки Войди или Зарегистрируйся
Таким образом, эволюция аутентификации создала всего три фактора: факторы знания (что‑то, что ты знаешь), факторы владения (что‑то, что ты имеешь) и факторы свойства (что‑то, что характеризует тебя). Поэтому фундаментально у нас есть следующие альтернативы:

  • минимизировать недостатки парольной аутентификации (SSO, OAuth, OpenID);
  • комбинировать факторы знания с другими факторами (2FA, MFA);
  • не использовать факторы знания (беспарольная аутентификация).
Если наша задача — отказаться от паролей, то подходит только последний вариант. Будем исходить из того, что беспарольная аутентификация (БА) — это аутентификация, которая не использует фактор знания (пароль, секретный вопрос, пасс‑фраза). То есть нам остается выбор одного из двух факторов. Тем временем многофакторная аутентификация (MFA) предполагает использование двух и более различных факторов. Так что БА и MFA — это разные вещи, которые не следует путать.

Развею самое большое заблуждение о БА. Любое использование биометрии — это локальное решение производителя аутентификатора, но даже в этом случае никто никуда твои отпечатки или их производные не посылает и ничего ими не подписывает, это касается и FIDO2, о котором пойдет речь ниже. Многие путают использование биометрии и БА, что порождает массовую истерию по поводу утечки биометрических данных.


Зоопарк FIDO​

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

С 2004 года были образованы OATH, OIDF, OASIS, IDSA, OIX и другие. Количество организаций и протоколов росло, компании пробовали создавать продукты, но ни к какому общему решению не пришли. Поэтому в июле 2012 года PayPal, Lenovo и еще четыре компании основали альянс FIDO (Fast IDentity Online), Для просмотра ссылки Войди или Зарегистрируйся которого стало «сократить всеобщую зависимость от паролей». Вопреки расхожему мнению, Google и Microsoft не были среди основателей, а присоединились только в 2013 году. Сейчас в альянс FIDO входит несколько сотен компаний.

На первых порах новоиспеченный альянс объединил два независимых проекта. Во‑первых, это Universal Authentication Framework (UAF), разработанный в PayPal и Validity Sensors, — протокол, который предполагает использование биометрических данных для аутентификации пользователя без пароля на стороне мобильных устройств. Во‑вторых, это Universal Second Factor (U2F), созданный в Google и Yubico. Этот протокол предполагает использование внешнего токена безопасности как второго фактора аутентификации, в дополнение к паролю. В результате появились две спецификации: UAF 1.0 (8 декабря 2014 года) и U2F 1.0 (9 октября 2014 года), которые можно условно назвать проектом FIDO 1.0.

Концепт выглядел отлично, но ему не хватало унификации, поэтому в сентябре 2015 года альянс FIDO объединил две спецификации и выпустил предложение FIDO 2.0, которое было отправлено в W3C. На этой основе в W3C в мае 2016 года выпустили протокол WebAuthn, а альянс FIDO после нескольких доработок в июле 2017 года зарелизил протокол U2F 1.2 (он же CTAP 1.0). Эту связку уже можно назвать полноценным проектом FIDO 2.0.

info​

W3C (World Wide Web Consortium) — это международная организация по стандартизации веба. Есть и другие подобные организации, например WHATWG (поддерживает HTML) и ECMA (поддерживает JavaScript). Стандарты, выпущенные этими организациями, не обязательные, но общепризнанные.
W3C и FIDO регулярно выпускают новые итерации своих спецификаций. Так, на сегодняшний день стандартом является Для просмотра ссылки Войди или Зарегистрируйся от 2021 года и Для просмотра ссылки Войди или Зарегистрируйся от 2022 года, но существует и новая версия, которая пока на этапе предложения.

Для просмотра ссылки Войди или Зарегистрируйся
На сегодняшний день FIDO2 — это наиболее распространенное решение альянса FIDO, хотя U2F также еще используется некоторыми веб‑сервисами как метод 2FA, а UAF применяется в мобильных приложениях как метод подтверждения действия, например транзакции в банковском приложении.

Итого нужно запомнить, что FIDO — это альянс, FIDO1 и FIDO2 — это проекты, а не протоколы; UAF, U2F, CTAP и WebAuthn всех версий — это протоколы, у которых есть одноименные спецификации.


Архитектура FIDO2​

FIDO2 позиционируется как безопасный метод аутентификации, построенный на криптографии публичного ключа, и состоит из двух частей — протоколов WebAuthn и CTAP. Зачем два протокола? Так FIDO было легче формализовать свое творение: W3C выпускает только стандарты для веба, а на стороне устройств ничего не решает. Поэтому и получился такой полустандартный стандарт, за который отвечают одновременно некоммерческий консорциум (W3C) и ассоциация коммерческих организаций (альянс FIDO).

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

Также FIDO2 не покрывает Passkeys, которые сейчас начинают предлагать на некоторых крупных сайтах. Дело в том, что в первых спецификациях FIDO2 такого понятия не существовало, а позже словом Passkeys для удобства начали называть те самые криптографические ключи. На практике Passkeys — это одна из реализаций ключа на основе криптографии, которая может использоваться в FIDO2 и обладает другими полезными функциями, например синхронизацией между устройствами. Но стоит помнить, что ни WebAuthn, ни CTAP не регламентируют Passkeys. Это в данный момент просто самое распространенное решение.

Основные участники взаимодействия — это:

  • пользователь;
  • аутентификатор (Authenticator);
  • устройство пользователя;
  • JS-клиент устройства пользователя (клиент);
  • ответственная сторона (Relying Party — RP).
Протокол WebAuthn отвечает за взаимодействие между JS-клиентом и RP, его можно условно назвать клиентским API. В большинстве случаев JS-клиент — это браузер пользователя, но он может быть и нативным приложением для Android или iOS. Для простоты будем считать понятия JS-клиент и браузер, а также веб‑сайт и RP равнозначными.

Протокол CTAP регулирует отношения между аутентификатором и устройством пользователя, его можно условно назвать API аутентификатора. Аутентификатор может быть встроенным, например Face ID, или внешним, например аппаратный токен YubiKey, но мы не будем делать между ними различий.

Данные CTAP может передавать через USB, NFC или BLE (Bluetooth Low Energy). Самые внимательные наверняка заметят, что у нас остался пробел во взаимодействии между устройством пользователя и JS-клиентом. К сожалению, каждая платформа (ОС) решает этот вопрос по‑своему, здесь четких стандартов нет.

Концептуально архитектура FIDO2 приведена на рисунке ниже, а компоненты разных цветов зависят от разных команд или даже вендоров.

Для просмотра ссылки Войди или Зарегистрируйся

Церемония регистрации​

Нет‑нет, речь сейчас пойдет не о загсе. В FIDO2 существует две церемонии: церемония регистрации и церемония аутентификации. Давай начнем с первой. Сразу оговоримся, что для читаемости я буду использовать знакомые всем форматы данных вместо байтовых (Uint8Arrays), которые на самом деле отправляются в полях вызовов.

Для начала пользователь должен войти на сайт, найти форму регистрации, ввести свой логин и нажать кнопку регистрации. Дальше RP формирует запрос PublicKeyCredentialCreationOptions к браузеру. Этот массив содержит:

  • Данные RP, где rp.id — это домен, в рамках которого будут действовать будущие ключи, а name — название ресурса в читабельном для человека виде.
  • Данные пользователя, где user.id — это уникальный идентификатор пользователя в системе RP, user.displayName — неуникальное имя пользователя на платформе (ник), а user.name — это уже уникальный логин пользователя.
  • Задача (сhallenge) — это уникальное произвольное значение не меньше 16 байт. При регистрации задачу не подписывают, она служит для защиты целостности данных.
  • Требования к ключам (pubKeyCredParams), которые должен создать аутентификатор. Здесь в порядке убывания приводятся предпочтительные алгоритмы. Например, -7 означает ES256, а полный список от IANA можно посмотреть в Для просмотра ссылки Войди или Зарегистрируйся.
  • Требования к аутентификатору (authenticatorSelection), так же как и требования к аттестации (attestation), обычно устанавливаются только в случае, если у веб‑сервиса есть какие‑то требования от регулятора, например если это правительственный или банковский ресурс. В остальном здесь все более‑менее стандартно. Например, аттестация в 99% случаев будет иметь значение none, то есть «не требуется».

Аттестация​

Аттестация — это дополнительная процедура безопасности. Ее основная цель в том, чтобы установить модель аутентификатора. Ответственной стороне это необходимо для выполнения требований к безопасности, установленных регулятором.
Если аттестация требуется, то сгенерированный публичный ключ будет подписан аттестационным приватным ключом. Аттестационный приватный ключ создается на аутентификаторе у производителя и уникален для каждой модели устройства, произведенной в заданные временные рамки: например, все YubiKey 5, произведенные с сентября по декабрь 2022 года, будут иметь одинаковый ключ. Следом подписанный публичный ключ и аттестационный сертификат отправляются к RP.
RP может проверить аттестацию, а может и нет! Для установления доверия RP проверяет цепочку сертификата от подписи производителя до корневого сертификата GlobalSign. При этом для определения возможностей аутентификатора ответственной стороне необходимо загрузить и ежемесячно обновлять базу Для просмотра ссылки Войди или Зарегистрируйся, которая содержит данные о каждой модели аутентификатора.
Код:
PublicKeyCredentialCreationOptions
{
  "rp": {
      "id": "subdomain.domain.com",
      "name": "Company Name"
    },
  "user": {
      "name": "i.ivanov@mail.ru",
      "displayName": "Ivan Ivanov",
      "id": "123e4567-e89b-12d3-a456-426655440000"
    },
  "challenge": "yGvVFCug1QLmaW4OnIYw7JONQP7XDSDNZ3SELT0PBhI",
  "pubKeyCredParams": [
    {
      "alg": -7,
      "type": "public-key"
    },
    {
      "alg": -257,
      "type": "public-key"
    }
  ],
  "authenticatorSelection": {
      "authenticatorAttachment": "platform",
      "residentKey": "required"
      "requireResidentKey": true,
      "userVerification": "discouraged"
  },
  "attestation": "none",
  "timeout": 30000,
  "excludeCredentials": [],
  "extentions": []
}

После получения запроса браузер вызывает функцию navigator.credentials.create(), в которой проверяет, что значение rp.id совпадает с именем домена, а также хеширует данные запроса. На этом моменте WebAuthn заканчивается, а ОС вызывает authenticatorMakeCredential у аутентификатора через CTAP-протокол. В целом большинство значений этого массива тебе должно уже быть знакомо, укажем только на clientDataHash, который является упомянутым SHA-256-хешем данных запроса, и options, которые содержат требования по процедурам наличия пользователя (UP) и верификации пользователя (UV) в числе прочих.

Наличие и верификация пользователя​

Обе церемонии (регистрации и аутентификации) требуют одну или обе процедуры — наличие пользователя (UP) и верификацию пользователя (UV). UP — это обязательная базовая процедура, которая заключается во взаимодействии пользователя с аутентификатором. Например, нужно нажать на кнопку. UV — это более сложная, но и опциональная процедура, когда аутентификатор убеждается, что пользователь авторизован его использовать. Например, может быть нужно ввести пин или предоставить биометрию.
Спецификации WebAuthn и CTAP не определяют эти процедуры строго, говоря о некоем «авторизационном жесте», который каждый производитель может понять по‑своему. Для FIDO2 разница в том, что UV позволяет отличить разных пользователей одного аутентификатора, а UP — нет.
Код:
authenticatorMakeCredential
{
  "clientDataHash": "LNeTz6C...oYH2el7Mz1NsKQQF3Zq9ruMdVE",
  "rp": {
      "id": "subdomain.domain.com",
      "name": "Company Name"
    },
  "user": {
      "name": "i.ivanov@mail.ru",
      "displayName": "Ivan Ivanov",
      "id": "123e4567-e89b-12d3-a456-426655440000"
    },
  "pubKeyCredParams": [
    {
      "alg": -7,
      "type": "public-key"
    },
    {
      "alg": -257,
      "type": "public-key"
    }
  ],
  "excludeCredentials": [],
  "extentions": [],
  "options": {
      "rk": true,
      "up": true,
      "uv": false
    }
}
После получения запроса аутентификатор создает пару ключей и производит другие действия, всего в алгоритме 19 шагов. В результате аутентификатор возвращает операционной системе по CTAP объект AuthenticatorAttestationResponse. ОС передает его скучающей функции navigator.credentials.create(), которая формирует PublicKeyCredential и заканчивает свой цикл.

Возвращаемый аутентификатором AuthenticatorAttestationResponse часто называют просто Attestation, поэтому иногда можно услышать, что весь процесс регистрации тоже носит название Attestation (аттестация), но это скорее обиходное название, которое не следует путать с процессом установления модели аутентификатора описанным выше. Форматы AuthenticatorAttestationResponse и PublicKeyCredential практически идентичны, поэтому рассмотрим только последний:

  • Уникальный параметр id представляет собой идентификатор созданного ключа.
  • Интерес представляет массив response, который содержит clientDataJSON — это как раз те самые данные SHA-256, хеш которых отправлялся аутентификатору, и attestationObject, где в большинстве случаев fmt будет равно none, так как аттестация не требуется, а attStmt будет в таком случае пустым.
  • Внутри attestationObject находится и самый важный для нас массив authData. Здесь в rpIdHash скрывается хеш SHA-256 уже известного нам rp.id, который определяет область действия ключа. Также видим объект attestedCredentialData, который содержит идентификатор аутентификатора (aaguid), идентификатор созданного ключа (credentialId) и сам публичный ключ (credentialPublicKey).
  • Важно обратить внимание на параметр signCount, который увеличивается с каждым успешным подписанием задачи при аутентификации. О нем мы еще вспомним, когда будем рассматривать одну из атак на протокол.
Код:
PublicKeyCredential
{
  "id": "AV19-ikcu3tKuMxfFnRZ9gU6tnDH6QqzYwUg",
  "response": {
      "clientDataJSON": "ew0KCSJ0eXBl...A0KCSJjaGFsbGVuZ2UiIDogInlHdl",
      "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdX...jLvw6oUiKGB"
          "authData": "LNeTz6C0...hSIoYH2el7Mz1NsKQQF3Zq9ruMdV"
    },
      "transports": {
          "internal"
        },
  },
  "clientExtensionResults": {
      "credProps": {
          "rk": true
        }
    }
}

Компоненты массива в деталях:

Код:
"clientDataJSON": {
    "challenge": "qNqrdXUrk5S7dCM1MAYH3qSVDXznb-6prQoGqiACR10",
    "origin": "https://subdomain.domain.com",
    "type": "webauthn.create",
    "crossOrigin": false,
    "tokenBinding": {
        "status": "unsupported"
      }
}

"attestationObject": {
    "fmt": "none",
    "attStmt": [],
    "authData": "LNeTz6C0...hSIoYH2el7Mz1NsKQQF3Zq9ruMdV"
}

"authData": {
    "rpIdHash": "LNeTz6C0GMu_DqhSIoYH2el7Mz1NsKQQF3Zq9ruMdVE",
    "flags": {
        "up": true,
        "uv": false,
        "at": true,
        "ed": false
    },
    "signCount": 0,
    "attestedCredentialData": {
        "aaguid": "YCiwF7HUTAK0s6_Nr8lrsg",
        "credentialId": "AV19-ikcu3tKuMxfFnRZ9gU6tnDH6QqzYwUg",
        "credentialPublicKey": "pAEDAzkWZFf4weLZ...kjWm6vNvT-JWMqe39MBAAE"
  }
}
На финальном этапе браузер отправляет PublicKeyCredential к RP. RP производит верификацию полученных данных, например проверяет, соответствуют ли полученные ключи и алгоритмы заявленным требованиям, проводит аттестацию. Всего спецификация WebAuthn предполагает алгоритм из 19 шагов. В случае успеха RP сохраняет credentialID и публичный ключ с метаданными у себя в базе. Далее пользователь чаще всего перенаправляется на страницу логина, чтобы войти.

Для просмотра ссылки Войди или Зарегистрируйся

Церемония аутентификации​

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

Conditional UI​

Conditional UI (он же Passkeys autofill) — это возможность автозаполнения. Это не часть WebAuthn, а дополнительная разработка, которую RP может внедрить на фронте для удобства пользования.
Conditional UI работает только для аутентификации и поддерживается большинством браузеров или встроенными вызовами ОС для нативных приложений. Conditional UI работает только с обнаруживаемыми ключами (см. ниже), а также может вступать в конфликт с возможностями автозаполнения менеджеров паролей. При этом он не требует установки плагинов на стороне пользователя.
RP формирует запрос PublicKeyCredentialRequestOptions к браузеру, который содержит:

  • Параметр challenge. Стоит отдельно подчеркнуть, что WebAuthn не описывает, как это значение должно выглядеть и каким алгоритмом создаваться.
  • Параметр rpId определяет область доверия, в рамках которой действует ключ. Если веб‑ресурс укажет его неправильно, то аутентификатор не найдет ключа и мы никуда не попадем.
  • Самый интересный параметр — это allowCredentials. Здесь RP указывает идентификаторы ключей, которые уже зарегистрированы для данного логина. Такое решение в теории помогает избавить пользователя от выбора ключа или регистрации нового аутентификатора, если он забыл, на каком именно хранится ключ. Но с точки зрения безопасности выглядит как прекрасная возможность для атаки подбора пользователей. Это поле необязательно для обнаруживаемых ключей, но для необнаруживаемых ключей его все‑таки придется заполнить.

Обнаруживаемые и необнаруживаемые ключи​

Существует два типа ключей — обнаруживаемые (discoverable или resident) и необнаруживаемые (non-discoverable или non-resident). Они различаются по месту хранения и способу запроса. В FIDO2 по умолчанию создаются обнаруживаемые ключи.
Обнаруживаемые ключи хранятся на аутентификаторе, а при логине аутентификатор предлагает пользователю выбрать, какой из ключей для домена (rp.id) использовать.
Необнаруживаемые ключи не хранятся на аутентификаторе, а создаются как производное от мастер‑ключа аутентификатора и сид‑значения. При логине RP отправляет аутентификатору идентификатор ключа и сид‑значение, а аутентификатор воссоздает ключ и подписывает задачу. Так как ключ доступен в памяти аутентификатора только определенное время, его еще называют эфемерным, а сам аутентификатор не знает, что ключ существует, если ему не сказать об этом.
Код:
PublicKeyCredentialRequestOptions
{
  "publicKeyCredentialRequestOptions": {
      "challenge": "kYhXBWX0HO5GstIS02yPJVhiZ0jZLH7PpC4tzJI-ZcA=",
      "timeout": 30000,
      "rpId": "subdomain.domain.com",
      "userVerification": "discouraged",
      "allowCredentials": [
          {
            "id": "X9FrwMfmzj...",
            "type": "public-key"
          }
      ],
      "extensions": []
  }
}
Далее браузер вызывает функцию navigator.credentials.get(), в которой проверяет, что значение rp.id совпадает с доменом взаимодействия, а также хеширует данные запроса. На этом моменте WebAuthn опять заканчивается, а ОС вызывает функцию authenticatorGetAssertion аутентификатора через протокол CTAP.

Получив запрос, аутентификатор находит у себя приватный ключ и выполняет другие действия, включая взаимодействие с пользователем. Весь алгоритм предполагает 13 шагов. В результате аутентификатор по CTAP возвращает операционной системе объект AuthenticatorAssertionResponse, который та передает в navigator.credentials.get(). Эта функция формирует PublicKeyCredential и заканчивает свой цикл.

Возвращаемый аутентификатором AuthenticatorAssertionResponse часто называют просто Assertion, поэтому иногда можно услышать, что весь процесс аутентификации тоже носит название Assertion (подтверждение) — по аналогии с тем, как регистрацию часто называют аттестацией.

Для наглядности давай посмотрим на разницу в отправляемых данных массива PublicKeyCredential при регистрации и аутентификации.

  • Обрати внимание на параметр signCount, который увеличился на единицу по сравнению с отправляемым во время регистрации, так как произошло успешное подписание задачи.
  • Параметр signature как раз представляет собой задачу, подписанную приватным ключом. По сути, это и есть подтверждение, доказывающее, что пользователь владеет приватным ключом, который соотносится с хранящимся у RP публичным.
  • Параметр userHandle для нас по форме новый, но по содержанию это уникальный идентификатор пользователя у ответственной стороны. То есть ему присваивается известное нам значение user.id.
Код:
PublicKeyCredential
{
  "id": "X9FrwMfmzj...",
  "response": {
      "authenticatorData": {
          "authData": {
            "rpIdHash": "LNeTz6C0GMu_DqhSIoYH2el7Mz1NsKQQF3Zq9ruMdVE",
            "flags": {
                "up": true,
                "uv": false,
                "at": false,
                "ed": false
              },
            "signCount": 1,
        },
      "clientDataJSON": {
          "challenge": "kYhXBWX0HO5GstIS02yPJVhiZ0jZLH7PpC4tzJI-ZcA",
          "origin": "https://subdomain.domain.com",
          "type": "webauthn.get"
        },
      "signature": "MEUCIQDNrG...HD3UWA",
      "userHandle": "123e4567-e89b-12d3-a456-426655440000"
    },
  "clientExtensionResults": []
}
На финальном этапе браузер отправляет PublicKeyCredential ответственной стороне. Она верифицирует полученные данные, например проверяет, совпадает ли challenge. Весь алгоритм проверки в спецификации WebAuthn — это 23 шага. В случае успеха RP отправляет пользователю сессионный cookie.

Для просмотра ссылки Войди или Зарегистрируйся

Атаки на FIDO2​

FIDO2 предполагает защиту не только от слабых паролей, но и от фишинговых и MitM-атак, а также повышенную приватность данных пользователя. Более того, даже если хакеры взломают сервер компании, пользователи не будут скомпрометированы. Давай разберемся со всеми этими утверждениями по очереди.

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

Во‑вторых, фишинг. Здесь тоже согласимся с разработчиками стандарта: мы помним, что при регистрации RP обменивается с браузером значением rp.id, к которому привязывается приватный ключ. Поэтому, даже если ты войдешь не в ту дверь, аутентификатор ничего не подпишет. Но ничего принципиально нового здесь нет, любой менеджер паролей обладает такой функцией.

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

Кто‑то обязательно скажет, что аутентификатор показывает пользователю уведомление о том, на какой ресурс он заходит. Однако Тарун Кумар Ядав отметил в своем исследовании (Для просмотра ссылки Войди или Зарегистрируйся), что только один из двадцати пользователей проверяет доменное имя в поп‑апе, а двойное нажатие на аутентификатор никто не считает зловредным.

Еще одна интересная атака — это клонирование аутентификатора. Сейчас это сложная задача, но не невыполнимая. Так, в 2024 году специалистам NinjaLab удалось успешно Для просмотра ссылки Войди или Зарегистрируйся аппаратные ключи YubiKey 5.

У FIDO2 есть защита от подобных типов атак — тот самый signCount, который при несовпадении на стороне аутентификатора и RP не позволит успешно завершить вход. Но этот механизм защиты легко обходится. Дело в том, что аутентификатор увеличивает signCount после каждой успешной подписи задачи, а RP — после каждой успешной аутентификации, то есть, по сути, обе стороны действуют независимо.

Предположим, что злоумышленник скопировал твой аппаратный токен, когда signCount равен 200, обозначим это как A = 200, L = 200 от слов Assertion на стороне аутентификатора и Login на стороне RP. Ход атаки продемонстрирован в таблице ниже. Злоумышленник успешно входит на ресурс, при этом A увеличивается только у него, а L — у всех участников.

Когда пользователь попробует залогиниться, получит ошибку, так как A и L совпадать не будут, но аутентификатор пользователя успешно подпишет задачу и увеличит signCount, а RP не осуществит успешного логина и оставит значение signCount неизменным. Соответственно, оба значения сравняются и при второй попытке логина пользователь успешно зайдет в аккаунт. К сожалению, сайты показывают только общее сообщение об ошибке, часто прося пользователя повторить вход, когда ошибки уже не возникнет.

ЭтапЗлоумышленникЖертва
1. Изначальное значениеA = 200, L = 200A = 200, L = 200
2. Злоумышленник вошелA = 201, L = 201A = 200, L = 201
3. Жертва пытается войтиA = 201, L = 201Ошибка, так как A != L
4. Жертва пытается войти сноваA = 201, L = 201A = 201, L = 201
Можно еще вспомнить простую атаку с кражей сессии (session hijacking). Даже после супер‑пупер‑защищенной аутентификации мы остаемся наедине с протоколом HTTP, который не хранит состояния и опирается на cookie-файлы. Поэтому, если сайт подвержен, например, XSS, можно полностью завладеть сессией пользователя. Да и MitM-атаки никак не предотвращаются.

FIDO2 опирается на TLS-соединение, при этом MitM с началом применения TLS никуда не пропали. Так что не стоит надеяться на отсутствие проблем и в данном случае.

Говорить о случаях, когда корневой сертификат находится у твоей организации или у государственного агентства, я думаю, даже не стоит. Ситуацию могла бы спасти технология Token Binding (Для просмотра ссылки Войди или Зарегистрируйся), которая привязывает TLS-соединение к браузеру пользователя, но, к сожалению, в FIDO2 она необязательна, а браузеры ее практически не поддерживают.

Как видим, у FIDO2 есть внутренние уязвимости протоколов и он не дает защиту от многих атак. Например, в исследовании Михала Кепковски Для просмотра ссылки Войди или Зарегистрируйся пример удаленной атаки по времени для определения ключей, имеющихся на аутентификаторе. Исследователь также указывает и на то, что процедура UP легко симулируется, а, поскольку большинство ответственных сторон не требуют UV, это создает еще один вектор обхода механизмов защиты FIDO2.

Тарун Кумар Ядав также указывает, что 47% браузерных расширений из Chrome Web Store могут осуществить как минимум пять специфичных для FIDO2 атак, хотя действительно вредоносных расширений, нацеленных на такие атаки, найдено не было.

Отмечу также, что вопрос приватности FIDO2 остается открытым — пользователь по‑прежнему оставляет на стороне RP тонну личных данных, да и профилирование стандартными методами никуда не делось.


Выводы​

Среди очевидных плюсов FIDO2 — защита от двух самых распространенных кибератак: фишинга и подбора паролей. Это, безусловно, воодушевляет, однако не стоит забывать, что совместное использование тех же самых менеджеров паролей и 2FA дает практически такой же эффект.

Конечно, БА выглядит проще и удобнее — от пользователя не требуется что‑то вводить или придумывать, все, за исключением нескольких нажатий, происходит автоматически. Также на стороне FIDO2 тот факт, что эта технология Для просмотра ссылки Войди или Зарегистрируйся всеми основными браузерами и ОС.

Пусть беспарольная аутентификация — это круто, но большинство веб‑ресурсов ее все‑таки не вводят. Компании не видят смысла, потому что, во‑первых, сейчас и так все прекрасно работает с паролями, во‑вторых, пользователи привыкли к паролям, а в‑третьих, БА — это новый процесс, и придется его согласовывать, выбирать софт и платить разработчикам. То есть БА для бизнеса — это долго, дорого и неинтересно.

Более того, FIDO2 — это только протоколы, а от ответственной стороны зависит их реализация, правильная настройка требований к аутентификаторам, поддержка механизмов восстановления доступа и хранения данных. Это накладывает на бизнес дополнительную ответственность и создает новые риски. Возможно, именно из‑за этого БА пока держится на голом энтузиазме отдельных компаний, а серьезные сдвиги могут произойти только после вмешательства регуляторов.

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

Для примера можно вспомнить, как относятся к КЭП генерального директора в небольших компаниях: аппаратный токен с ней гуляет по всему офису и каждый сотрудник подписывает и принимает документы подписью генерального директора.

Пароль легко передать доверенному лицу, и все умеют это делать. С БА появятся новые способы делиться доступом, но, чтобы они работали, нужна совместимость между устройствами. Да и сами пользователи должны знать о том, как работает эта функция, и уметь ей пользоваться.

С самим FIDO2 тоже не все так гладко. В протоколах CTAP и WebAuthn есть внутренние уязвимости и слабые механизмы защиты, а между ними — прослойка в виде ОС, которая делает нас зависимыми от третьей стороны, чьи действия FIDO2 не регулирует.

FIDO2 по‑прежнему подвержен MitM и кражам сессии, да и в плане приватности для пользователя он не дает новых надежд. Аппаратные токены не обновляются, так как это несет риск их заразить, поэтому на пользователя падает бремя не только выбора и покупки железа, но и его замены в случае критической уязвимости.

БА ради удобства предлагает отказаться от пароля и использовать только один фактор. Получается, что мы скатываемся от привычного 2FA, где есть и пароль и код OTP к 1FA, где есть только аутентификатор. Конечно, можно реализовать многофакторную БА и использовать ещё, например, биометрию, но в чем тогда разница с нынешней парольной аутентификацией? Все равно ведь нужно будет вписывать разные коды и даже таскать с собой аппаратный токен, что повышает риск его потерять.

FIDO2, как и идея БА, конечно, выглядят очень многообещающе. Проделана огромная работа, крупные компании согласились действовать вместе ради благородной цели — сделать жизнь проще и безопаснее. И пускай начало беспарольной революции уже положено, но работы предстоит еще очень много. А значит, в обозримом будущем мы вряд ли откажемся от паролей.
 
Activity
So far there's no one here
Сверху Снизу