Мы привыкли доверять приложениям, которые установили на свои гаджеты. Порой обоснованно, порой не очень. Если посмотреть документацию на API авторизации какого-нибудь крупного российского банка или соцсети, то можно увидеть Oauth 2.0, OIDC, authorization code flow и т.д. К сожалению, в большинстве случаев это либо не соответствует действительности вообще, либо частично. Как будто за всеми этим упускается один важный момент, и сегодня мы поговорим об этом более подробно.
Смотрим примеры
Пару лет назад я начал активно интересоваться вопросами авторизации и аутентификации – кроме изучения соответствующих опенсорсных решений, таких как keycloak, я присоединился к сообществу spring security и начал активно вносить свой вклад в развитие фрэймворка – мои активности можно посмотреть в аккаунте на github, там как мелкие доработки, так и полноценные core-фичи. По мере накопления опыта мой скептицизм в отношении безопасности некоторых приложений, установленных на моем iphone 12, только увеличивался. На самом деле все не совсем так – я пришел к выводу, что подавляющее большинство мобильных приложений в моем телефоне не очень-то и безопасны в плане авторизации. Давайте рассмотрим пару примеров. Вот с чего начинается процесс авторизации и аутентификации в приложении одного крупного банка (не вижу смысла скрывать его название):

После ввода номера телефона приходит смс с кодом, который также надо ввести. Это первый фактор. Второй фактор можно пройти по номеру карты и паролю:

А вот так выглядит первый экран авторизации в одной известной отечественной соцсети:

В общем-то точно такое же начало, как и в предыдущем случаем. Для сравнения давайте посмотрим с чего начинается авторизация во всеми нам известном сервисе от компании Google:

Как минимум у нас появилась кнопка «Войти». Уже лучше, давайте нажмем эту кнопку.

Youtube честно нас предупреждает, что для входа в приложение будет использован google.com. Хорошо, продолжим.

Если присмотреться внимательно, то это ни что иное, как браузерное окно – вверху виден адрес открывшейся страницы.
Посмотрим еще один пример авторизации от Microsoft:

Кнопка есть, как и в предыдущем варианте. Далее:

Уже знакомое нам предупреждение. Продолжаем:

Я думаю, что дальше нет смысла продолжать.
Разбор
Видно, что первые два варианта авторизации сильно отличаются от youtube и github по своей природе. Скорее всего большинство пользователей (и опытные it-инженеры, в том числе специалисты по безопасности) не увидят тут какого-либо подвоха и спокойно будут вводить свои авторизационные данные что в приложение вк, что в youtube. Проблема в том, что у первых двух приложений есть один важный момент, связанный с упомянутым выше Ouath 2.0 – они фундаментально небезопасны, т.к. их авторизация противоречит основной идее Oauth 2.0. А точнее – не отдавать клиентскому приложению свои учетные данные (логин, пароль). Мы видим, что youtube так не делает, вы не вводите в нативных формах приложения логин, пароль, какие-либо коды из смс, и т.д., youtube открывает для вас отдельное браузерное окно, где мы видим сервер авторизации google, и вот ему вы уже честно отдаете свой логин, пароль и все, что он у вас попросит. Аналогичная ситуация у github. Оба этих варианта подразумевают, что есть некий сервер авторизации, которому вы доверяете, на нем вы проходили регистрацию, и приложение всегда предупреждает вас, что именно этот сервер сейчас запросит у вас учетные данные. Безопасно получить доступ к этому серверу можно только через браузер, который должен открыться отдельно от самого приложения. У того же google процесс авторизации внешне выглядит одинаково, при этом неважно, где бы вы авторизовывались – где-то в браузере на своем ПК или в мобильном приложении. Что касается первых двух приложений, то все, что требует протокол авторизации вводится исключительно в самом приложении (не в отдельно открытом браузере). И тут важно понимать почему это небезопасно.
Вот что написано в RFC:

Наверное, кто-то скажет, что это ведь не password grant как таковой, но по факту разницы нет. Это ровным счетом тоже самое, более правильно было бы написать не про конкретный grant, а про возможность ввода каких-либо авторизационных данных на клиенте в принципе.
Про потенциальные утечки пароля, трояны, перехватывающие otp и т.д. мы уже слышали много раз. Да, такое возможно, история знает много примеров, когда учетные данные куда-то утекали из клиентского приложения. В принципе, я верю, что такое сейчас случается нечасто и в этом плане современные мобильные приложения можно считать относительно безопасными. Что конечно же является большой натяжкой. Не нужно сбрасывать со счетов этот момент, но прежде всего стоит обратить внимание на кое-что другое – вы привыкаете вводить свой логин и пароль в приложение, в его интерфейс, а не в браузер. Никто вас не предупреждает, что ваше приложение хочет использовать какой-либо сервер для авторизации. Вы просто верите, что вы вводите пароль туда, куда надо. Наученные годами пользования youtube пользователи могут несколько раз подумать прежде, чем вводить свой пароль куда-то в другое место, где не выскакивает окно предупреждения и не открывается привычная страница google.com со знакомыми кнопками. А могут и не думать вовсе, т.к. в телефоне есть куча приложений, где такого нет, а значит можно вводить свой логин пароль как угодно и куда угодно.
Удивительно, что такой проблемой страдают, наверное, все отечественные банки, где процесс авторизации идет исключительно в мобильном приложении. И как бы странно это не звучало, но на вопрос «неужели крупный банк может подвергать опасности меня и мои финансы?» ответ – да, может. Если посмотреть с какой периодичностью в том же app store появляются откровенно мошеннические приложения, которые пользуются, тем фактом, что пользователь просто не привык видеть то, что он видит при авторизации в том же youtube. Например, раз, два, три. Это классическая атака «человек посередине».

Можно бесконечно предупреждать о фейковых приложениях в app store, пользователям от этого легче не станет, причины таких атак и, как следствие украденных учетных данных (и денег тоже) кроются в самих компаниях-разработчиках этих приложений – нужно предпринимать конкретные шаги для уменьшения вероятности атак, следуя рекомендациям rfc и хотя бы того же Oauth 2.0.
Подробно обсуждать ситуацию с телеграм я не буду. Всем и так известно, что количество угнанных аккаунтов исчисляется тысячами. Примерно по тем же самым причинам, что и в вышеописанных случаях. Последствия в общем-то тоже известны – многие истории настолько драматичны, что хочется искренне посочувствовать жертвам мошенников.
И что нам делать?
Увы, мы тут заложники ситуации. Пока в наших телефонах будут такие приложения мы будем вынуждены вводить свои учетные данных именно так, как они требуют. Неважно безопасно это или нет. Причин тому может быть много, я слышал разные объяснения – от классического «исторически так сложилось» до «бизнес требует». Наверное, в первую очередь тут стоит работать с разработчиками приложений и специалистами по it-безопасности, чтобы у них в головах появились новые категории и паттерны веб-секьюрити. Может ли решить все проблемы массовое внедрение настоящего Oauth 2.0 в мобильных приложениях. Я думаю, что нет, проблемы все равно останутся, но мы можем решить часть этих проблем и уменьшить поверхность атак и вариантов мошенничества, а это уже будет небольшой победой.
Вместо послесловия
Где-то год назад на форуме keycloak появился вопрос Programmatically registering & authenticating passkeys. Автор пытался понять есть ли у keycloak какой-либо REST API для авторизации через пасскеи (т.е. без пароля). На что получил весьма содержательный ответ от одного из основных разработчиков keycloak:

Тут добавить нечего…
Автор: franticticktick