Передача токенов через URL часто возникает как побочный результат упрощённых решений: разработчик добавляет параметр в адрес для быстрого доступа к защищённому ресурсу или авторизации пользователя. Например:
https://example.com/dashboard?token=eyJhbGciOiJIUzI1NiIsInR5cCI6...
или
https://example.com/reset-password?accessToken=abc123xyz
На первый взгляд это выглядит удобно: ссылка самодостаточна, не требует дополнительных запросов, легко пересылается. Однако именно это свойство и создаёт фундаментальную проблему — URL является публичным носителем данных.
URL участвует во множестве процессов, которые выходят за пределы приложения:
Каждый из этих этапов увеличивает поверхность атаки. Даже если пользователь не делится ссылкой напрямую, токен уже может оказаться в сторонней системе.
Один из самых недооценённых механизмов утечки — заголовок Referer. При переходе по ссылке браузер может отправить полный URL текущей страницы на внешний ресурс.
Пример сценария:
Пользователь открывает страницу:
https://site.com/dashboard?token=SECRETНа странице загружается изображение или скрипт с внешнего домена.
Браузер отправляет запрос:
Referer: https://site.com/dashboard?token=SECRETВ этот момент токен покидает систему без ведома пользователя и может быть сохранён на стороне стороннего сервера.
URL сохраняется в нескольких местах локально:
Если устройство используется несколькими пользователями или подвергается компрометации, токен становится доступным посторонним лицам.
Особенно критично это для публичных или корпоративных устройств, где контроль над профилем браузера ограничен.
Практически любой веб-сервер по умолчанию логирует полный URL запроса. Это означает, что токен может попасть в:
Даже если доступ к логам ограничен, это всё равно увеличивает число потенциальных точек компрометации.
При использовании CDN или reverse proxy URL также проходит через промежуточные узлы. Многие из них сохраняют метаданные запросов для диагностики и кеширования.
Если токен находится в query-параметрах, он автоматически становится частью этих данных.
Главная проблема заключается не в том, что “его могут украсть”, а в том, что он по определению не предназначен для хранения секретов.
URL:
Токен же:
Совмещение этих двух сущностей приводит к нарушению базовой модели безопасности.
/reset?token=...
Часто такие ссылки отправляются по email. Проблема в том, что почтовые клиенты могут:
Некоторые реализации передают токен напрямую в redirect URL:
/callback?token=...
Это упрощает обработку, но делает токен доступным для всех промежуточных слоёв.
Например:
/file/download?token=...
Подобный подход часто используется вместо подписанных URL, но без ограничений по утечке.
Распространённое заблуждение заключается в том, что HTTPS защищает токен в URL.
HTTPS защищает только транспорт между клиентом и сервером, но не:
Таким образом, токен остаётся уязвимым уже после расшифровки на клиенте.
Authorization: Bearer <token>
Токен не попадает в URL и не участвует в логировании адресов.
Токен хранится в cookie с флагами:
Это предотвращает доступ через JavaScript и снижает риск утечки через URL.
Если требуется использовать ссылку, безопасный вариант выглядит так:
Пример:
/download?id=123&signature=HMAC(...)
На уровне архитектуры проблема часто возникает из-за стремления:
Но безопасность не должна следовать за удобством реализации. Токен — это элемент аутентификации, а не параметр маршрутизации.
Если токен находится в URL, он автоматически становится:
Этого достаточно, чтобы считать его скомпрометированным в любой системе с реальными требованиями безопасности.
Даже если каждый отдельный источник утечки кажется незначительным, в совокупности они позволяют:
URL с токеном становится стабильным идентификатором, который выходит за рамки первоначального запроса.
При проектировании веб-приложений важно разделять:
Любой секрет, помещённый в URL, автоматически перестаёт быть секретом в строгом смысле.