Согласно документации Spring Security, для веб-сокетов SOP реализован на уровне сервера, в отличие от обычного http, где SOP реализуется браузером. Однако Spring Security также требует токен CSRF для сообщений CONNECT, чтобы гарантировать SOP. Из документации Spring:
Для любого входящего сообщения CONNECT требуется действительный токен CSRF для соблюдения политики одного и того же происхождения.
Как может произойти CSRF-атака, если SOP реализован на уровне сервера? Является ли запрос на соединение простым запросом? Даже если это так, не будет ли оно просто отклонено сервером? Насколько я знаю, изменение заголовка источника в браузере невозможно. Я также проверил эту ветку, но до сих пор не ясно, достаточно ли проверки происхождения на стороне сервера.
Любая помощь приветствуется!
Я согласен, что это может сбить с толку. Это должно было называться что-то вроде проверки происхождения на стороне сервера. Однако оно обеспечивает соблюдение того же происхождения.
Поскольку никто не смог мне ответить, я постараюсь опубликовать здесь свое обоснование того, почему проверки заголовка Origin на сервере должно быть достаточно для обеспечения безопасности веб-сокетов. Имейте в виду, что я не эксперт по безопасности/веб-сокетам. Сначала нам нужно понять, зачем нам нужен токен CSRF, когда речь идет о HTTP-запросах, и почему SOP, реализованного браузерами, недостаточно.
Браузеры не применяют SOP для простых запросов. Это означает, что запрос будет отправлен вместе с файлами cookie и обработан сервером, но ответ не будет доступен для чтения. Поскольку запрос был обработан, ущерб уже был нанесен. Чтобы преодолеть это ограничение, в качестве защитного механизма был введен токен CSRF.
Я бы сказал, что даже для http-запросов проверки Origin на стороне сервера должно быть достаточно для защиты CSRF, поскольку, если она реализована правильно, она должна блокировать запрос до начала обработки. Для веб-сокетов это должно быть еще безопаснее, поскольку работа с веб-сокетами состоит из двух этапов:
Поскольку мы проверяем происхождение на сервере, злоумышленник никогда не дойдет до шага 2, поскольку запрос будет заблокирован на шаге 1.
OWASP перенес проверку происхождения на стороне сервера в список стратегий глубокоэшелонированной защиты. Как я понял из этой ссылки, это связано с тем, что некоторые браузеры (например, IE11) в некоторых редких случаях не отправляют заголовок Origin. Очевидно, такие случаи достаточно редки, чтобы их игнорировать. Также я предполагаю, что если заголовок Origin не установлен, хорошая реализация заблокирует запрос по умолчанию (надеюсь, Spring Security это сделает).
Вы можете спросить, зачем вообще не использовать токен CSRF, если Spring Security предоставляет его «из коробки». Причина в том, что я добавил Spring Cloud Gateway перед микросервисом, использующим веб-сокеты, и реализовал безопасность (включая токен CSRF) на уровне шлюза. Однако, хотя REST API защищен (поскольку шлюз отправляет заголовок авторизации через фильтр TokenRelay, который заставляет микросервис пропускать проверку CSRF, по сути доверяя шлюзу), он не оказывает никакого влияния на веб-сокеты. Кроме того, включение безопасности веб-сокетов в микросервисе активирует токен CSRF, но запросы не будут выполнены, так как я отправляю токен CSRF шлюза (существует два отдельных репозитория токенов: один для шлюза и один для микросервиса). Я, вероятно, добавлю еще один вопрос только по этой теме. Как следствие, я был вынужден отключить токен CSRF для веб-сокетов и задаться вопросом, действительно ли он необходим.
Политика одинакового происхождения реализуется браузерами, а не серверами. Описывать любые ограничения, реализуемые сервером, как «политику одного и того же происхождения» сбивает с толку; этот отрывок из документации Spring ошибочен.