"Краткость - сестра таланта" - именно так сказал Антон Павлович Чехов, и теперь говорю я. Сегодня, завтра и до конца дней площадки речь пойдет о WebSocket-ах: "Что это?", "Как работает?" и главное - "Как это взламывать?" (в целях этичного хакинга конечно). Начнем с простого и будем идти к более сложному, пробираясь через тернии к звёздам. Приятного чтения.

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

Оглавление


Начнем с основ

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

Протокол имеет две схемы URI:

  • ws: / host [: port] path [? query] для обычных соединений.

  • wss: / host [: port] path [? query] для туннельных соединений TLS.

Вот основные характеристики и особенности WebSocket:

  1. Установка соединения: WebSocket начинается с установки соединения через HTTP (обычно используется стандартный порт 80 или защищенный порт 443). После успешной установки соединения клиент и сервер могут обмениваться данными в реальном времени;

  2. Двусторонняя связь: WebSocket поддерживает как отправку данных от клиента к серверу, так и от сервера к клиенту. Это позволяет строить интерактивные веб-приложения, где клиент и сервер могут обмениваться информацией без задержек;

  3. Низкая задержка: WebSocket обеспечивает низкую задержку (лаг) по сравнению с традиционными методами долгого опроса (long polling) или периодическими запросами;

  4. Протокол на основе кадров (frame-based protocol): Данные в WebSocket упаковываются в кадры (frames), что делает их эффективными для передачи и обработки;

  5. Поддержка защиты (Security): WebSocket может использовать шифрование для обеспечения безопасности передаваемых данных, используя wss:// вместо ws:// в URL;

  6. Поддержка разных типов данных: WebSocket позволяет передавать различные типы данных, включая текст, бинарные данные и даже произвольные объекты;

  7. Событийная модель: WebSocket использует событийную модель для обработки входящих данных. Это означает, что Вы можете реагировать на события, такие как открытие соединения, получение сообщения или закрытие соединения.

Пример использования WebSocket:

  1. Установка соединения:

    • Клиент отправляет HTTP-запрос на сервер с заголовком "Upgrade: websocket".

    • Если сервер поддерживает WebSocket, он возвращает HTTP-ответ с заголовком Upgrade: websocket, и соединение переключается на WebSocket.

  2. Обмен данными:

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

  3. Закрытие соединения:

    • Клиент или сервер могут закрыть соединение по желанию, отправив специальный кадр.

Для лучшего понимания, представьте настольный теннис. Сервер периодически присылает ответ по WS с просьбой о действии - послать запрос на сервер. Если клиент отвечает до истечения тайм-аута — он подключен, если нет, то происходит разрыв соединения до следующего рукопожатия.

Я думал, что не так уж и много приложений используют WS... Как же я ошибался.

на 21.09.2023
на 21.09.2023

Давайте углубляться

Для детального понимания протокола WebSocket крайне важно знать его "строительный блок". Наиболее важные моменты упомянуты ниже.

  • Fin Bit - это фундаментальный бит WebSocket. Он автоматически генерируется при начале соединения.

  • RSV1, RSV2, RSV3 Bits - биты, зарезервированные для дальнейших возможностей.

  • Opcode является частью каждого кадра и объясняет процесс интерпретации данных полезной нагрузки конкретного кадра. Некоторые из распространенных значений Opcode - 0x00, 0x0, 0x02, 0x0a, 0x08 и многие другие.

  • Mask bit активизируется, когда один из битов установлен в 1.

WebSocket требует использования подобранного клиентом случайного ключа для всех данных полезной нагрузки. Маскирующий ключ, совмещенный с данными полезной нагрузки, помогает разделить данные полезной нагрузки в операции XOR. Это имеет большое значение с точки зрения безопасности прикладного API, поскольку маскирование позволяет предотвратить неправильную интерпретацию или отравление кэша.

Компоненты WS

Давайте подробнее разберемся в его важнейших компонентах:

Длина полезной нагрузки (Payload len)

Используется для кодирования общей длины данных полезной нагрузки в WebSocket. Payload len отображается, когда длина кодируемых данных меньше 126 байт. Если длина данных полезной нагрузки превышает 126 байт, то для описания длины полезной нагрузки используются дополнительные поля.

Masking-key

Каждый кадр, отправляемый клиентом на сервер, маскируется 32-битным значением. Маскирующий ключ отображается, когда бит маски равен 1. В случае если бит маски равен 0, маскирующий ключ будет равен нулю.

Данные полезной нагрузки (Payload data)

Всевозможные произвольные данные приложения и данные расширения называются данными полезной нагрузки. Эти данные используются клиентом и сервером для переговоров и применяются в ранних рукопожатиях WebSocket. Тут же, возникает вопрос - "А какие данные можно передавать?". WebSockets могут передавать любые типы данных, которые могут быть сериализованы в строковый или двоичный формат, включая текст, изображения и мультимедиа. Это делает их пригодными для широкого круга приложений, требующих обмена данными в реальном времени.

Как работает это рукопожатие ?

Рукопожатие — это первый шаг в общении между клиентом и сервером. Клиент и сервер для рукопожатия используют протокол HTTP, однако формат доставляемых сообщений немного различается. Не все критерии HTTP-сообщения соблюдены. Например, отсутствует заголовок Content-Length.

Сначала клиент устанавливает соединение с сервером и отправляет следующий запрос:

GET /echo HTTP/1.1  
Host: localhost:8081  
Sec-WebSocket-Version: 13  
Origin: http://localhost:8081  
Sec-WebSocket-Key: SWxvdmVjYXRzdmVyeW11Y2g=  
Connection: keep-alive, Upgrade  
Upgrade: websocket

Мы также можем спросить какая версия используется, указав любую цифру

Sec-WebSocket-Version: 16

Если сервер не может обмениваться данными с использованием указанной версии протокола WebSocket, он ответит ошибкой (например, 426 Требуется обновление), которая включает в свои заголовки заголовок Sec-WebSocket-Version со списком поддерживаемых версий, разделенных запятыми. версии протокола. Если сервер поддерживает запрошенную версию протокола, в ответ не включается заголовок Sec-WebSocket-Version.

Версия протокола WebSocket, которую клиент желает использовать при обмене данными с сервером. Этот номер должен быть самой последней версией, указанной в реестре номеров версий IANA WebSocket. Самая последняя версия протокола WebSocket — версия 13.

Соединение: Sec-WebSocket-Version, Sec-WebSocket-Key Upgrade и Upgrade: необходимы заголовки WebSocket; в противном случае сервер ответит HTTP/1.1 400 Bad Request. Вот как сервер отвечает на запрос клиента:

HTTP/1.1 101 Switching Protocols  
Upgrade: websocket  
Connection: Upgrade  
Sec-WebSocket-Accept: s3pPLMBiTxaQ3oYGazhZRuK+xOo=

Клиент генерирует заголовок Sec-WebSocket-Key как случайное 16-байтовое значение, закодированное в Base64.

Заголовки Sec-WebSocket-Key и Sec-WebSocket-Accept не используются для авторизации или поддержки сеансов; вместо этого они проверяют, что и запрос, и ответ используют протокол WebSocket. Это гарантирует, что сервер не будет принимать запросы от клиентов, не использующих WebSockets.

Если вы хотите углубиться ещё, то можете почитать Base Framing Protocol

Все сообщения клиента должны быть замаскированы. Пример сообщения «Привет, мир!» текстовое сообщение, отправленное клиенту (данные из tcpdump):

Fin: True  
Reserved: 0x0  
Opcode: Text (1)  
Mask: True  
Payload length: 14  
Masking-Key: a9292b01  
Payload: eaf7f76dcdb2ac6ed0fefx2021

Маскирование осуществляется обычным XOR с mask key. Клиент должен менять ключ для каждого передаваемого кадра. Сервер не должен маскировать свои сообщения. Пример передачи текстового сообщения "Hello world!" серверу:

Fin: True  
Reserved: 0x0  
Opcode: Text (1)  
Mask: False  
Payload length: 14  
Payload: 98658c6c7f20776f726c642021

Поскольку маскировка передаваемых сообщений не является криптографической, для сохранения конфиденциальности с WebSocket следует использовать протокол TLS и схему WSS.


Основы есть, теперь к теме "а как с ним работать?"

Я мог бы начать говорить что вот у postman есть возможность работать с WebSocket (как неожиданно ????), но я хочу рассказать про то, чем сам пользуюсь в последнее время и при написании этой статьи.

SocketSleuth

На моём телеграмм канале уже вышел краткий обзор инструмента SocketSleuth, но сейчас мы разберём его более детально.

Референс - Ссылка

Возможности SocketSleuth

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

WebSocket Connection Manager

Просмотр всех различных WebSocket-соединений, запросов на установление соединения и сообщений в Burp Suite может быть несколько утомительным. Вкладка SocketSleuth WebSocket history облегчает просмотр этой информации и позволяет сосредоточиться на соответствующих WebSocket для конкретной задачи.

Перехват сообщений WebSocket с помощью функции match & replace

Простая, но мощная функция, которой нам не хватало, - это возможность задавать правила перехвата и подбора и замены для сообщений WebSocket. Бывает очень полезно автоматически заменять заданное значение в сообщении, и SocketSleuth позволяет это делать для сообщений WebSocket.

WebSocket AutoRepeater

Такие расширения в Burp-е, как Autorize и AutoRepeater, значительно упростили автоматизированное тестирование на проблемы авторизации. Функция WebSocket AutoRepeater основана на этих расширениях и позволяет указать сокет-источник и сокет-получатель, а также направление сообщения.

Когда AutoRepeater запущен, он принимает все сообщения от сокета-источника и, если направление совпадает с конфигурацией, автоматически воспроизводит сообщение в сокете назначения.

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

WebSocket Intruder

Последней функцией, включенной в бета-версию, является WebSocket Intruder. Как и его аналог, работающий с HTTP-запросами, он призван обеспечить некоторые возможности автоматизации, которые могут быть использованы в различных сценариях, таких как перечисление скрытых методов, перебор параметров и другие необходимые действия. В начальном запуске присутствуют два типа атак злоумышленников: JSON RPC method discovery и Sniper.

А что там есть у Бурпа ?

Из коробки он тоже умеет с ними работать, хоть и не так полно, как хотелось бы.

  • Перехватывать и модифицировать сообщения WebSocket;

  • Воспроизводить и генерировать новые сообщения WebSocket;

  • Манипулировать соединениями WebSocket.

Вспомним и про Owasp Zap

Owasp ZAP может проводить автоматизированное сканирование (самое главное для нас, если он используется в пайплайне):

  • перехватывать и показывать сообщения WebSocket;

  • Устанавливать breakpoint на определенные типы сообщений WebSocket;

  • Фаззить WebSocket-сообщения;

  • Пассивно сканировать WebSocket-сообщений и выдавать предупреждения с помощью скриптов.


Уязвимости WebSocket

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

В принципе, практически любая уязвимость веб-безопасности может быть связана с WebSockets:

  • Пользовательский ввод, передаваемый на сервер, может быть обработан небезопасным образом, что приведет к таким уязвимостям, как SQL-инъекция или инъекция внешней сущности XML;

  • Некоторые "слепые" уязвимости, достигаемые через WebSockets, могут быть обнаружены только с Out-of-band Application Security Testing (OAST);

  • Если данные, контролируемые злоумышленником, передаются через WebSockets другим пользователям приложения, то это может привести к XSS или другим уязвимостям на стороне клиента.

Манипулирование сообщениями WebSocket

Большинство уязвимостей WebSocket, связанных с вводом данных, могут быть найдены и использованы путем подмены содержимого сообщений WebSocket.

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

{"message":"Hello Cat"}

Содержимое сообщения передается (опять же через WebSockets) другому пользователю чата и отображается в его браузере следующим образом:

<td>Hello Cat</td>

В этой ситуации, при условии отсутствия других средств обработки входных данных или защиты, злоумышленник может осуществить XSS-атаку, передав следующее WebSocket-сообщение:

{"message":"<img src=1 onerror='alert(document.cookie)'>"}

Манипулирование рукопожатием WebSocket

Некоторые уязвимости WebSockets могут быть найдены и использованы только путем манипулирования рукопожатием WebSocket. Эти уязвимости, как правило, связаны с недостатками проектирования, такими как:

  • Неправильное доверие к HTTP-заголовкам для принятия решений о безопасности, например, к заголовку X-Forwarded-For;

  • Недостатки в механизмах обработки сеансов, поскольку контекст сеанса, в котором обрабатываются сообщения WebSocket, обычно определяется контекстом сеанса в сообщении квитирования;

  • Поверхность атаки, создаваемая пользовательскими HTTP-заголовками, используемыми приложением.

Использование межсайтовых WebSockets

Некоторые уязвимости в безопасности WebSockets возникают, когда злоумышленник устанавливает междоменное WebSocket‑соединение с сайта, который он контролирует. Такая атака называется межсайтовой WebSocket hijacking и предполагает использование уязвимости подделки межсайтового запроса (CSRF) в рукопожатии WebSocket. Атака часто имеет серьезные последствия, позволяя злоумышленнику выполнять привилегированные действия от имени пользователя‑жертвы или перехватывать конфиденциальные данные, к которым он имеет доступ.

Как находить ?

Для выявления уязвимости WebSocket в приложении можно выполнить следующие действия:

  • Позволяет ли приложение осуществлять обмен данными с использованием ws вместо wss?;

  • Осуществляется ли проверка ввода отправляемого сообщения?;

  • Проверяется ли заголовок Origin или там можно прописать свой собственный домен? (попробуйте использовать его, если в GET-запросе нет рандомизированного CSRF-токена);

  • Возможна ли неограниченная отправка междоменных вызовов, приводящая к DoS-атакам?

Используя WebSocket-клиент, попытайтесь подключиться к удаленному WebSocket-серверу. Если соединение установлено, возможно, сервер не проверяет заголовок origin в рукопожатии WebSocket.

Ниже перечислены наиболее распространенные слабые места в системе безопасности ws:

  • Unencrypted Communications;

  • Cross-Site WebSocket Hijacking (CSRF with WebSockets);

  • Sensitive information disclosure over network;

  • Denial of Service;

  • Cross-Site Scripting.

  • IDOR/Improper Access

  • Перебор OTP

  • Подмена данных

Большое спасибо @r0hack за корректировки в даном вопросе

CSWSH

Начнем немного из далека. Впервые проблема была описана Кристианом Шнайдером в его блоге. Поскольку WebSockets не ограничены политикой SOP (Same Origin Policy) браузера, при отсутствии защитных механизмов злоумышленник может инициировать WebSocket-коммуникацию с вредоносной страницы, нацеленной на уязвимую конечную точку wss, и в итоге получить возможность двустороннего взаимодействия с сервером.

Как обнаружить?

Метод тестирования практически идентичен JSON Hacking. Просто проверьте, можете ли вы установить WebSocket-соединение с сайта, отличного от сервиса, путем манипулирования заголовком Origin в веб-запросе Upgrade.

GET /connect HTTP/1.1
Upgrade:WebSocket
Origin: attacker.site.com
Connection: keep-alive, Upgrade
Upgrade:WebSocket

Эксплуатация

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

function editProfile(cswshSocket) {
  var msg = {
    type: "editProfile",
    name: "attacked",
    profile_image: "https://~~~",
  };
  cswshSocket.send(JSON.stringify(msg));
}

function getUserInfo(cswshSocket) {
  var msg = {
    type: "userInfo"
  };
  cswshSocket.send(JSON.stringify(msg));
}

cswshSocket.onopen = function (event) {
  // Отредактируйте информацию о пользователе или воспользуйтесь кнопкой
  editProfile(cswshSocket)

  // Импорт данных или использование
  getUserInfo()
};

cswshSocket.onmessage = function(event) {
  console.log(JSON.parse(event.data))
}

"Bypass protection"

Конечно, ваш сервис может проверять заголовок Origin. Однако его можно обойти, используя те же доверенные домены, строки и т.д., что и при обычном перехвате JSON.

Origin: attacker.site.com
Origin: trust_domain.site.com
Origin: *

Инструменты для автоматизированного тестирования

  • Wstest- Инструмент командной строки для тестирования реализаций WebSocket, поддерживающий различные сценарии тестирования WebSocket, включая тестирование на наличие уязвимостей, которые могут быть использованы для CSWH;

  • SockJS-Client - Библиотека JavaScript для создания WebSocket-клиентов, которые могут быть использованы для автоматизации тестирования на уязвимости CSWH;

  • WS-Attacker - Инструмент для тестирования безопасности WebSocket, включающий набор атакующих модулей для тестирования уязвимостей, которые могут быть использованы для CSWH;

  • Gauntlt - Платформа тестирования безопасности с открытым исходным кодом, включающая набор инструментов для проведения автоматизированного тестирования. Функциональность тестирования WebSocket в Gauntlt может быть использована для проверки уязвимостей, которые могут быть использованы для CSWH;

  • Zap-WebSocket - Дополнение к OWASP ZAP, включающее функциональность тестирования WebSocket для проверки на наличие уязвимостей, которые могут быть использованы для CSWH.


Заключение

Вот, что я знаю и что было в моих многочисленных заметках. Подготовленный материал поможет Вам с пониманием, поиском и эксплуатацией уязвимостей WS в Вашей нелёгкой работе пентестера, AppSec-а или бб-хантера. И ещё раз, спасибо за потраченное время, жду дополнения в комментарии, ведь Мы стараемся заработать денег сделать интернет немножечко безопаснее. ^-^

P.S. Больше подобной информации и хороших мемов Вы сможете найти тут

Комментарии (0)