Как изменилась жизнь интернет-безопасников с приходом QUIC? IDS и threat analysing в реалиях HTTP/3

от автора

Архитектура QUIC и что это такое вкратце

Как многие уже знают, QUIC — разработка гугла, новый протокол для передачи гипертекста на базе UDP (вместо TCP+TLS в HTTP/2). Он улучшил скорости загрузки сайтов, привнес более качественное и более полное шифрование данных, однако не остался без изъянов.
Стоит сделать отступление, упомянув, что одной из больших проблем HTTP/2 был TCP, который работает благодаря упорядоченной доставке байтового потока, что означает что при потере хотя бы одного пакета данных, каждый последующий должен ожидать переотправления. Само собой в условиях высокой потери пакетов скорость передачи данных страдает настолько, что даже предшественник HTTP/2 (т.е. HTTP/1.1) обгоняет своего последователя. Заменив TCP на UDP и обернув шифрование (TLS) в QUIC, данная проблема решается. Помимо прочего, с помощью внедрения идентификаторов соединения(CID), пакеты имеют идентификацию, не привязанную к IP/порту что гарантирует бесшовную миграцию соединения

Основные фичи QUIC

  • Потоковое восстановление потерь пакетов

    QUIC использует систему потоков для передачи данных, причём каждый поток обрабатывает потерю пакетов самостоятельно. Все важные для сохранности и безопасности данных операции также происходят на уровне потоков (упорядочивание, перенаправление, контроль количества данных, шифрование) что позволяет не блокировать полностью соединение при потере пакетов.

  • Встроенный TLS 1.3

    В QUIC шифрование вшито в транспортный уровень, соответственно нет необходимости в отдельном TLS handshake, как это было раньше

  • Миграция подключения

    Традиционные TCP соединения привязаны к четырём параметрам (IP/port источника и получателя), из-за чего при любой смене IP (WiFi -> mobile переключение или VPN) ломается соединение, рукопожатие происходит заново и портится ощущение пользователя

  • 0-RTT connection и 1-RTT handshake

    1-RTT

    • Шаг 1 (Клиент -> Сервер): Клиент отправляет пакет Initial. Он содержит параметры транспорта QUIC и приветственное сообщение TLS (ClientHello), включая поддерживаемые алгоритмы шифрования и публичный ключ (Key Share).

    • Шаг 2 (Сервер -> Клиент): Сервер отвечает пакетами Initial и Handshake. Он присылает свои транспортные параметры, Server Hello, свой публичный ключ, сертификат и подтверждение проверки. 0-RTT При предыдущем успешном подключении сервер выдаёт клиенту Session Ticket (или resumption PSK — Pre-Shared Key) + необходимые параметры (включая transport parameters) что позволяет сразу начать отправлять полезную нагрузку, игнорируя рукопожатие и ускоряя работу сервиса

А одной из важнейших фич HTTP/3 является его преимущество в скорости над предшественниками В моих опытах HTTP/3 показал 31.7 миллисекунд от тайминга отправки инициализирующего пакета до payload, а HTTP/2 в свою очередь 61.7 мс Тесты были проведены curl на google.com (на cloudflare.com результат схожий), несколько раз, результат усреднён.

По данным cloudflare в 2020 году для NA региона HTTP/3 обгонял HTTP/2 на 12.4% Стоит учитывать что из-за распространнёности и долгого времени на рынке, было придумано очень много ухищрений для ускорения HTTP/2

Насколько уже популярен HTTP/3 и нужен ли он бизнесу

  • По данным w3techs, новый протокол применяется уже 40% сайтов Среди клиентов cloudflare уже 20.5% трафика используют HTTP/3 по данным на 2024 год.

  • По поводу необходимости — сказать сразу трудно, но есть основные критерии по которым принимается решение.

    • Переход на QUIC связан с дополнительной нагрузкой на оборудование

    • При работе в обстановке с преобладанием внутренних быстрых сетей оптимизации которые делает протокол будет слишком несущественны

    • 0-RTT handshake может создать риск POST replay-attacks, бэкенд должен будет уметь обрабатывать заголовок Early-Data и защищать неидемпотентные операции.

Хочу также упомянуть интересную статью на тему важности latency для сервисов, а также более подробные сравнения методик ускорения сервисов и разницы между HTTP/2 vs. HTTP/3

IDS в эру QUIC

Наконец затронем основную тему данной статьи — изменения которые претерпели или должны претерпеть системы обнаружения злоумышленников и как поменялся анализ угроз

Что было раньше? фингерпринтинг на HTTP/2

Прежде чем расписывать конкретные техники, стоит явно ввести разделение, на котором всё держится: есть фингерпринтинг на уровне TLS/TCP-хендшейка (доступен любому, кто видит трафик — пассивному IDS на сетевом периметре) и фингерпринтинг на уровне самих HTTP/2-фреймов (доступен только той стороне, которая терминирует TLS — то есть серверу, edge-узлу CDN, или MITM-прокси с инспекцией трафика).

JA3 / JA3S — фингерпринтинг по TLS ClientHello/ServerHello

Даже в TLS 1.3 сообщение ClientHello передаётся в открытом виде (это нужно серверу для выбора сертификата/ALPN до того, как ключи согласованы) — соответственно, любой пассивный наблюдатель (Zeek, Suricata, корпоративный NIDS) может его прочитать без расшифровки. JA3 берёт из ClientHello версию TLS, список cipher suites, список расширений (extensions), эллиптические кривые и их форматы точек — конкатенирует их в определённом порядке и хеширует MD5. Получается короткий хеш, который уникален для конкретной комбинации TLS-библиотеки + её версии + способа конфигурации (а не для конкретного пользователя или сайта). JA3S — то же самое, но для ServerHello, то есть фингерпринт самого сервера/сервиса. JA3 фингерпринтит не браузер и не пользователя, а конкретную реализацию TLS-стека. Curl, Python requests, OpenSSL, BoringSSL (Chrome), wolfSSL — у каждого свой характерный набор cipher suites и порядок extensions, и поэтому свой устойчивый JA3-хеш.

Практическое применение JA3 в IDS

Детект C2-трафика малвари — многие семейства малвари используют статически слинкованные/кастомные TLS-библиотеки, которые дают уникальный, неизменный JA3-хеш независимо от домена, на который они стучатся. Это позволяло строить блок-листы JA3-хешей известных C2-фреймворков, даже если домен и IP меняются, фингерпринт стека остаётся тем же. Обнаружение несоответствия UA и стека — если в HTTP-заголовке User-Agent написано “Chrome 120 на Windows”, а JA3 соответствует урезанному набору cipher suites от Python urllib или curl — это сильный сигнал, что трафик генерируется скриптом, а не браузером (используется и для антибот-систем, и для выявления скрытой автоматизации в корпоративной сети). Детект TLS-инспекции/MITM — корпоративные прокси с расшифровкой трафика (forward proxy с собственным CA) сами выступают TLS-клиентом к внешнему серверу, и их JA3 отличается от JA3 оригинального браузера. Это используется как индикатор, что трафик проходит через инспектирующий узел (актуально и для атакующих, которые ищут такие узлы, и для защитников, которые легитимно деплоят такие прокси).

HTTP/2-специфичный фингерпринтинг

Второй подход — смотреть уже на сами фреймы отправленные после установления TLS сессии, то есть отправленные зашифрованным каналом. Этот метод эксклюзивен для анализа с доступом к расшифрованным H2-фреймам, например может применяться CDN/edge-провайдерами типо cloudflare и т.п. Основные источники сигнала это параметры фрейма SETTINGS (их обычно шесть — HEADER_TABLE_SIZE, ENABLE_PUSH, MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE, MAX_FRAME_SIZE, MAX_HEADER_LIST_SIZE — и их конкретные значения и порядок перечисления уникальны для конкретного HTTP-клиента/библиотеки) начение приращения в первом WINDOW_UPDATE, наличие и параметры PRIORITY-фреймов (зависимости и веса потоков — браузеры расставляют их по-разному в зависимости от типа ресурса), а также порядок псевдозаголовков (:method, :scheme, :authority, :path) и особенности использования HPACK (какие заголовки кодируются через статическую таблицу, в каком порядке).

Достойно упоминания

C примерно 2023 года в Chrome и других браузерах порядок TLS-extentions начали перемешивать чтобы было сложнее цензурировать сеть и фингерпринтить (злоумышленникам, ну или всем кроме самого гугла =) ). После этого появился JA4, он сам сортирует список дополнений не теряя в информативности. Злоумышленники также умеют имитировать чужие фингерпринты и прятать свои, но об этом как-то в следующий раз.

По сути, вcё упомянутое выше строилось на одном основном принципе — незашифрованности TCP-handshake и ClientHello/ServerHello что естественно очень на руку не только экспертам, анализирующим трафик но и пользователям с чуть менее благородными целями

QUIC и что он поменял

QUIC работает на UDP, который сам по себе практически не содержит полезной информации, а поверх него — заголовок QUIC, предварительно зашифрованный. Многие “старые” методы анализа теряют смысл, ведь единственное что остаётся перехватчику трафика — UDP-порт, длины пакетов и тайминги. Или нет? Это ни что иное как заблуждение — на самом деле узнать о соединении можно многое, даже если это соединение по QUIC.

  1. Несмотря на то, что основная информация действительно зашифрована и классический глубокий анализ пакетов (DPI), который полагался на парсинг TCP-флагов (SYN/ACK), номеров последовательности и открытых метаданных TLS, с QUIC больше не работает, нужно учесть что в протоколе QUIC есть два типа заголовков: Long Header (длинный) и Short Header (короткий). На этапе установления соединения (Handshake) используется открытый Long Header. Из него перехватчик может напрямую прочитать:

    • Версию QUIC

    • Идентификаторы соединения (Destination & Source Connection IDs) — уникальные токены, которые позволяют отслеживать сессию, даже если у пользователя изменился IP-адрес (например, при переключении с Wi-Fi на LTE).

  2. Хотя пакеты установления соединения (Initial Packets) формально зашифрованы, ключи для их расшифровки статичны и прописаны прямо в тексте стандарта RFC 9000/9001. Любой сетевой шпион (или ТСПУ в РФ, или Великий китайский файрвол) может на лету взять эти публичные ключи (ну или уже сидеть с готовыми ключами), расшифровать CRYPTO-фрейм первого пакета и прочитать SNI (Server Name Indication) — то есть точное доменное имя сайта, на который идет пользователь. Однако! эту проблему решает ECH(Encrypted Client Hello), обеспечивающий дополнительное шифрование Init пакета, подробнее про него тут

  3. В коротких заголовках QUIC (которые идут во время передачи данных) есть один незашифрованный бит, называемый Spin Bit. Он специально оставлен открытым для сетевых инженеров. По тому, как этот бит меняет значение (0 или 1) при прохождении пакетов туда-назад, перехватчик на линии может с ювелирной точностью вычислять RTT (время задержки сети) для конкретного пользователя, не зная содержимого пакетов. А такая уязвимость позволяет (при достаточно большом и разнообразном количестве данных) даже выяснить приблизительное местоположение пользователя

  4. Современные DPI системы также используют различные алгоритмы для анализа структуры потока. Страница конкретного сайта (например, главная страница Википедии) генерирует уникальный «рисунок» из размеров пакетов и пауз между ними при загрузке картинок и скриптов. С вероятностью более 90% ML-модель может угадать, какое видео на YouTube вы смотрите или какую статью читаете, просто анализируя этот паттерн. Зашифрованный протокол передачи данных уязвим для атак класса «фингерпринтинг сайтов» (Website Fingerprinting, WFP), если злоумышленники могут вычислить посещаемые пользователем веб-страницы путем мониторинга канала связи.Поскольку QUIC шифрует данные, цели злоумышленников смещаются на незашифрованные пакеты этапа установления соединения (handshake). Более того, так как QUIC основан на модели «запрос-ответ», он позволяет атакующим разделять трафик, относящийся к разным веб-ресурсам, из-за относительно фиксированной последовательности рендеринга страниц в браузере. Это снижает преимущества конфиденциальности, достигаемые за счет шифрования, в условиях WFP-атак. источник

Фингерпринтинг QUIC

С приходом TLS 1.3 и массовым внедрением QUIC (HTTP/3) классический JA3 стал стремительно устаревать. В конце 2023 года компания FoxIO представила стандарт JA4, который кардинально меняет подход. В отличие от JA3, который генерировал MD5-хеш всей строки, JA4 строит модульный, частично human-readable фингерпринт, состоящий из трех компонентов, разделенных дефисами. JA4 не чувствителен к технологиям рандомизации. Современные браузеры (например, Chrome) активно используют механизмы GREASE (случайные мусорные значения в параметрах) и постоянно меняют порядок следования TLS-расширений при каждом новом соединении. Из-за этого у одного и того же браузера в JA3 получались сотни разных хешей, чтобы избавиться от этой проблемы JA4 перед фингерпринтингом очищает параметры от GREASE-значений и сортирует расширения по алфавиту. Это позволяет получить стабильный, уникальный и легко анализируемый отпечаток криптографического стека приложения.

Анатомия отпечатка JA4

Возьмем как пример отпечаток q13d0315h3_55b375c5d22e_dc5437974b47 Это отпечаток полученный мной при запросе через firefox и zen браузеры, причём zen является firefox-based браузером, из-за чего отпечатки у них одинаковые Здесь мы видим

  • q — указатель на протокол QUIC, если бы был TCP, стояла бы буква t

  • 13d0315h3 — метаданные (как и буква q, стоит упомянуть), это самое полезное для нас

    • 13 — версия TLS (TLS 1.3)

    • d — означает что домен указан и SNI либо не зашифрован, либо зашифрован публично-доступными ключами, так как по какой-то причине не использовалась технология ECH

    • 03 — количество Cipher Suits, то есть клиент отправивший запрос предложил серверу всего 3 варианта шифрования (так как в TLS 1.3 вырезали старые алгоритмы)

    • 15 — Количество переданных клиентом TLS-расширений

    • h3 — указатель на прикладной протокол затребованный клиентов внутри приветствия

  • 55b375c5d22e — хэш шифров, 12 первых символов SHA-256 хэша от отсортированных по возрастанию хэш-кодов алгоритмов шифрования переданных в пакете. Данный хэш будет уникален для каждого уникального набора алгоритмов шифрования.

  • dc5437974b47 — хэш расширений, то есть опять первые 12 символов от SHA-256 хэша переданных клиентом расширений. Благодаря сортировке, данный хэш остаётся узнаваемым даже если браузер перемешивает расширения при отправке пакета. (сортировка происходит по алфавиту, если вдруг интересно)

В качестве сравнения JA4 отпечаток полученный от Chromium q13d0311h3_55b375c5d22e_653d80c3fe9d
Как можно заметить, отличий не так много, однако Chromium передал на 4 расширения меньше, и хэш расширений естественно отличается, а вот набор алгоритмов шифрования — одинаковый, как и сами алгоритмы.

Website-фингерпринтинг

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

  • Каждый сайт и каждая страница это уникальный набор картинок, скриптов, текста и так далее

  • Браузер всегда запрашивает эти элементы в определённой последовательности

  • На выходе получается уникальный временной паттерн, со всплесками и падениями сетевой активности (так как скорость загрузки разных элементов отличается)

  • Теперь алгоритм может сравнить этот паттерн с базой данных известных сайтов и определить посещаемый пользователем сайт

Важная ремарка

Уже указанная мною статья (на английском языке) является очень увлекательной и сильной работой наших коллег, которую я очень рекомендую к изучению, в ней описаны основные виды атак с QUIC и его проблемы с приватностью, читать тут

Проблемы IDS и как их решают

Новой головной болью систем обнаружения угроз стала миграция подключения, ведь если одно логическое соединение, оставаясь привязанным к Connection ID будет менять IP/port в течении своей жизни, классические NIDS, которые раньше трекали сессии по 5-tuple (src ip, dst ip, src port, dst port, protocol), такую миграцию увидят как два разных, никак не связанных потока — то есть стейтфул-анализ (например, детект аномального количества запросов с одного клиента, rate limiting, поведенческий анализ) ломается, если система не умеет коррелировать по CID.

Однако, данная проблема может отчасти быть решена, например введением корреляции по CID, как уже сделали например Suricata. Конечно для такого нововведения требуются повышенные мощности, так как при зашифрованном трафике (коим и является трафик QUIC, причём CID шифруется и меняется на новые, используя зашифрованные фреймы NEW_CONNECTION_ID при неизменном подключении) сигнатурный анализ опирается на заголовки, хэши и специальные правила, включая QUIC Keywords

Но проблемы на этом не заканчиваются, ведь очень часто при переходе на новую версию прилетает огромное количество ошибок “failed decrypt”. Обьясняется это переменным отсутствием ключей расшифровки сообщений, что приводит к ложным срабатываниям по нескольким причинам:

  1. Suricata, работая в режиме пассивного IDS/IPS, перехватывает трафик «на лету». Без интеграции с сервером (через файлы логов SSLKEYLOGFILE) или без использования MitM-прокси (Man-in-the-Middle) у сетевого сенсора физически нет сессионных ключей для дешифрации.

  2. В QUIC маскируются даже номера пакетов и некоторые флаги. Suricata пытается применить базовые алгоритмы декомпрессии и демаскирования (используя публичные соли для конкретных версий QUIC), но если сессия уже перешла в защищенный режим (Short Header), парсер выдает ошибку.

  3. Если Suricata из-за высокой нагрузки на интерфейс пропускает хотя бы один пакет с началом TLS-рукопожатия, она теряет контекст криптографической сессии и не может разобрать последующую структуру, что выкидывает failed decrypt.

  4. Некоторые браузеры могут использовать нестандартные расширения QUIC или вышеупомянутые механизмы GREASE чтобы путать детекторы.

Иногда это можно решить настроив Suricata, иногда приходится блокировать UDP-порты, а также данные слова применимы и к другим NIDS в большей или меньшей степени.

0-RTT replay атака

QUIC предоставляет возможность обрабатывать полезные данные начиная с первого же пакета, используя PSK (ключи с прошлой сессии), которые в свою очередь не имеют Forward Secrecy на момент отправки, в следствие чего злоумышленник может реплаить перехваченный 0-RTT пакет до того как установится полноценное соединение пакет дважды, атакующий может повторно выполнить неидемпотентный запрос.

Для современных систем IDS/WAF это порождает новый класс правил и логики детекта, работающий на двух уровнях:

  • При работе на WAF уровнях система должна не только валидировать корректность пакета, но и учитывать контекст его доставки, так как данные со служебной пометкой Early-Data: 1, не должны содержать в себе неидемпотентных операций. В ином случае IDS может классифицировать это как аномалию и возвращать требование придти через новое, безопасное соединение.

  • Пассивные же IDS, которые трекают Initial пакеты по определённым транспортным параметрам и CRYPTO фреймам должны маркировать аномальные всплески Initial пакетов с одинаковым криптографическим профилем направленных на один и тот же защищенный эндпоинт.

Заключение?

Подводя итоги, которые я скорее назвал бы промежуточными, стоит упомянуть что далеко не все атаки и методы их обнаружения были упомянуты и огромное количество нюансов и технологий остаётся за гранью данного разбора. Однако, мой вывод из сего исследования: IDS столкнулся с повышенными требованиями к производительности с приходом HTTP/3 и новые сложности вынуждают делать систему контроля трафика более изощренной, пассивные IDS проводят куда больше вычислений и дешифрования на своей стороне, а WAF-системы теперь более уязвимы к ложным срабатываниям и также выполняют больше операций.

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

ссылка на оригинал статьи https://habr.com/ru/articles/1060624/