Современный Интернет не предоставляет механизмов предотвращения захвата аккаунтов. FIDO2 — классно, но нас не спасет

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

Захват аккаунта может произойти на трех стадиях:

  1. Вход в аккаунт

  2. В аккаунт уже вошли и перехватили сессию

  3. Восстановление аккаунта

Удостоверься, что ко мне пришел тот же пользователь, что и проходил регистрацию

Задача аутентификации в типичном веб-приложении

1. Вход в аккаунт

Очевидно, чтобы захватить аккаунт, можно предоставить то, чему поверит сервис чтобы нас пустило под нужным пользователем

И мы начали с паролей

С понятного пользователя механизму, известного из давних времен. В самом начале, в 90-е, это неплохо работало. Но после начались проблемы:

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

  • Credential stuffing. Окей, пользователь запомнил один сложный пароль и начал использовать его везде. Злоумышленники начали взламывать менее защищенные ресурсы и использовать пароли на привязанных почтах и других сервисах. Сервисы, для своей защиты, стали выкачивать утекшие базы паролей к себе и блокировать пользователей, запрещая скомпроментированные пароли. Пользователи начали добавлять к своему, старому, сложному, скомпроментированному паролю,»1» или »2» в конец или в начало. Злоумышленники начали делать тоже самое. Дефенсивы тоже начали мутировать утекшие пароли. И так по кругу.

Злоумышленники пытаются запугать пользователей через утекшие базы с паролями. Они заработали более $500,000, https://www.vice.com/en/article/xwk3wq/hackers-sextortion-half-million-blackmail-caught-watching-pornЗлоумышленники пытаются запугать пользователей через утекшие базы с паролями. Они заработали более $500,000, https://www.vice.com/en/article/xwk3wq/hackers-sextortion-half-million-blackmail-caught-watching-porn

  • Борьба с брутфорс атаками. Полностью нерешенная задача ни одной компанией с массовым сервисом. Самый менее затратный, и наиболее действенный способ — это «supercookies», блокировка вообще любых входов кроме как с устройств, с которых уже был вход (trusted devices), имеет недостатки:

    • Очевидное допущение самого существования «supercookie» и подобных устройств

    • Возможность злоумышленнику заблокировать вход в аккаунт с любого другого, non-trusted устройства

    • Блокировка non-trusted устройств должна сниматься и можно аккаунт брутить снова

    • Не работает на протоколах без cookies — например IMAP

  • Фишинг. Браузеры позволяют отправлять один и тот же пароль в разные origin. Само это допущение нужно только для нормального UX, но это несовместимо с безопасностью. Да еще и сами сервисы часто приучают пользователя быть уязвимым — делают кучу форм с вводом пароля на основном домене, на поддоменах, да что там — бывает и на совершенно других доменах второго уровня. Некоторые команды смогли исправить это ужасное допущение прошлого и разместить форму на домене вида auth | account | login .example.com, еще и проставляя куку, что именно на этом домене юзер ввел пароль (мы еще к этому вернемся), но это большая работа.

  • Парольные менеджеры. Ужасный костыль, который мы изобрели, чтобы подпереть им проблемы выше. Массовые сервисы спасет (на сегодняшний день) только принудительная двухфакторная аутентификация для всех пользователей без исключения и мы уже видим, что это работает — например в Steam. Парольные менеджеры так и будут уделом гиков и продвинутых пользователей, которых в самом лучшем раскладе не более 5–10%. Был бы я инвестором, не вложился (или вложился только на краткий срок) в проекты парольных менеджеров.

Я использую 1password, но очень бы хотел этого не делатьЯ использую 1password, но очень бы хотел этого не делать

  • Безопасное хранение паролей — сложная инженерная задача, использовать Bcrypt/Scrypt/Yescrypt с «правильным» настройками недостаточно, про это есть хорошая статья. Я с ней не везде не согласен, но, как минимум, обратите внимание на подход проверки пароля без прав select на столбец с хешем пароля, через хранимые процедуры. Этого нет ни в одном из популярных фреймворков для разработки — Wordpress, Django или других, будем считать — что почти никто в мире не хранит пароли безопасно по сей день. И единицы сервисов будут подкручивать коэффециенты хэширующих функций в будущем, поговорим про это в отдельной статье.

И пришли SMS

Первым массовым сервисом с аутентификацией по SMS можно назвать WhatsApp и вход через SMS поменял правила игры. Пользователям — удобно, злоумышленникам стало сложнее (скольких знакомых вы можете назвать, у которых был взломан WhatsApp?). Казалось, страдали только владельцы бизнесов, ибо SMS начали дорожать, операторы хотят хоть как-то на них зарабатывать из-за повального перехода пользователей в мессенджеры. Но тут начинается слух, что и SMS небезопасны! Правда ли это и взламывают ли через них пользователей? Давайте также разберем все способы, как можно перехватить SMS:

Перевыпуск SIM карт

Самый частый способ, который упоминают в дискуссиях. Одним из самых популярных способов перехвата SMS действительно, до сих пор, является перевыпуск SIM карт в салонах связи. Вопрос стоит в сумме взятки или обман консультанта (где потребуются данные паспорта, которые злоумышленники могут найти какими-либо иными способами) и SIM карта готова. Как это пытаются исправить:

  1. Операторы пытаются решить вопрос организационно — усложняя процесс перевыпуска и пытаясь повысить ответственность своих сотрудников. Вполне себе есть уголовные дела после таких «залетов»

  2. Операторы запрещают прием SMS первые сутки-двое после перевыпуска SIM карты. Реальный владелец в этом случае замечает проблему и может успеть вернуть номер себе

  3. Можно мониторить перевыпуск SIM карт через операторов, но это стоит довольно дорого и обычно работает всего для нескольких стран

Перехват SMS при помощи программно-аппаратных комплексов

Этот способ требует от атакующего находиться физически рядом с «жертвой»:

  1. Атакующий находится рядом с жертвой и при помощи SDR слушает эфир

  2. Атакующий посылает «silent sms» на номер «жертвы» — специальный вид SMS, который приходит на устройство. При помощи него атакующий узнает TMSI (Temporary Mobile Subscriber Identifier) — специальный временный идентификатор, который используется для регистрации абонента в сети

  3. Атакующий запрашивает SMS, которое нужно перехватить

  4. SMS приходит на устройство «жертве»

  5. Атакующему надо быстро расшифровать трафик между базовой станцией и телефоном жертвы — для этого есть готовые бесплатные инструменты, требуется только специально сформированный файл весом в 1.6 ТБ («радужные» таблицы) и более-менее быстрый компьютер, т.е. уровень типового пользователя

  6. Готово, SMS расшифровано

Из минусов для атакующего — «жертва» увидит это SMS. Также сам способ требует заглушить 3G/4G/5G, что не так сложно, но тоже дополнительный шаг. Кстати, про безопасность GSM есть ресурс https://gsmmap.org/, на котором энутзиазисты собирают состояние безопасности по каждой стране и оператору и у кого проще или сложнее перехватить SMS или звонок. Данные не совсем актуальны, но полезно посмотреть сами подходы и аналитику в прошлом. Например, в Сингапуре, 2G полностью отключен с 2021 года.

Атаки через SS7

Про атаки через SS7 было достаточно много статей. Вкратце так — есть система, которую используют по всему миру. Подключившись к ней, т.е. по факту став оператором связи (говорят, стоит 20–50к+ евро) можно сообщать другим операторам связи, что теперь конкретный абонент у тебя в роуминге. И все звонки-SMS направлять к себе. Результат — перехват SMS. Некоторые группировки не покупают доступ, а взламывают операторов, которых много и не все занимаются безопасностью, главная добыча — доступ к SS7.

Malware

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

Экзотические атаки

Примером такой атаки может служить ресерч от shubs из Австралии в 2014 году (https://shubs.io/how-i-bypassed-2-factor-authentication…/). Вкратце:

  1. Запрашиваем на номер жертвы в каком-либо сервисе SMS с TOTP

  2. Если выждать 30–60 секунд часто появляется кнопка «Не пришло SMS? Позвонить мне и продиктовать код». Не (!) жмем её

  3. В этот момент звоним жертве и занимаем номер телефона

  4. Теперь жмем кнопку на шаге 2 и звонок попадает в голосовую почту

  5. Подменяем номер телефона на номер жертвы (что стоит $1-$5) и звоним на номер для чтения голосовой почты. Или подбираем пин код к голосовой почте (чаще всего нет рейтлимитов на это, как в статье выше)

  6. Читаем почту, забираем код

Инфраструктурные уязвимости

Есть приложения от операторов связи, которые позволяют перенаправлять SMS и в них бывают уязвимости (или в сервисах для бизнеса). Разработчики могут случайно залогировать коды из SMS где-нибудь по пути. Также из реальных кейсов — это взлом шлюзов через которые SMS отправляют компании и вся безопасность в итоге сводится к безопасности этих шлюзов. Чтобы эффективно и дешево отправлять SMS всему миру нужно подключить более 30–50 таких шлюзов если у вас популярный ресурс

Но все ли так плохо с SMS? Взломов все-таки становится меньше

1. Вход через SMS — зло и плохо, так делать не надо, их «легко» перехватить

Все потенциальные векторы выше уже доступны для атаки и взлома юзеров на любом популярном сервисе и дают доступ в аккаунт (!). Вы практически везде (естественно, в аккаунте без 2-факторки), при привязанном номере телефона, можете восстановить доступ по номеру телефона, запросить SMS и попасть в аккаунт. Это уже доступно

2. Вроде да, но это требует смены пароля или придет пуш о новом входе (Telegram), будет разлогин (WhatsApp), это более заметно

Сравним импакт. Хоть при логине через SMS, хоть при восстановлении доступа к аккаунту и смене пароля — юзер (или злоумышленник) попадает в аккаунт и получает доступ к данным, разница лишь в несколько секунд и надо в первую очередь думать над этим. Это именно то, что обсуждается в статье.

Чаще всего аккаунт взламывают из-за ненадежного или украденного пароля и их можно спасти входом без пароля, в т.ч. кодом через SMS. Но все же:

  • Это дорого

  • Не работает в оффлайне

  • Завязка на чужой инфраструктуре

  • Остается возможность брутфорса кода, как прямого — брут конкретного пользователя, так и горизонтального — брутфорс миллионов пользователей с одним и тем же кодом. Нужна инженерная работа — например увеличивать длину кода с 6 до 8–9 символов при аномалиях и т.п.

  • Ввод кода все также уязвим к фишингу

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

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

Вход через почту

Отличный способ, пока вы не сами почтовый сервис :) Но давайте разберем, какие способы входа бывают:

  • Отправка TOTP кода, проблемы:

    • Прямой перебор

    • Перебор с ротацией IP

    • Горизонтальный перебор (один код к куче email’ов)

    • Фишинг

  • Переходим по секретной ссылке из письма с достаточно устойчивым к бруту токеном — логинит во вкладке с этой ссылкой. Проблемы:

    • Отравление Host заголовка (и подмена ссылки, по которой перейдет пользователь)

    • Фишинг (теоретически)

    • CSRF на логин

    • UX — юзер вообще-то хотел зайти возможно в другом браузере и устройстве

  • Переходим по секретной ссылке из письма с достаточно устойчивым к бруту токеном — логинит в оригинальной вкладке. Проблемы:

    • Массовая рассылка таких ссылок (IP rotation), кто-нибудь да кликнет, где-нибудь да пустит

    • Фишинг (теоретически)

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

OAuth

В целом — отличный способ, похожий на предыдущий. Самая частая ошибка при реализации входа через внешний сервис это отсутствие CSRF защиты при привязке аккаунта и что злоумышленник может начать сам привязку и дать ссылку с последнего шага «жертве» и привязать свой аккаунт к аккаунту жертвы. Это описывал Егор еще в 2012, но до сих пор актуально.

FIDO2

Конечно же, абсолютный лидер в плане безопасности:

Но есть множество проблем:

  • Аутентификаторы на девайсах, условный Touch ID на Mac или Windows Hello, работают только как дополнительные устройства для входа. И они не для регистрации аккаунта, они не мобильны. Ситуация c Apple меняется с приходом Apple PassKeys

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

  • Оба вида аутентификатора требуют покупки, минимум по 20 долларов за переносимый аутентификатор. Скоро ли мы увидим рядом с заточкой ключей около метро продажу Fido2 ключей? Думаю, что нет

Apple и Google за последние 3 года сделали многое чтобы популяризировать Fido2, если у вас Pixel (возможно и другие Android устройства) / iOS 16+ устройство с включенным iCloud и синхронизацией keychain — вы уже можете использовать их как переносные Fido2 ключи, но не все так гладко.

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

Мы приравняли проверку кучи факторов, может самых безопасных, к какому-то рандомному токену в Cookie и верим ему на каждом шаге после входа в аккаунт

2. Захват существующей сессии

Как мы видим, текущие механизмы или позволяют легко ошибаться в реализации, или зависят от другой платформы и это не то, что мы хотим видеть как технологию, которая должна быть отчуждена и достаточна сама по себе. Fido2 будет решением, когда покроет 99%+ пользователей. И все же, сессия создана и account takeover может быть сделан через нее. Сессия — какое-то одно или несколько рандомных значений в cookie (или localstorage, для отчаянных людей, которые не боятся XSS)

Session confusion

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

  • У вас есть attacker.com, на котором вы заходите под своим user_id=1 и получаете сессию abcdef123456. Сайт находится на shared хостинге

  • Есть victim.com, который использует такую же CMF/CMS и смотрит на условные поля в сессии user_id, и использует этот же shared хостинг

  • Мы берем сессию abcdef123456 и подставляем ее в cookie, но уже при запросе на victim.com, получая сессию под нужным пользователем

Если хостинг не разграничил сессии на каждого клиента мы получаем возможность крафтить сессии между сайтами. Конечно, это пофиксили давно, но вот в этом репорте именно это и случилось. Был партнерский сайт, куда можно было приходить с cookie с основного сайта и натыкаться на случайные, чужие аккаунты. И все потому, что мы почему-то используем рандомные значения для аутентификации после проверки всех факторов

Malware

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

Mitigation-костыли

В итоге все полагаются на сессию и хотели бы защититься от случаев, когда она утекла. В мире придумали самое очевидное решение — sudo сессии. Т.е. на все критичные действия еще раз спрашивать пароль. Ну, про пароли ты мы помним, да? Еще можно редиректить на условный домен account.example.com, в котором мы ставили супер cookie когда юзер вводил пароль, но и это частичное решение проблемы. Скорее, времен HTTP и возможного MitM.

3. Восстановление аккаунта

Сколько вы видели докладов, как правильно делать восстановление аккаунтов?

Сколько вы видели докладов, как ломать восстановление аккаунтов? (Скорее всего, чуть больше)

Ни у кого нет правильной инструкции как правильно восстанавливать аккаунты и не иметь нулевой retention rate и каждый придумывает свое решение.

Интересное чтиво доступно в статье Wired, пусть и 2012 года, но оно актуально до сих пор. Бывают и ошибки в бизнес-логике, например, на одном популярном сервисе можно было менять в cookie step=2 на step=5 и попадать на финальный шаг восстановления аккаунта и менять пароль.

Мы бы могли свести к нулю захват аккаунтов через восстановление имея возможность связывать достаточное количество технических устройств (включая FIDO2) на регистрации, но это все также пока что убивает конверсию. Главное помните — нельзя использовать контрольные вопросы.

Все придумано до нас

Вы можете быть удивлены, но решение большинства проблем векторов 1 и 2 было реализовано в браузерах лет 15 (?) назад. С рядом проблем, конечно же, но все так — это Client Certificate Authentication, которую вы практически не можете встретить в интернете и не встретите ни в одном популярном сервисе. Как это работает?

  • Вы генерируете пару приватный и публичные ключи, и импортируете в браузерное хранилище ключей

  • При входе на сайт он вам сообщает, что хочет от вас аутентификацию по ключу

  • Браузер делает хендшейк и каждый ваш последующий запрос аутентифицирует

Пример запроса сертификата в браузереПример запроса сертификата в браузере

Проблемы:

  • Очевидно, UX. Откуда этому ключу взяться? Надо его сгенерировать (так, к слову, делает старый и добрый клиент TeamSpeak3)

  • Нет возможности разлогина. Т.е. выбрали сертификат и все — браузер будет тупо его использовать каждый раз, сбросить состояние можно только через настройки, открытие incognito или полный перезапуск браузера. Прямо как basic auth, как аутентифицироваться придумали, а разлогин — забыли

  • Malware. Пока ключ на файловой системе его можно своровать, но уже можно использовать, например, Yubikey и троян не сможет своровать ключ. Еще бы поддержку встроенных HSM, надеемся и она скоро будет

Какой крутой способ, мы почти у идеала. Проблемы еще есть, но мы бы могли их решить

Keyless Certificate Authentication

Анализируя все проблемы безопасности и UX кажется очевидным, что все, что нам нужно, чтобы все-таки предотвратить в некотором максимуме проблему захвата аккаунта, это совместить все лучшее, что мы уже умеем:

  • Превратить каждое мобильное устройство не в FIDO2 ключи, а в генератор TLS тикетов, на подобии как работает Keyless SSL в Cloudflare. Хранить приватный ключ в HSM (есть в любом современном девайсе) и передавать эти тикеты на PC, если нужно. Мы уже научились в похожий механизм в Paywave/Paypass при оплате картой с телефона или часов.

  • Реализовать заголовок в браузерах вида Extension-Policy: none, который будет запрещать использовать расширения которые имеют право вмешиваться в текущий Origin, хотя бы на конкретных страницах

  • Конечно же, это все должно работать origin-based и быть устойчивым к фишингу

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

© Habrahabr.ru