HTTP 2 – kompresja danych oraz atak CRIME

HTTP 2.0 jak wiemy z poprzedniego już wpisu jest protokołem binarnym. Wiemy również, że fundamentalne zasady działania HTTP nie zostały zmienione. Oznacza to, że HTTP pozostaje protokołem bezstanowym.  To z kolei w praktyce oznacza, że każde zapytanie musi dostarczać wszelkie informacje potrzebne do odtworzenia stanu aplikacji. Powoduje to, że zarówno ciało zapytania jak i nagłówek po jakimś czasie mogą zawierać dużo informacji, które należy przesyłać w każdym zapytaniu.

Kompresja danych, dostarczona w HTTP 2.0  jest kolejnym usprawnieniem poprawiającym wydajność, a w szczególności opóźnienie. HTTP 2.0 dostarcza również kompresje nagłówków, co kompletnie nie było dostępne w HTTP 1.1 (była możliwość jedynie kompresji ciała).

Kompresja HTTP 2.0 jest również odporna na atak CRIME (Compression Ratio Info-leak Made Easy), na który był podatny nawet klasyczny HTTPS czy poprzednik HTTP 2.0, a mianowicie SPDY. Jak to możliwe, że HTTPS, który jest szyfrowany może cierpieć na niebezpieczny atak ze względu na dodaną kompresję danych?

Jak sama nazwa wskazuje, atak polega na monitorowaniu rozmiaru skompresowanej treści. Prawdopodobnie dodając trochę treści, rozmiar musi się zmienić. Pomimo, że całość jest szyfrowana, to naturalnie rozmiar pakietu jest całkowicie jawny – to informacja, którą atakujący może wykorzystać.

W jaki sposób zatem przedstawiony atak może wyglądać? Załóżmy, że chcemy odgadnąć szyfrowany identyfikator sesji. Gdzieś w ciele zapytania musi być  przechowywana wartość np. “sessionId=252”. Jednym z fragmentów, które możemy kontrolować jest typ i adres zasobu dla zapytań. Jeśli chcemy wysłać GET do strony głównej wtedy zapytanie będzie wyglądać następująco:

GET /home

Wyobraźmy sobie, że wysyłamy jednak  najpierw poniższy pakiet

GET /sessionId=9

Oczywiście cały czas monitorujemy rozmiar pakietu. Następnie kolejny pakiet to:

GET /sessionId=2

Co możemy dowiedzieć się z rozmiarów wysłanych pakietów? Czy będą miały identyczny rozmiar? Jeśli kompresja jest użyta, drugi pakiet (sessionId=2) będzie mniejszy niż pierwszy, ponieważ sessionId=2 występuje już w ciele zapytania, które zawiera sekretny identyfikator sesji. Algorytmy kompresji, w dużym skrócie polegają na zastępowaniu duplikatów pewnymi wskaźnikami – np. skrótami. Naturalne zatem, że po kompresji ciąg  znaków “AABB” będzie miał mniejszy rozmiar niż “ABCD”. Metodą prób i błędów modyfikujemy zatem pakiet (w tym przypadku adres zasobu), aby rozmiar całości redukował się. Jeśli dodanie kolejne cyfry sesji zwiększa rozmiar, to znaczy, że takowa cyfra nie występuje w zaszyfrowanym ciele i stąd kompresja nie przynosi skutków. Jeśli rozmiar jest mniejszy, pewne fragmenty pakietu się powtarzają i oznacza to dla nas, że odgadliśmy kolejną cyfrę.

Widzimy, że przechwycenie zaszyfrowanego pakietu, zawierającego numer sesji może być niebezpieczne dla użytkownika. Pomimo, że nie mamy szans rozszyfrować pakietu, to bazując na rozmiarze możemy spróbować odtworzyć analogiczny pakiet. Podsumowując, do przeprowadzenia CRIME musimy:

  • posiadać próbkę pakietu, zawierającego sekretne dane (np. identyfikator sesji).
  • kompresja danych musi być włączona
  • należy wstrzyknąć pewną treść, np. za pomocą adresu zasobu.

W przypadku HTTP 1.1, polecane jest aby wyłączyć kompresje danych zarówno po stronie klienta (przeglądarka internetowa) jak i serwera. HTTP 2.0 nie jest podatny na ten typ ataku.

Leave a Reply

Your email address will not be published.