Что такое маска в фрейме WebSocket?

Я работаю над реализацией websocket и не знаю, что такое смысл маски в кадре.

может кто-нибудь объяснить мне, что он делает и почему это рекомендуется?

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
 | |1|2|3|       |K|             |                               |
 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
 |     Extended payload length continued, if payload len == 127  |
 + - - - - - - - - - - - - - - - +-------------------------------+
 |                               |Masking-key, if MASK set to 1  |
 +-------------------------------+-------------------------------+
 | Masking-key (continued)       |          Payload Data         |
 +-------------------------------- - - - - - - - - - - - - - - - +
 :                     Payload Data continued ...                :
 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
 |                     Payload Data continued ...                |
 +---------------------------------------------------------------+

2 ответов


Websockets определены в RFC6455, который заявляет в 5.3:

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

на запись в блоге о Websockets Я нашел следующее объяснение:

masking-key (32 бита): если бит маски установлен (и поверьте мне, это если вы пишете для на стороне сервера) вы можете прочитать здесь неподписанные байты, которые используются для xor полезной нагрузки. он используется для обеспечения того, чтобы дерьмовые прокси не могли злоупотреблять злоумышленниками со стороны клиента.

но самый четкий ответ я нашел вархив списка рассылки. Там Джон Тэмплин заявляет:

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

Как заявил kmkaplan, вектор атаки описан в 10.3 RFC.
Это мера для предотвращения прокси атаки отравления кэша (см. бумага об атаке). То, что он делает, создает некоторую хаотичность. Вы должны XOR полезной нагрузки со случайным ключом маскировки.

кстати: это не просто рекомендуется. Это обязательное.


с в этой статье:

маскировка трафика WebSocket от клиента к серверу требуется из-за маловероятной вероятности того, что вредоносный код может привести к тому, что некоторые сломанные прокси-серверы сделают что-то не так и используют это как атаку. Никто не доказал, что это действительно может произойти, но поскольку тот факт, что это может произойти, был достаточной причиной для поставщиков браузеров, чтобы получить дерганый, маскировка была добавлена, чтобы удалить возможность ее использования в качестве атака.

таким образом, предполагая, что злоумышленники смогли скомпрометировать как код JavaScript, выполненный в браузере, так и бэкэнд-сервер, маскировка предназначена для предотвращения последовательности байтов, отправленных между этими двумя конечными точками, созданными особым образом, который может нарушить любые сломанные прокси между этими двумя конечными точками (сломанные это означает прокси, которые могут попытаться интерпретировать поток websocket как HTTP, когда на самом деле они не должны).

браузер (и не код JavaScript в браузере) имеет последнее слово на случайно сгенерированной маске, используемой для отправки сообщения, поэтому злоумышленники не могут знать, какой конечный поток байтов может увидеть прокси.

обратите внимание, что маска является избыточной, если ваш поток WebSocket зашифрован (как и должно быть). статьи от автора Python's Flask:

Почему вообще маскировка? Потому что, по-видимому, есть достаточно сломанных инфраструктура, которая позволяет заголовку обновления пройти, а затем обрабатывает остальную часть соединения как второй HTTP-запрос, который затем загружается в кэш. У меня нет слов для этого. В любом случае, защита от этого в основном является сильным 32-битным случайным числом в качестве ключа маскировки. Или вы знаете ... используйте TLS и не используйте дерьмовые прокси.