Jakiś czas temu pisałem o sposobie na limitowanie liczby żądań generowanych przez klienta: Limitowanie klienta. Chcę na chwilę wrócić do tego tematu w kontekście ochrony przed DoS.
Proof-of-work
Za dawnych czasów stanie w kolejce było sportem ekstremalnym. Na przykład pojawiała się plotka, że w sklepie będzie cukier i już pół miejscowości koczowało pod sklepem patrząc na siebie nieufnie, pilnując swojego miejsca przed tymi stojącymi dalej w kolejce jednocześnie czatując na błąd tych stojących wcześniej. Sport ten powoli zanika (aczkolwiek wciąż istnieją miejsca, gdzie kolejki mają się dobrze, a twarde łokcie i chamstwo można uznać za przystosowanie ewolucyjne do środowiska bytowania), w coraz większej ilości miejsc pojawiają się automaty z numerkami, które mają kolejki ucywilizować.
Spójrzmy na taki system kolejkowy oczyma atakującego. Co może chcieć osiągnąć? Oczywiście po pierwsze może chcieć uzyskać wcześniejszą obsługę. Mogę sobie wyobrazić sytuację, w której ktoś przychodzi z własnym, podrobionym "numerkiem". Tym razem jednak chodzi mi o sytuację, w której ktoś z czystej złośliwości chce tak zmanipulować system, by klienci nie mogli skorzystać z oczekiwanej usługi.
Jaki jest sens takiego ataku? Załóżmy, że obok siebie znajdują się dwa salony sprzedające bardzo podobny produkt/usługę. Jeśli klienci zirytują się na czas oczekiwania w jednym z salonów, być może pójdą do drugiego i to właśnie w nim taki produkt/usługę zakupią. Można wyobrazić sobie sytuację "sztucznego tłumu", ale równie dobrze może działać prostszy atak - pobranie dużej ilości numerków. Kolejne przychodzące osoby widząc ilość osób przed nimi w kolejce i szacowany czas oczekiwania (ta informacja jest zwykle nadrukowywana na numerku) mogą zrezygnować z czekania, przy okazji potęgując efekt (nie zwalniają miejsca w kolejce). Kolejka składająca się z samych duchów nie rozładuje się natychmiast. Po wyświetleniu się numerka zawsze następuje pewien czas oczekiwania na podejście klienta, dopiero po jego upływie podejmowana jest próba wezwania kolejnego oczekującego. Tu dodatkowo warto zauważyć, że w części przypadków miejsce obsługi i miejsce oczekiwania klientów są od siebie oddzielone, konsultant może nie wiedzieć, że tak naprawdę czeka tylko jeden klient, przed którym jest kilkunastu "wirtualnych".
Teraz przejdźmy do wszystkich "wirtualnych" kanałów obsługi klientów (chaty, rozmowy audio, rozmowy wideo) korzystających z Internetu. Tu również atak polegający na odmowie usługi ma sens i może powodować wymierne skutki. Czy można się przed nim jakoś bronić?
Przede wszystkim trzeba się zastanowić kiedy zasoby potrzebne do obsługi klienta są alokowane i jakie to są zasoby. Prawidłowe podejście jest takie, by na początku alokować najmniejszą możliwą pulę zasobów, pozostałe wymagane zasoby należy alokować dopiero w chwili rozpoczęcia obsługi klienta. Jeśli zasoby alokowane są "od początku", wówczas może się okazać, że atak DoS będzie prosty do przeprowadzenia - wystarczy nawiązać dużą ilość fałszywych połączeń. Zwykle jest tak, że zasoby potrzebne do obsługi takiego połączenia po stronie serwera są dużo większe, niż zasoby wymagane po stronie atakującego. W szczególnych przypadkach może zdarzyć się tak, że atakujący nie musi alokować żadnych zasobów - wywołuje w nieskończoność pierwszy krok protokołu, a serwer dla każdego takiego wywołania alokuje zasoby i czeka (prawie w nieskończoność) na kolejne kroki. Nic nowego pod słońcem, prawda?
Nawet jeśli po stronie serwera są zastosowane mechanizmy mające na celu odsunięcie w czasie alokowania zasobów i usuwania z kolejki klientów, którzy "sobie poszli", atak nadal może być możliwy - atakujący może wymagać po prostu większej ilości zasobów. I tutaj właśnie dochodzimy do sedna sprawy - jak zwiększyć koszt nawiązywania połączenia po stronie klienta (atakującego)?
Odpowiedzią może być wspomniany w tytule mechanizm proof-of-work. Chodzi o to, by przy każdej próbie połączenia klient musiał wykonać pewną pracę (kosztowną obliczeniowo), serwer natomiast powinien być w stanie zweryfikować wykonanie tej pracy bez angażowania w to większych zasobów. Przykłady takich "puzzli" znajdują się w podlinkowanym wpisie. "Uczciwy" klient dodatkowego nakładu pracy w trakcie nawiązywania połączenia prawdopodobnie nawet nie zauważy. Dla atakującego może to już być istotnym problemem, ponieważ nie będzie w stanie alokować zasobów na tyle szybko, by serwer nie nadążył ich zwalniać.
Oczywiście, atakujący może rozwiązać ten "problem" przez wykorzystanie większej ilości zasobów. Koszt takiego ataku wówczas jednak rośnie i, przynajmniej w części przypadków, przestanie on być atrakcyjny dla atakujących.