Перейти к основному содержанию
Вход по QR-коду можно переслать: атакующий начинает вход в своём браузере и уговаривает сотрудника его подтвердить. Внутреннему приложению — интранету, бэк-офису, панели администратора — вход из-за пределов компании не нужен. Если начинать вход можно только из сети офиса или через VPN, у атакующего снаружи нет QR-кода для пересылки. Сотрудники по-прежнему подтверждают вход в мессенджере, и телефону не нужно подключаться к сети офиса. Veriqa и ваше приложение менять не нужно: ограничение вы задаёте на обратном прокси, и оно работает на текущей версии.

Что вы реализуете сами

  1. Составьте список сетей. Диапазоны офиса и пул адресов VPN, IPv4 и IPv6. Включайте только сети, доступ к которым вы контролируете: управляемое устройство, подключение к VPN, пропуск в здание.
  2. Ограничьте /connect/authorize на прокси. Вход начинает только этот маршрут. Пример для NGINX с условными диапазонами. Добавьте этот блок рядом с конфигурацией со страницы «За reverse-proxy»:
    Veriqa принимает этот маршрут в любом регистре и с косой чертой в конце, и блок совпадает с теми же вариантами пути: ~* не различает регистр, а /? допускает косую черту. Точный location = пропустил бы /CONNECT/AUTHORIZE через общий location /. Строка запроса на совпадение не влияет. Если Veriqa стоит под префиксом пути, включите префикс в выражение и разрешите ему повторяться: ^(/auth/veriqa)+/connect/authorize/?$. Когда общий блок обрезает префикс, запрос /auth/veriqa/auth/veriqa/connect/authorize доходит до Veriqa как /auth/veriqa/connect/authorize, и Veriqa принимает его за этот маршрут. Регулярные выражения NGINX проверяет по порядку, поэтому поставьте этот блок перед остальными блоками location ~. Проверьте, что этот путь не покрывает блок location ^~ или location =: тогда NGINX регулярные выражения не проверяет. В этом блоке proxy_pass передаёт путь без изменений, потому что внутри location с регулярным выражением NGINX не принимает URI в proxy_pass. Veriqa принимает и путь с префиксом, даже если ваш общий блок префикс обрезает. Адрес укажите тот же, что в общем блоке, например тот же upstream, чтобы запросы доходили до экземпляров так же, как остальные.
  3. Остальные маршруты оставьте открытыми. Телефон открывает страницы под /auth/ и /r/ через мобильный интернет, мессенджеры вызывают вебхуки под /api/channels/, а ваш бэкенд обращается к /connect/token оттуда, где он работает. Страницу входа и её WebSocket открывает браузер, который уже прошёл проверку. Маршрутами под /connect/authorize/callback пользуется и телефон: например, через них он отправляет форму, которая запрашивает недостающее поле профиля. Поэтому их не ограничивайте; блок выше с ними не совпадает.
  4. Проверяйте адрес клиента. NGINX сверяет адрес того, кто к нему подключился. Если перед NGINX стоит балансировщик или CDN, сначала восстановите адрес клиента из заголовка, который они передают, директивами set_real_ip_from и real_ip_header модуля realip. Иначе NGINX увидит у всех запросов адрес балансировщика и пропустит или отклонит их все разом. На стороне Veriqa доверие к самому прокси задаёт раздел ForwardedHeaders — см. шаг 6 самостоятельной установки.
  5. Объясните человеку отказ. За пределами ваших сетей браузер получает ответ 403. Покажите вместо этого ответа свою страницу (error_page 403 в том же location), где сказано, что вход работает только из сети офиса или через VPN.

Почему это работает

Пересылка QR-кода начинается с того, что браузер атакующего открывает страницу входа. За пределами ваших сетей этот браузер вместо страницы получает 403, и пересылать нечего. Чтобы начать вход, атакующему нужно устройство внутри сети — в RFC это сказано так: «the attacker needs to have access to a device on the network». В терминах BCP 247 это мера Trusted Networks (RFC 10027 §6.1.8). Список хранится в вашем прокси, а не в Veriqa, поэтому на странице «Veriqa, BCP 247 и модель угроз» эта мера отмечена как не покрытая в ядре, а за тем, что можно сделать уже сейчас, страница ведёт сюда. По тому же списку сетей можно выбирать поверхность в сценарии «Место и личность».

На что обратить внимание

  • Правило действует на все приложения этого экземпляра Veriqa. Маршрут /connect/authorize у них общий. Какое приложение начинает вход, прокси узнаёт только из параметра запроса client_id. Записать этот параметр можно по-разному, поэтому правило прокси по нему легко обойти. Если один экземпляр Veriqa обслуживает и внутреннее, и публичное приложение, выделите внутреннему свой экземпляр, со своим именем хоста и issuer.
  • Для приложений, которыми пользуются ваши клиенты, это не подходит. Ваши клиенты входят из сетей, которые вы не контролируете; RFC сам называет это ограничением.
  • Сеть надёжна ровно настолько, насколько защищён доступ к ней. Гостевой Wi-Fi в том же диапазоне, личное устройство в VPN или вредоносная программа на офисном компьютере уже внутри. RFC советует сочетать эту меру с другими (§6.1.8, SHOULD), например со сценарием «Passkey вместе с Veriqa».
  • Удалённая работа — через VPN. Сотрудник вне офиса входит только с включённым VPN, и сбой VPN останавливает и его вход.