Почему для WebSockets нет политики одинакового происхождения? Почему я могу подключиться к ws: // localhost?

86

Я хотел бы использовать WebSockets для межпроцессного взаимодействия моего приложения (Daemon <-> WebGUI и Daemon <-> FatClient и т. Д.). Во время тестирования я попытался подключиться к моему локально работающему серверу веб-сокетов (ws: // localhost: 1234) через клиент JavaScript WebSocket на websocket.org ( http://www.websocket.org/echo.html ).

У меня вопрос:
почему это возможно? Не реализована ли в браузерах политика перекрестного происхождения (здесь: FF29 в Linux)?

Я спрашиваю, потому что, если websocket.org был злом, он мог бы попытаться связаться с моим локальным WS-сервером и перенаправить каждое сообщение, которое он получает от localhost, на любой другой сервер:

Браузер локального сервера WebSocket Злой веб-сервер
на ws: // localhost: 1234 на http: //evil.tld
        | | |
        | | ------ [GET /] ---------> |
        | | <----- [HTML + EvilJS] ---- |
        | <------ [подключить ws: // ..] ---- | |
        | <---- [немного общения] -> | |
        | | ---- [злой вперед] ----> |
        | | |

Я не тестировал весь вариант использования, но подключение к ws: // localhost из JS, предоставленного websocket.org, определенно работает.

binwiederhier
источник
2
websocket.org не должен быть злом, веб-сокеты могут быть;)
kuldeep.kamboj

Ответы:

52

Для решения вопроса "Почему?" Частично причина, по которой браузеры не применяют политику одного и того же происхождения (из которой CORS является ослаблением) для WebSockets, в отличие от вызовов AJAX, заключается в том, что WebSockets были введены после того, как значение запросов между источниками было установлено, и потому что они ' Если SOP изначально не распространяется, историческая причина проверок на стороне клиента CORS неприменима.

Для AJAX, во времена общей политики единого происхождения, серверы никогда не ожидали, что аутентифицированный браузер отправит запрос из другого домена 1 , и поэтому не нужно было гарантировать, что запрос поступает из надежного места 2 , просто проверьте файл cookie сеанса. Более поздние ослабления, такие как CORS, должны были иметь проверки на стороне клиента, чтобы избежать злоупотребления существующими приложениями , нарушая это предположение (эффективно выполняя CSRF-атаку ).

Если бы Интернет изобрели сегодня, зная то, что мы знаем сейчас, для AJAX не потребовались бы ни SOP, ни CORS, и возможно, что вся проверка была бы оставлена ​​на сервере.

WebSockets, являясь более новой технологией, с самого начала предназначены для поддержки междоменных сценариев. Любой, кто пишет серверную логику, должен знать о возможности запросов из разных источников и выполнять необходимую проверку без необходимости жестких мер предосторожности на стороне браузера, как CORS.


1 Это упрощение. Запросы GET между источниками для ресурсов (включая теги <img>, <link> и <script>) и запросы POST на отправку форм всегда разрешались как фундаментальная функция Интернета. В настоящее время также разрешены вызовы AJAX с разными источниками, запросы которых имеют одинаковые свойства, и их называют простыми запросами с перекрестными источниками . Однако доступ к возвращенным данным из таких запросов в коде не разрешен, если явно не разрешено заголовками CORS сервера. Кроме того, именно эти «простые» запросы POST являются основной причиной того, почему для серверов необходимы токены защиты от CSRF для защиты от вредоносных веб-сайтов.

2 На самом деле, безопасный способ проверки источника запроса даже не был доступен, поскольку Refererзаголовок может быть подделан, например, с помощью уязвимости открытого перенаправления. Это также показывает, насколько плохо тогда были изучены уязвимости CSRF.

Staafl
источник
6
Это действительно ответ на вопрос, так что +1. Но, для протокола, я категорически не согласен с этим рассуждением. Я предсказываю, что в результате этого проектного решения значительное количество сайтов, использующих WebSockets, не смогут проверить Originзаголовок и в результате утечка личных данных пользователя на сторонние сайты. Клиенты, проверяющие Access-Control-Allow-Originзаголовок, как они это делают перед тем, как разрешить JS-доступ к ответам на любой другой HTTP-запрос из разных источников в Интернете, были бы простым способом предотвратить весь этот класс атак (Cross-Site WebSocket Hijacking). Слишком поздно.
Ajedi32 02
3
Я склонен согласиться с тем, что изменение дизайна, по сути, заключается в переходе от подхода на основе белого списка к подходу, основанному на черном списке, что рискованно. Честная оценка.
staafl 03
43

Оберстет ответил на вопрос . Спасибо! К сожалению, я не могу отметить его как «правильный», потому что это был комментарий. Браузер отправляет заголовок «origin», который может проверяться приложением.

В Java [1]:

@Override
public void onOpen (WebSocket clientSocket, ClientHandshake рукопожатие) {
    Строка clientOrigin = handshake.getFieldValue ("origin");

    if (clientOrigin == null ||! clientOrigin.equals (WEBSOCKET_ALLOWED_ORIGIN_HEADER)) {
        logger.log (Level.WARNING, «Клиент не отправил правильный заголовок источника:» + clientOrigin);        

        clientSocket.close ();
        возвращение;
    }

    // ...
}

[1] с использованием https://github.com/TooTallNate/Java-WebSocket

binwiederhier
источник
1
OWASP упоминает проверку заголовка Origin (и, возможно, Referer) в своей шпаргалке по CSRF как первый и самый важный шаг, но они также рекомендуют пойти дальше и реализовать защиту, специфичную для CSRF. В случае WebSockets это может быть добавление токена защиты от подделки XSRF к URI WS в качестве параметра запроса и его проверка на стороне сервера после проверки происхождения.
Кевин Секрист
19

WebSockets может взаимодействовать между доменами, и они не ограничены SOP (Same Origin Policy).

Та же проблема безопасности, которую вы описали, может возникнуть без WebSockets.

Злой JS может:

  • Создайте тег сценария / изображения с URL-адресом evil.tld и поместите данные в строку запроса.
  • Создайте тег формы, поместите данные в поля и вызовите действие формы «отправить», выполнив HTTP POST, который может быть перекрестным. AJAX ограничен SOP, но обычный HTTP POST - нет. Проверьте проблему веб-безопасности XSRF.

Если что-то внедряет javascript на вашу страницу или вы получаете вредоносный javascript, ваша безопасность уже нарушена.

втортола
источник
1
Меня не беспокоит злой JS. Я знаю, что это всегда возможно. Что меня действительно беспокоит, так это прорыв браузера: теперь любой веб-сайт может связываться с локально привязанным сокетом WS и красть данные оттуда.
binwiederhier
54
SOP / CORS не применяется к WebSocket, но браузеры будут отправлять originзаголовок, содержащий имя хоста сервера, который обслуживал HTML с JS, открывшим соединение WebSocket. Затем сервер WebSocket может ограничить доступ, проверив origin.
Оберстет
Это не отвечает на вопрос. Возник вопрос, почему веб-страница из другого домена может получить доступ к локальному WebSocket. В сценарии OP нет ничего, что «вставляет javascript на вашу страницу» - это другой сценарий. Без WebSocket удаленная веб-страница не смогла бы читать ресурсы на localhost, потому что это именно то, что SOP предотвращает.
sleske