Шведский BankID — это форма цифровой идентификации, используемая большинством, если не всеми, жителями Швеции для аутентификации на различных сервисах, таких как: интернет-провайдеры, онлайн-банковские услуги, сайты ставок и особенно правительственные веб-сайты.
Я сам живу в Швеции, и с хакерским менталитетом, который всегда крутится в моей голове, я решил, что это будет очень интересная область для проведения некоторых исследований в области безопасности.
В этом посте я расскажу о новой уязвимости, которую я обнаружил у большинства шведских поставщиков услуг из-за небезопасной реализации протокола аутентификации BankID.
Я кратко расскажу, как работает такой протокол, как выглядит уязвимая конфигурация, как ее использовать, как исправить и, наконец, что эти типы атак означают для общей реализации eID.
BankID — это услуга, которая устанавливается на устройство пользователя и получается путем запроса ее в шведском банке при условии, что у вас есть шведский персоннумер — персональный фискальный код. Приложение устанавливается на устройство пользователя и подключается к его фискальному коду, по сути привязывая его/ее личность к такому приложению. Часто именно так работают системы электронной идентификации: уполномоченная правительством и доверенная третья сторона раздает часть программного обеспечения, привязанную к конкретному лицу, а затем службы интегрируются с поставщиком этой части программного обеспечения, чтобы позволить пользователям проходить аутентификацию на своих устройствах. платформа, модель общего доверия, которая позволяет сервисам легко аутентифицировать людей.
BankID ничем не отличается и предоставляет документацию для таких сервисов, которые отныне будут называться проверяющей стороной (RP), чтобы они могли легко интегрировать свой поток аутентификации с BankID. https://www.bankid.com/en/utvecklare/guider/teknisk-integrationsguide/rp-introduktion .
При использовании BankID для аутентификации пользователя используются два основных потока:
Аутентификация на том же устройстве
Авторизация на другом устройстве
Мы скоро вернемся к этим двум, однако оба потока начинаются с того, что RP отправляет запрос к API BankID для запуска порядка аутентификации. В этом почтовом запросе RP должен указать параметр endUserIp
, который содержит IP-адрес пользователя, который пытается войти в систему, это будет важно позже в отчете.
Конечная точка API /auth
ответит примерно так:
HTTP/1.1 200 OK Content-Type: application/json { "orderRef":"131daac9-16c6-4618-beb0-365768f37288", "autoStartToken":"7c40b5c9-fa74-49cf-b98c-bfe651f9a7c6", "qrStartToken":"67df3917-fa0d-44e5-b327-edcc928297f8", "qrStartSecret":"d28db9a7-4cde-429e-a983-359be676944c" }
orderRef
— это идентификатор, который RP может использовать для конечной точки /collect
для проверки статуса аутентификации и последующего получения необходимой информации о пользователе от этого человека.autoStartToken
— это токен, который используется RP для создания глубокой ссылки , при нажатии на которую открывается приложение BankID и предлагается пользователю пройти аутентификацию ( это будет очень важно ). qrStartToken
и qrStartSecret
будут рассмотрены ниже, но они не являются строго важными для проводимых исследований безопасности.
Помимо IP-адреса пользователя, RP может указать дополнительные параметры для порядка аутентификации, включая текст, который будет отображаться в приложении BankID, и требования к аутентификации .
Среди требований аутентификации, которым будет посвящен этот пост, относятся политики сертификатов . Они позволяют RP сообщать BankID, какой из двух потоков был выбран пользователем.
Когда пользователь решает пройти аутентификацию с использованием BankID на том же устройстве, RP использует autoStartToken
для создания глубокой ссылки, которая выглядит следующим образом: bankid:///?autostarttoken=7c40b5c9-fa74-49cf-b98c-bfe651f9a7c6&redirect=https://service.com/login
. Эта глубокая ссылка затем подхватывается операционной системой пользователя и передается приложению BankID.
При исследовании этого потока была обнаружена уязвимость Open Redirect , поскольку проверка параметра redirect
со стороны BankID не выполняется. Позже я расскажу, почему эта дополнительная ошибка делает атаку перехвата сеанса еще более мощной.
Когда пользователь решает пройти аутентификацию с использованием BankID на другом устройстве, RP использует qrStartToken
и qrStartSecret
для генерации динамического QR-кода (путем получения данных следующего кадра из вышеупомянутой конечной точки /collect
), который может сканироваться пользователем с помощью его Mobile BankID. приложение.
Они ДОЛЖНЫ быть указаны RP при инициировании заказа аутентификации. Они позволяют BankID отклонять попытку аутентификации, если поток не совпадает, чтобы уменьшить риск фишинга. Например, если пользователь выбрал «аутентификацию на том же устройстве», RP должен сообщить об этом BankID, чтобы при попытке аутентификации по мобильному BankID и/или с использованием QR-кода приложение могло ее отклонить.
В дополнение к этому, после завершения аутентификации RP может получить ipAddress
, который использовался для открытия приложения BankID, из конечной точки API /collect
. Затем это СЛЕДУЕТ сверить с IP-адресом пользователя на RP, если он выбрал «аутентификацию на том же устройстве».
Политики сертификатов вместе с ipAddress
СЛЕДУЕТ использовать, чтобы гарантировать, что поток аутентификации не может быть подделан.
Тем не менее, несмотря на то, что эти меры безопасности существуют, BankID не отражает их важность и не реализует их правильно даже в представленном примере реализации! https://github.com/BankID/SampleCode
Так что же произойдет, если этот протокол не будет реализован безопасно?
Когда я впервые увидел глубокую ссылку bankid:///
я просматривал свои формы заявления в университет, доступ к которым можно получить, войдя в систему с помощью BankID. Сначала я подумал: а что будет, если я отправлю кому-нибудь эту глубокую ссылку? Поэтому я отправил его своему другу, который нажал на него, и, к моему удивлению, после того, как он открыл BankID, передо мной оказались все его заявления в университет!
Именно тогда я начал изучать API BankID, реализовал свой собственный RP и узнал обо всем, что я только что изложил.
После нескольких недель исследований я разработал сценарий, который автоматизировал захват глубоких ссылок bankid:///
для более чем 30 RP. Этот сценарий запускал веб-сервер и создавал путь для каждой службы, когда пользователь посещал ссылку для конкретную службу, сценарий получит свежую ссылку и перенаправит на нее пользователя. Это приведет к тому, что устройство пользователя откроет приложение BankID, и после аутентификации вместо него будет аутентифицирован я.
Мне удалось это сделать, потому что:
RP не отправляли политики сертификатов в BankID, что позволило мне получить глубокую ссылку и передать ее в приложение Mobile BankID.
RP не сравнивали IP-адрес, запрашивающий ссылку, с IP-адресом, завершившим аутентификацию.
RP предоставили ссылку, даже когда была выбрана опция «аутентификация на другом устройстве».
Это привело к уязвимости фиксации сеанса.
Давайте представим себе уязвимый сервис под названием AmazingSevice AB. Они реализовали поток BankID в соответствии с предоставленным примером кода и размещают такую реализацию по адресу https://amazingservice.se/login/bankid
.
Злоумышленник интересуется пользовательскими данными, хранящимися на AmazingSevice AB, и держит свою жертву в поле зрения. Ему просто нужно будет автоматизировать захват ссылки bankid:///
, разместить ее на своем сервере, а затем отправить ссылку на свой вредоносный сервер своим жертвам. Выбрав понравившуюся ему фишинговую доставку (СМС, электронная почта и т. д.), он встроит ссылку в сообщение, выдавая себя за AmazingSevice AB и предлагая жертве авторизоваться.
Подобный захват учетной записи практически не требует социальной инженерии, поскольку как только жертва нажимает на ссылку, ей немедленно предлагается открыть BankID, оставляя «неизвестную территорию» сайта злоумышленника для гораздо более знакомого интерфейса BankID. Кроме того, AmazingSevice AB запрашивает запрос аутентификации, который жертва увидит в приложении BankID, что делает невозможным обнаружение мошеннического поведения.
После аутентификации жертвы сеанс злоумышленника аутентифицируется для учетной записи жертвы, жертву можно дополнительно обмануть, воспользовавшись уязвимостью Open Redirect , присутствующей в BankID, что позволяет злоумышленнику указать параметр redirect
как https://amazingservice.se/login/bankid
. Это приведет к тому, что жертва будет перенаправлена на законный веб-сайт службы, в результате чего он просто будет думать, что аутентификация не прошла успешно.
По понятным причинам я не смог воспользоваться услугами одной из компаний, о которых сообщил, поэтому вместо этого в демо-версии показано, что демо-сервис BankID уязвим к этому!
В правом углу — вид жертвы, получившей ссылку, здесь имитируется посещение сайта злоумышленника. Как только жертва посещает ссылку, сервер злоумышленника открывает автономный браузер и извлекает ссылку bankid:///
которая затем передается на телефон жертвы. В приложении BankID вы можете увидеть «Test av BankID», который является законным источником демонстрационного сайта BankID. Кроме того, в начале видео включается VPN, чтобы убедиться, что во время аутентификации не выполняется проверка IP-адреса. В конце концов, можно увидеть, что на ноутбуке злоумышленника он авторизован как жертва (Йохан Йоханссон).
Ошибка фиксации сеанса приводит к захвату учетной записи в один клик в любом приложении, которое использует шведский BankID в качестве поставщика аутентификации и неправильно (или вообще не реализует) политики сертификатов и проверки ipAddress
. Это довольно серьезно, поскольку зачастую сервисы, использующие BankID для аутентификации своих пользователей, имеют доступ к весьма конфиденциальным данным и действиям. Более 30 приложений были признаны уязвимыми для этой атаки, с максимально возможным количеством приложений связались, в результате чего на основных платформах было принято 11 отчетов об ошибках.
Одна из служб, о которой я сообщил об этой уязвимости, смогла связаться со шведской национальной CSIRT, поскольку проблема широко распространена и серьезна. Переговоры только начались, поэтому, если вы хотите быть в курсе новостей, подписывайтесь на меня в Твиттере (X) @m4st3rspl1nt3r.
Если вы ищете пример того, как выглядит безопасная реализация BankID RP API, я создал ее, которую вы можете использовать либо как библиотеку Golang, либо настроить и развернуть как микросервис. Вы можете найти это здесь .
Большинство пострадавших служб, особенно тех, у которых есть BBP и VDP, были весьма восприимчивы и быстро отреагировали на мой отчет. Однако ответ BankID был немного другим. В одном электронном письме, которое я получил после многократного обращения к ним по различным каналам, они объяснили, что знают о проблеме, но считают, что с ней мало что можно сделать, чтобы сохранить «простоту интеграции» для RP. Запланированное смягчение последствий, которое, к сожалению, все еще требует внесения изменений на стороне RP, было сообщено мне (но по какой-то причине его нигде нет в их документации) следующим образом:
Дополнительное требование, которое сможет установить RP, — это Риск. Это установит приемлемый уровень риска для сделки. Если риск транзакции превышает требуемый лимит, транзакция будет заблокирована. «НИЗКИЙ» — принимать только ордера с низким риском. «СРЕДНИЙ» — принимать ордера с низким и умеренным риском. Если этот параметр установлен. Мы, среди прочего, проведем проверку IP на своей стороне, если она предоставлена RP. Другими параметрами риска, которые будут отслеживаться, если они предусмотрены, являются ReferDomain, UserAgent и DeviceIdentifier.
Кроме того, существует план по устранению уязвимости Open Redirect.
Мое личное мнение по этому поводу таково: если вы разрабатываете и используете столь важного и широко распространенного поставщика аутентификации, который часто используется для защиты очень конфиденциальной пользовательской информации, вам следует должным образом документировать свои механизмы безопасности, чтобы RP могли безопасно интегрировать его. Дополнительные функции безопасности совершенно бесполезны, если разработчик может сэкономить время, не реализуя определенные функции/параметры, именно это и произойдет, и мы не можем винить в этом сторону RP. BankID должен сделать все возможное, чтобы перенести на свою сторону как можно больше функций по борьбе с мошенничеством и безопасности, чтобы сохранить «простоту интеграции», но также обязательно должным образом документировать любые дополнительные функции безопасности, которые должен реализовать RP; обратите внимание на обязательное , а не необязательное.
Эта часть блога является чисто моим мнением.
Для меня эта уязвимость является примером, показывающим опасность предоставления частной компании полного контроля над системой, которая имеет решающее значение для населения страны. Причина, по которой я считаю, что это более серьезно, чем просто еще одна уязвимость в компании-разработчике программного обеспечения, заключается в том, что BankID — это то, что используют более 8,5 миллионов жителей Швеции, он используется для входа в ваш банк, страховую компанию, поставщика электроэнергии и другие конфиденциальные платформы, которые иметь реальные последствия.
Если кто-то обнаружит захват учетной записи на Facebook, вы можете потерять некоторые фотографии. Если кто-то обнаружит уязвимость в системе eID вашей страны (часто частной), последствия для чьей-либо жизни могут быть невообразимыми.
Все больше и больше европейских стран принимают eID, и ЕС планирует в ближайшие годы внедрить собственный eID ЕС (подробнее об этом можно прочитать здесь ).
Я надеюсь, что регулирующие органы будут настаивать на том, чтобы поставщики eID полностью разрабатывались и контролировались государственными учреждениями, возможно, с требованием, чтобы такие системы были с открытым исходным кодом и регулярно проверялись на наличие недостатков безопасности.
Как мы можем безопасно принимать в нашем обществе столь важные части программного обеспечения, если они разработаны частной компанией?
Хотя основной темой этого сообщения в блоге была атака с фиксацией сеанса на BankID, я обнаружил, что многие другие поставщики аутентификации/идентификации были разработаны с тем же недостатком. Новый класс уязвимости можно найти у провайдеров, которые требуют использования другого устройства (часто мобильного телефона) для завершения процесса аутентификации.
Исследования продолжаются, и вскоре я надеюсь опубликовать новые результаты и инструмент , над которым я работаю, который можно использовать для автоматизации и использования таких уязвимостей. Следите за моей следующей темой. Задуманная фиксация сеанса — кошмары межустройствной аутентификации
А пока взломайте планету!