Токен в URL: почему это опасно

Как токены оказываются в адресной строке

Передача токенов через URL часто возникает как побочный результат упрощённых решений: разработчик добавляет параметр в адрес для быстрого доступа к защищённому ресурсу или авторизации пользователя. Например:

https://example.com/dashboard?token=eyJhbGciOiJIUzI1NiIsInR5cCI6...

или

https://example.com/reset-password?accessToken=abc123xyz

На первый взгляд это выглядит удобно: ссылка самодостаточна, не требует дополнительных запросов, легко пересылается. Однако именно это свойство и создаёт фундаментальную проблему — URL является публичным носителем данных.


Где именно “утекает” токен

URL участвует во множестве процессов, которые выходят за пределы приложения:

  • хранится в истории браузера
  • попадает в логи веб-сервера
  • фиксируется прокси-серверами и CDN
  • отправляется в заголовке Referer при переходах
  • сохраняется в аналитических системах
  • может быть записан расширениями браузера

Каждый из этих этапов увеличивает поверхность атаки. Даже если пользователь не делится ссылкой напрямую, токен уже может оказаться в сторонней системе.


Referer-заголовок как скрытый канал утечки

Один из самых недооценённых механизмов утечки — заголовок Referer. При переходе по ссылке браузер может отправить полный URL текущей страницы на внешний ресурс.

Пример сценария:

  1. Пользователь открывает страницу:

    https://site.com/dashboard?token=SECRET
  2. На странице загружается изображение или скрипт с внешнего домена.

  3. Браузер отправляет запрос:

    Referer: https://site.com/dashboard?token=SECRET

В этот момент токен покидает систему без ведома пользователя и может быть сохранён на стороне стороннего сервера.


Кэширование и история браузера

URL сохраняется в нескольких местах локально:

  • история браузера
  • автодополнение адресной строки
  • резервные копии профиля браузера

Если устройство используется несколькими пользователями или подвергается компрометации, токен становится доступным посторонним лицам.

Особенно критично это для публичных или корпоративных устройств, где контроль над профилем браузера ограничен.


Логи серверов и инфраструктуры

Практически любой веб-сервер по умолчанию логирует полный URL запроса. Это означает, что токен может попасть в:

  • access-логи Nginx или Apache
  • логи балансировщиков нагрузки
  • APM-системы (Datadog, New Relic и аналоги)
  • системы мониторинга и трассировки

Даже если доступ к логам ограничен, это всё равно увеличивает число потенциальных точек компрометации.


CDN и промежуточные сервисы

При использовании CDN или reverse proxy URL также проходит через промежуточные узлы. Многие из них сохраняют метаданные запросов для диагностики и кеширования.

Если токен находится в query-параметрах, он автоматически становится частью этих данных.


Почему токен в URL — архитектурная ошибка

Главная проблема заключается не в том, что “его могут украсть”, а в том, что он по определению не предназначен для хранения секретов.

URL:

  • предназначен для идентификации ресурса
  • должен быть безопасен для логирования
  • может быть свободно передан третьим сторонам
  • не контролируется приложением после формирования

Токен же:

  • является секретом
  • должен быть ограничен по времени
  • должен иметь строгий контроль доступа
  • должен храниться в защищённой среде

Совмещение этих двух сущностей приводит к нарушению базовой модели безопасности.


Типичные сценарии, где ошибка встречается чаще всего

Сброс пароля

/reset?token=...

Часто такие ссылки отправляются по email. Проблема в том, что почтовые клиенты могут:

  • предварительно загружать ссылки (link preview)
  • проксировать содержимое через свои серверы
  • сохранять URL в логах безопасности

OAuth и редиректы

Некоторые реализации передают токен напрямую в redirect URL:

/callback?token=...

Это упрощает обработку, но делает токен доступным для всех промежуточных слоёв.

Временные доступы к ресурсам

Например:

/file/download?token=...

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


Почему HTTPS не решает проблему

Распространённое заблуждение заключается в том, что HTTPS защищает токен в URL.

HTTPS защищает только транспорт между клиентом и сервером, но не:

  • браузерную историю
  • серверные логи
  • Referer-заголовки при переходах
  • сторонние сервисы, встроенные в страницу

Таким образом, токен остаётся уязвимым уже после расшифровки на клиенте.


Более безопасные альтернативы

Заголовки авторизации

Authorization: Bearer <token>

Токен не попадает в URL и не участвует в логировании адресов.


HttpOnly cookies

Токен хранится в cookie с флагами:

  • HttpOnly
  • Secure
  • SameSite

Это предотвращает доступ через JavaScript и снижает риск утечки через URL.


Подписанные одноразовые ссылки

Если требуется использовать ссылку, безопасный вариант выглядит так:

  • короткий срок жизни
  • одноразовое использование
  • привязка к IP или устройству
  • минимальный объём данных в URL

Пример:

/download?id=123&signature=HMAC(...)

Ошибки при проектировании API

На уровне архитектуры проблема часто возникает из-за стремления:

  • упростить клиентскую часть
  • избежать хранения состояния на сервере
  • использовать “stateless” подход без учёта угроз

Но безопасность не должна следовать за удобством реализации. Токен — это элемент аутентификации, а не параметр маршрутизации.


Практическая модель угроз

Если токен находится в URL, он автоматически становится:

  • публичным (через Referer и логи)
  • долговечным (через историю браузера)
  • неконтролируемым (после передачи пользователю)
  • воспроизводимым (может быть скопирован и использован повторно)

Этого достаточно, чтобы считать его скомпрометированным в любой системе с реальными требованиями безопасности.


Часто игнорируемый аспект: агрегация данных

Даже если каждый отдельный источник утечки кажется незначительным, в совокупности они позволяют:

  • восстановить сессию пользователя
  • связать действия между сервисами
  • построить профиль активности
  • осуществить несанкционированный доступ

URL с токеном становится стабильным идентификатором, который выходит за рамки первоначального запроса.


Практика безопасного проектирования маршрутов

При проектировании веб-приложений важно разделять:

  • идентификаторы ресурсов (URL)
  • данные аутентификации (headers/cookies)
  • служебные параметры (query без секретов)

Любой секрет, помещённый в URL, автоматически перестаёт быть секретом в строгом смысле.