Akademia protokołów – #2 JA4 + Encrypted Traffic Analysis

Encrypted Client Hello

Encrypted Client Hello może zamknąć pewną epokę podglądania ruchu sieciowego. Przez lata SNI był tym jednym polem, które zostawało w plaintext nawet po całym zaciskaniu pętli przez TLS – i na nim opierała się cała selektywna dekrypcja ruchu sieciowego. To po SNI firewall decydował, czy w ogóle deszyfrować sesję, to on pozwalał kategoryzować ruch i omijać MITM tam, gdzie polityka tego zabraniała (np. bankowość, zdrowie). ECH szyfruje inner ClientHello razem z SNI i tym samym zabiera ostatni dostępny sygnał o intencji połączenia. Naturalny wniosek, który wyciąga większość ludzi, brzmi: skoro nie widzę już SNI i nie dekryptuję, to jestem ślepy. I właśnie z tym wnioskiem chcę w tym wpisie polemizować. Brak dekrypcji to nie to samo co brak widoczności. Treść znika, ale sposób, w jaki klient się przedstawia, i kształt, jaki przyjmuje ruch na „drucie”, zostają – i da się z nich wyciągnąć zaskakująco dużo. To jest jedna z opcji ochrony organizacji jeśli dekrypcja ruchu nie może zostać zastosowana. Ta metoda nie daje 100% pewności co do przesyłanego ruchu, ale pozwala z dużym prawdopodobieństwem określić czy ruch może być szkodliwy czy jednak nie.

Dlaczego fingerprinting w ogóle działa

Sedno sprowadza się do jednej obserwacji: fingerprint nie mówi co przesyłasz, tylko czym to przesyłasz, jak często to przesyłasz. Identyfikuje implementację i stos aplikacji klienta, a nie treść sesji – i dlatego działa to nawet przy pełnym szyfrowaniu zawartości (payload). Mechanizm jest prosty i wynika z tego, jak musi wyglądać negocjacja: zanim ustali się wspólny klucz, klient wysyła ClientHello otwartym tekstem, bo inaczej obie strony nie mogłyby uzgodnić parametrów połączenia. A ten ClientHello to kopalnia „metadanych” czy raczej cech implementacyjnych takich jak: wersje protokołu, lista szyfrów (cipher suites), zestaw i kolejność rozszerzeń, deklarowane ALPN, wspierane grupy krzywych. Różne biblioteki i różne przeglądarki układają to po swojemu, często na tyle charakterystycznie, że sam kształt handshake’u zdradza, czy po drugiej stronie siedzi Chrome, OpenSSL, Go czy jakiś custom client. To właśnie ten odcisk kondensuje JA4.

Dla zobrazowania można odwiedzić stronę AmIUnique i zobaczyć jak bardzo unikalny w sieci jest odcisk naszej przeglądarki internetowej, na który mogą się składać np.: user-agent, rozdzielczość ekranu, akceptowane języki, strefa czasowa czy nawet specyficzny sposób generowania grafik przez nasze urządzenie. Tak też firmy reklamowe mogą śledzić użytkowników. Choć w tym przypadku nie jest wykorzystywany fingerprinting JA4 to zasada działania jest podobna.

Tu pojawia się pytanie, które w kontekście ECH trzeba postawić wprost: skoro ECH szyfruje ClientHello, to czy nie zabija też fingerprintingu? Nie – i to jest kluczowy niuans. ECH szyfruje inner ClientHello, czyli tę część z prawdziwym SNI i wrażliwymi parametrami. Ale żeby połączenie w ogóle doszło do skutku, na zewnątrz wędruje outer ClientHello, który dalej jest widoczny i dalej niesie swój własny zestaw cech negocjacyjnych. Mówiąc inaczej: ECH odebrał Ci wgląd w to, do jakiej usługi klient się łączy, ale nie w to, jakim stosem aplikacyjnym się łączy. Wciąż istnieje możliwość wykonania fingerprintu na Outer handshake. Co więcej, sama obecność ECH i to, jak klient go „składa”, staje się kolejną cechą – ruch korzystający z ECH to na dziś wciąż mniejszość, więc paradoksalnie sama informacja „ten klient używa ECH” bywa jasnym sygnałem. Fingerprinting przeżywa ECH, bo celuje w zupełnie inną warstwę informacji niż ta, którą ECH chroni.

JA4+ jako rodzina, nie pojedynczy hash

Pierwsza rzecz, którą trzeba odkłamać, to samo słowo „fingerprint” w liczbie pojedynczej. JA3 przyzwyczaił wszystkich do myślenia w kategoriach jednego hasha na połączenie – policz skrót z parametrów ClientHello i masz odcisk klienta. JA4+ porzuca to na rzecz całej rodziny skorelowanych fingerprintów, z których każdy patrzy na inny fragment tej samej sesji. To mała zmiana podejścia: zamiast jednego sygnału, na który system ma opierać decyzję, dostajesz zestaw sygnałów, które nabierają sensu dopiero zestawione razem.

Z perspektywy sieciowca warto wiedzieć, co realnie jest w tym pudełku. JA4 to odcisk klienta TLS – następca właściwego JA3. JA4S opisuje odpowiedź serwera, czyli jak druga strona odpowiada na negocjację; parując JA4 z JA4S masz już charakterystykę całej pary klient–serwer, a nie tylko inicjatora. JA4H bierze na warsztat żądanie HTTP – nagłówki i ich układ. JA4X liczy się z certyfikatu X.509. JA4L szacuje dystans/latencję hopu, co pomaga lokalizować realne źródło ruchu. JA4T i JA4TS schodzą niżej, do parametrów TCP (klienta i serwera). Nie musisz używać wszystkich – chodzi o to, że masz do dyspozycji warstwy od TCP przez TLS po HTTP, i sam dobierasz te, które widzisz w swoim punkcie styku.

I tu jest sedno sprawy, które wymusza zrozumienie działania całego mechanizmu. Sam JA4 w izolacji potrafi być bezużyteczny jako dowód, bo miliony zupełnie legalnych klientów dzielą identyczny stos aplikacyjny – każdy świeży Chrome na danej wersji wygląda tak samo. Jeśli zablokujesz ten fingerprint po samym JA4, zablokujesz „pół internetu” :). Wartość pojawia się dopiero w korelacji: JA4 mówiący „to stos Chrome”, JA4H pokazujący nagłówki, które do Chrome nie pasują, i JA4L sugerujący, że hop jest zupełnie gdzie indziej, niż twierdzi reszta – dopiero to składa się na sygnaturę, która coś znaczy. Dlatego JA4+ warto traktować jako wejście do stosu korelacyjnego, a nie jako pojedynczy klucz, w oparciu o, który następuje decyzja czy zezwolić czy raczej zablokować dany ruch. Fingerprint to jeden głos w zespole, nie sędzia wydający wyrok. Małe live demo do przeklikania poniżej:

Co możemy zobaczyć

Cała ta teoria o warstwach fingerprintów nabiera sensu dopiero przy monitorze , gdy patrzysz na ruch, którego nie odszyfrujesz, i musisz zdecydować, co jest podejrzane. Najczęstszy i najwdzięczniejszy przypadek to malware C2 udający legalny ruch. Stały wzorzec jest taki, że implant łączy się po HTTPS, bo port 443 nikogo nie dziwi i rzadko bywa blokowany – ale pod spodem nie siedzi przeglądarka, tylko jakiś klient napisany w Go, Pythonie czy oparty o surowy OpenSSL. Dla pasywnego obserwatora treść jest zaszyfrowana i SNI może twierdzić, że to niewinna domena, ale JA4 wyliczone z outer handshake’u mówi „to nie jest stos aplikacyjny żadnej przeglądarki”. To jest dokładnie ta informacja, której ECH Ci nie odebrał.

Z powiązania tych informacji możemy uzyskać najmocniejszy sygnał: rozjazd między tym, co ruch o sobie deklaruje, a tym, czym naprawdę jest. User-Agent w nagłówku krzyczy „Chrome na Windowsie”, ale JA4 pokazuje odcisk python-requests albo curl – i to kłamstwo samo w sobie jest alertem, niezależnie od tego, co jest w ładunku. Legalny ruch nie ma powodu udawać kogoś innego na poziomie stosu. Ta sama logika łapie gotowe narzędzia ofensywne: Cobalt Strike, Sliver, rozmaite skanery i frameworki C2 mają swoje charakterystyczne profile TLS, które przy aktualnej bazie fingerprintów wyłapujesz po JA4/JA4S, zanim zdążą cokolwiek zrobić – znów bez zaglądania do treści.

Poza łapaniem złośliwego ruchu to samo narzędzie daje Ci czystą klasyfikację i inwentaryzację tego, co w ogóle pojawia się w Twojej sieci. Możesz rozpoznać aplikację i często jej wersję, odróżnić ruch generowany przez przeglądarkę od ruchu maszyna-do-maszyny, wychwycić klientów na przeterminowanych bibliotekach TLS, których nikt nie zaktualizował. W świecie bez SNI i bez dekrypcji ruchu bywa to jedyny sposób, żeby odpowiedzieć na banalne z pozoru pytanie „z kim, w ogóle nasi użytkownicy rozmawiają w Internecie”. Warto tylko pamiętać z tyłu głowy o jednej rzeczy, którą rozwinę w następnym punkcie: wszystkie te detekcje to sygnały o różnej sile, świetne do priorytetyzacji i triage’u, ale żaden z nich nie jest twardym dowodem – bo klient w pełni kontroluje swój własny handshake i może go podrobić. W prostu sposób jak np. wtyczka do przeglądarki, która zmienia User-Agenta.

Gdzie fingerprinting się kończy

Większość materiałów o JA4 urywa się tam, gdzie zaczyna się najciekawsze, czyli na pytaniu „a co, jeśli przeciwnik też to wie”. A wie. Fundamentalny problem jest wpisany w samą metodę: klient ma pełną i wyłączną kontrolę nad swoim ClientHello. Fingerprint nie jest cechą nadaną z zewnątrz, którą dałoby się niezależnie zweryfikować – to po prostu odczyt tego, co klient zdecydował się wysłać. A skoro to klient układa wersje, cipher suites i rozszerzenia, to nic nie stoi na przeszkodzie, żeby ułożył je dokładnie tak, jak robi to Chrome. W Go służy do tego biblioteka utls, która pozwala dowolnej aplikacji przyjąć wybrany profil handshake’u – i malware z niej korzysta rutynowo. Efekt jest taki, że implant, który „gołym” stosem aplikacyjnym Go świeciłby jak choinka, po owinięciu w utls przedstawia się fingerprintem nieodróżnialnym od świeżego Chrome. Spoofing JA3/JA4 nie jest trudny.

Druga grupa problemów to szum, który psuje fingerprinty nawet nieświadomie po drugiej stronie. Sztandarowy przykład to GREASE – mechanizm, w którym Chrome celowo wstrzykuje losowe, nieistniejące wartości do listy cipher suites i rozszerzeń. Dla JA3, który liczył skrót po surowej liście, oznaczało to inny hash przy w zasadzie identycznym kliencie. JA4 odpowiada na to między innymi sortowaniem rozszerzeń i odfiltrowaniem wartości GREASE, zanim policzy odcisk – i właśnie dlatego jest stabilniejszy od JA3. Ale to dobrze ilustruje charakter całej dziedziny: to wyścig zbrojeń, w którym każda strona reaguje na ruch drugiej, a fingerprint, który działa dziś, może wymagać korekty, gdy przeglądarki znów zmienią sposób składania handshake’u.

Trzecia rzecz to erozja bazy wiedzy przy przejściu na QUIC i HTTP/3. Fingerprinting tam jest możliwy i aktywnie się rozwija, ale profil jest inny niż w klasycznym TLS-over-TCP, a dojrzałość i pokrycie baz sygnatur bywają słabsze. Ruch, który migruje na QUIC, trafia więc często w obszar mniej rozpoznany – a akurat przez port 443/UDP przechodzi go coraz więcej.

Z tego wszystkiego płynie jeden wniosek, który trzeba postawić uczciwie: fingerprint to probabilistyka, nie dowód. Jest znakomity jako warstwa triage’u – do priorytetyzacji alertów, do wyłapywania tego, co „śmierdzi”, do zawężania pola, zanim sięgniesz po droższe narzędzia. Jest za to kiepski jako jedyny mechanizm blokujący, bo zmotywowany przeciwnik obejdzie go niskim kosztem. JA4 powinno się traktować jako źródło sygnału wejściowego, który podbija priorytet i uruchamia głębszą analizę ruchu, a nie jako wyroku, po którym się ten ruch odcina. I to jest dokładnie ten moment, w którym zderzamy się z granicą samego fingerprintingu handshake’u: skoro odcisk da się podrobić, a treści nie widać, to co zostaje, gdy nawet handshake przestaje być wiarygodny? Odpowiedź leży piętro niżej – w kształcie samego ruchu, niezależnym od tego, co klient o sobie deklaruje.

Encrypted Traffic Analysis

Jest warstwa, która zostaje nawet wtedy, gdy fingerprint da się podrobić, SNI zniknął, a treść jest zaszyfrowana. Encrypted Traffic Analysis nie odpowiada na pytanie „co jest w pakietach”, ale patrzy wyłącznie na metadane, które nie są szyfrowane. Rozmiary pakietów, ddstępy czasowe między nimi, kierunkowość – kto ile wysyła w którą stronę, długość i czas życia flow, wzorce, charakterystyka, bursty ruchu. Tego nie da się zaszyfrować, bo to nie jest zawartość przesyłana w kanale, tylko fizyczna charakterystyka tego, jak kanał jest używany. Klient może skłamać w każdym polu handshake’u, ale nie skłamie w tym, że co sześćdziesiąt sekund wysyła dwieście bajtów i dostaje krótką odpowiedź.

I to jest dokładnie ten przypadek, w którym ETA znajduje swoje zastosowanie – detekcja beaconingu. Implant C2 w trybie czuwania musi regularnie zgłaszać się do serwera po zadania, i ten rytm można zauważyć. Małe, periodyczne, zadziwiająco regularne flow do tego samego miejsca to może być podpis command-and-control, widoczny wyłącznie w domenie czasu. Nie ma znaczenia, że sesja jest w idealnym TLS 1.3 z ECH i sfałszowanym pod Chrome fingerprintem – metronom samego odpytywania zdradza ją niezależnie od całej reszty. To sygnał, którego żadna warstwa szyfrowania ani spoofingu handshake’u nie usuwa, bo wynika z samej logiki działania narzędzia, a nie z jego implementacji. Tak samo jak przykładem eksfiltracji dany może być nienaturalna ilość pakietów oraz rozmiar danych przesłanych za wykorzystaniem protokołu ICMP czy DNS, wewnątrz, których atakujący może zapisywać dane firmowe i wysyłać do siebie przez sieć Internet.

Podobnie z grubsza działa rozróżnianie typów ruchu i wyłapywanie eksfiltracji. Streaming wideo ma inny profil objętościowy i czasowy niż przeglądanie stron, interaktywna sesja wygląda inaczej niż masowy transfer, a tunel przepychający dane na zewnątrz zostawia charakterystyczny ślad w asymetrii i wolumenie – nagły, długi strumień w stronę wyjścia tam, gdzie normalnie klient głównie pobiera. Tu z natury rzeczy wchodzi statystyka i uczenie maszynowe, bo mówimy o klasyfikacji rozmytych wzorców, a nie o dopasowywaniu sztywnych reguł. I to jest jednocześnie największa siła i największa słabość metody: ETA operuje na poziomie „ten ruch zachowuje się jak…”, więc świetnie nadaje się do wykrywania anomalii i triage’u, ale sama z siebie rzadko daje twarde dowody. To kolejne piętro tej samej probabilistyki, o której była mowa przy fingerprintach – im mniej widzisz treści, tym bardziej schodzisz z poziomu pewności na poziom prawdopodobieństwa.

I tu właśnie dochodzimy do konkluzji: Im szczelniej zaszyfrowany ruch, tym wyżej wędrujesz po drabinie sygnałów: od treści, przez SNI, przez fingerprint handshake’u, aż po goły kształt flow – i na każdym szczeblu masz mniej pewności w zamian za widoczność, która wciąż zostaje. ETA to na ten moment ostatni szczebel, na którym da obserwować ruch i wyciągać wnioski pasywnie na drucie. Jeśli potrzebujesz czegoś więcej niż prawdopodobieństwa – a do krytycznych systemów i zadań potrzebujesz – i tak musisz wrócić do analizy treści. Tyle że skoro sieciowa dekrypcja umiera razem z SNI, QUIC-iem i ECH, to jedyne miejsce, gdzie dane wciąż są w plaintext, to samo urządzenie końcowe, tuż przed tym, zanim trafi do TLS.

Jak to robi vendor – Cisco EVE i rodzina narzędzi ETA

Dotąd mówiliśmy o ETA jako o koncepcji. Warto zobaczyć, jak to wygląda zaimplementowane w sprzęcie, który faktycznie stoi w szafie – a Cisco jest tu najlepszym przykładem, bo ma pod tym parasolem dwie różne generacje, które łatwo ze sobą pomylić.

EVE (Encrypted Visibility Engine) to nowsza rzecz, wbudowana bezpośrednio w Cisco Secure Firewall (dawny Firepower), dostępna od wersji oprogramowania 7.2 oraz wymaga SNORT wersji 3. EVE identyfikuje aplikacje i procesy klienckie korzystające z szyfrowania TLS – i robi to bez konieczności dekrypcji. Mechanizm jest dokładnie tym, co opisywaliśmy przy JA4: EVE fingerprintuje pakiet Client Hello w handshake TLS. Różnica między EVE a gołym JA4 leży w skali danych treningowych i w tym, co z fingerprintu wyciągają. Cisco przepuszcza przez machine learning ponad miliard fingerprintów TLS i ponad 10 000 próbek malware dziennie, które zbiera u swoich klientów, i z tego buduje oraz aktualizuje bazę fingerprintów EVE – te aktualizacje trafiają z powrotem do klientów jako paczki VDB (Vulnerability Database), czyli tym samym kanałem co reszta sygnatur. Efekt końcowy jest taki, że z samego Client Hello EVE potrafi wskazać proces kliencki, który zainicjował połączenie, oraz typ i wersję systemu operacyjnego klienta. Co istotne – EVE fingerprintuje ClientHello zarówno w ruchu TLS, jak i QUIC, więc migracja na HTTP/3 nie wyłącza tej metody automatycznie.

W trybie Monitor EVE wykrywa aplikacje klienckie i podnosi wskaźniki kompromitacji (IoC), a w trybie Protect dodatkowo blokuje złośliwe połączenia na podstawie skonfigurowanego progu threat score. Czyli nie jest to tylko pasywny wgląd – na podstawie oceny prawdopodobieństwa, że proces jest złośliwy, firewall potrafi od razu ciąć sesję, bez jej odszyfrowywania. I warto to w poście podkreślić uczciwie, bo sam Cisco to mówi wprost: EVE nie zastępuje dekrypcji SSL/TLS – uzupełnia istniejące mechanizmy, wyciągając metadane z samego handshake’u.

Starszy i koncepcyjnie inny jest ETA (Encrypted Traffic Analytics), który obecnie jest częścią Cisco Secure Network Analytics – i tu właśnie rodzi się pomyłka. ETA nie żyje w firewallu (choć firewall też może wysyłać dane typu Netflow/SFlow), tylko głównie w routerach i switchach z IOS-XE (Catalyst 9300/9400, routery), które eksportują wzbogaconą telemetrię do kolektora. ETA wyciąga dwa główne elementy danych: Initial Data Packet (IDP) oraz Sequence of Packet Length and Time (SPLT). To jest dokładnie ta „analiza kształtu ruchu”, o której mówiliśmy w punkcie o ETA jako koncepcji – IDP to zawartość pierwszego pakietu flow, a SPLT to sekwencja rozmiarów i czasów pakietów, czyli metronom połączenia. Te elementy są przesyłane dedykowanym protokołem NetFlow do Cisco Stealthwatch (dziś pod nazwą Secure Network Analytics), gdzie sama detekcja malware odbywa się już w chmurze Cisco, podczas gdy telemetria NetFlow i ETA jest przetwarzana lokalnie przez appliance Stealthwatch.

ETA = telemetria z infrastruktury (switch/router/firewall) + Stealthwatch + analiza w chmurze; patrzy głównie na kształt flow (IDP + SPLT); wdrażasz ją na drodze ruchu w całej sieci, także east-west.
EVE = silnik w firewallu; patrzy głównie na fingerprint Client Hello; identyfikuje proces i OS klienta, działa na brzegu/tam, gdzie stoi firewall.

W praktyce to dwa komplementarne poziomy tej samej filozofii „widoczność bez deszyfrowania ruchu” – jeden zbiera metadane przepływu z całej sieci, drugi robi głęboki fingerprint handshake’u na perymetrze sieci.

A inni vendorzy? To nie jest cisowy monopol, choć Cisco najmocniej to zbrandowało. Fingerprinting handshake’u i analiza metadanych ruchu to dziś standardowy element NGFW i NDR u większości graczy – Palo Alto, Fortinet, Zscaler czy czysto NDR-owe platformy (Darktrace, Vectra, ExtraHop) wszystkie mają warianty „inspekcji bez dekrypcji” opartej o metadane i uczenie maszynowe, pod własnymi nazwami. Nie chcę rzucać konkretnymi nazwami z pamięci, bo branding i nazwy zmieniają się szybko.

Podsumowanie

Szyfrowanie nie włącza i nie wyłącza widoczności jak przełącznik – ono przesuwa Cię w górę drabiny, na której każdy wyższy szczebel daje mniej pewności(ale, też wymaga mniej zasobów obliczeniowych) w zamian za sygnał, który wciąż zostaje. Na samym dole stała kiedyś treść – pełny wgląd do zawartości pakietu po jego odszyfrowaniu. Nad nią SNI, które pozwalało wiedzieć, dokąd klient się łączy, bez zaglądania do środka. Wyżej fingerprint handshake’u, mówiący już nie „dokąd” i „co”, tylko „czym” – jakim stosem aplikacyjnym rozmawia klient. A na samej górze goły kształt flow: rozmiary, timing, rytm, które nie znikają, bo są fizyką użycia kanału, a nie jego zawartością. TLS 1.3 zabrał pasywny wgląd w certyfikat i w klucz. ECH dołożył SNI. QUIC i ECH razem robią to samo z całym handshake’em. Każdy z tych kroków zrzuca Cię o szczebel wyżej – i za każdym razem schodzisz z poziomu dowodu na poziom prawdopodobieństwa.

I tu trzeba być uczciwym co do tego, czym to wszystko naprawdę jest. JA4, encrypted traffic analysis, EVE – to warstwa „triage”: narzędzia, które mówią „ten ruch śmierdzi”, podbijają priorytet alertu, zawężają pole i pozwalają podejmować decyzje enforcementu na podstawie oceny ryzyka zamiast pewności. Dla ogromnej części zadań – wychwycenia C2 udającego przeglądarkę, złapania beaconingu, inwentaryzacji tego, co gada na zewnątrz – to wystarcza i wystarczać będzie. Ale dla zasobów krytycznych, tam gdzie fałszywy alarm albo przeoczenie kosztują realnie, prawdopodobieństwo to za mało. Tam i tak musisz wrócić do pełnej dekrypcji ruchu.

Tyle że miejsce, w którym treść jest jeszcze dostępna w plaintext, właśnie się przenosi. Dekrypcja ruchu sieciowego na perymetrze sieci umiera razem z SNI, QUIC-iem, ECH i pinningiem – nie dlatego, że ktoś to wyłączył, tylko dlatego, że stało się to technicznie coraz trudniejsze. Jedyny punkt, w którym dane są jawne w sposób, którego nikt Ci nie zabierze, to sam endpoint – moment tuż przed tym, zanim aplikacja odda bajty do biblioteki TLS, i tuż po tym, jak je stamtąd odbierze. Dlatego logiczny ruch całej branży to analiza tegoż ruchu bezpośrednio na hoście: hooki na SSL_write i SSL_read przez eBPF, czytające plaintext, zanim w ogóle dojdzie do szyfrowania. Dla sieciowca to trochę egzystencjalny zwrot – bo oznacza, że punkt wglądu do ruchu sieciowego przesuwa się z „drutu”, który był jego domeną, na hosta, który był domeną kogoś innego. Ale to jest kierunek, w którym to wszystko zmierza.

Na koniec jedna, nadrzędna zasada: nie ma głupich pytań. A nawet jeśli jakieś pytanie jest rzeczywiście głupie, to jeszcze większą głupotą jest go nie zadać i tkwić w tejże głupocie. Uderzajcie do nas mailowo lub wbijajcie na naszego Discorda. Zapraszamy.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *