Přenos dat po HTTP
Jedním z hlavních omezení při provádění útoku DoS na sedmé (aplikační) vrstvě je počet souběžných spojení na transportní vrstvě. Každé spojení s sebou nese náklady v podobě zátěže, včetně paměti operačního systému pro záznamy soketů a vyrovnávací paměti, času procesoru pro TLS handshake a také každého spojení, které potřebuje jedinečnou čtveřici informací: dvojici IP adresy a portu pro každou stranu spojení. Tyto náklady vždy omezují počet souběžných spojení mezi dvěma IP adresami.
V prastarém protokolu HTTP/1.1 se požadavky zpracovávají postupně. Server přečte požadavek, zpracuje jej, vypíše klientovi odpověď a teprve poté přečte a zpracuje další požadavek. V praxi to znamená, že rychlost požadavků, které lze odeslat přes jedno spojení, odpovídá jednomu požadavku za cestu tam a zpět. To zahrnuje zpoždění sítě, dobu zpracování serverem a dobu zpracování požadavku backendem. Některé implementace klientů a serverů implementují pipelining protokolu HTTP/1.1, který zvyšuje propustnost spojení. Běžní klienti ho ale nepoužívají.
Proudy mění pravidla
Moderní protokol HTTP/2 používá „proudy“ (stream), jakési obousměrné abstrakce používané k přenosu různých typů zpráv nebo mezi koncovými body. Multiplexování proudů je základní funkcí protokolu HTTP/2, která umožňuje efektivnější využití každého spojení TCP. Využívá jediné spojení na čtvrté vrstvě (TCP), které je využito k přenosu mnoha různých objektů v jednu chvíli. To umožňuje klientům mít rozpracovaných více požadavků, aniž by zároveň bylo třeba spravovat více jednotlivých připojení k serveru.
Díky protokolu HTTP/2 může klient otevřít více souběžných datových proudů na jednom připojení TCP, přičemž každý datový proud odpovídá jednomu požadavku HTTP. Maximální počet souběžně otevřených proudů je řízen serverem, ale v praxi mohou klienti otevřít 100 proudů na jeden požadavek a servery tyto požadavky zpracovávají paralelně.
Klient tak může například otevřít 100 proudů a odeslat požadavek na každý z nich v rámci jedné cesty. Klient pak může otevírat další datové proudy v okamžiku, kdy obdrží odpovědi na ty předchozí. To dává efektivní propustnost pro jedno spojení 100 požadavků na jednu cestu tam a zpět s podobnými časy jako u původních požadavků HTTP/1.1. To obvykle vede k téměř stonásobně intenzivnějšímu využití každého spojení.
Útok HTTP/2 Rapid Reset
Protokol HTTP/2 umožňuje klientům oznámit serveru, že předchozí proud má být zrušen, odesláním zprávy RST_STREAM
. Protokol nevyžaduje, aby klient a server zrušení nějak koordinovali, klient to tedy může provést jednostranně. Klient může také předpokládat, že zrušení se projeví okamžitě, jakmile server zprávu obdrží, tedy ještě před zpracováním jakýchkoli dalších dat z daného spojení TCP.
Toho využívá útok s názvem Rapid Reset, protože spočívá ve schopnosti koncového bodu odeslat zprávu RST_STREAM
bezprostředně po odeslání samotného požadavku, čímž server zahájí potřebnou akci a poté požadavek rychle resetuje. Akce se zruší, ale spojení HTTP/2 zůstane otevřené.
Realizace takového útoku je velmi jednoduchá: klient najednou otevře velký počet proudů jako při standardním volumetrickém útoku na HTTP/2, ale místo čekání na každou odpověď okamžitě každý požadavek zase zruší.
Možnost okamžitého resetu proudu umožňuje mít rozjeté nekonečné množství požadavků. Díky explicitnímu rušení požadavků totiž útočník nikdy nepřekročí limit počtu současně otevřených proudů. Počet rozjednaných požadavků totiž v takovou chvíli nezávisí na době přenosu (RTT), ale pouze na dostupné šířce pásma.
Pro server ovšem zrušené požadavky stále znamenají spoustu práce, musí se například alokovat nové datové struktury pro proud, analyzovat dotaz, provést dekompresi hlavičky a namapovat adresa URL. V případě použití reverzního proxy serveru může být požadavek předán na backendový server ještě před zpracováním zprávy RST_STREAM
, což způsobí zátěž i na dalších prvcích infrastruktury.
Problém je, že klienta odesílání požadavků nestojí prakticky nic. Rychlé zrušení požadavku navíc znamená, že klient ani nedostává žádnou odpověď, což pěkně šetří jeho vlastní přenosové pásmo. Tím vzniká zneužitelná asymetrie nákladů mezi serverem a klientem.
Zmírnění dopadů
Při zjištění zneužití je potřeba uzavřít celé spojení TCP s klientem. Protokol HTTP/2 poskytuje vestavěnou podporu pro uzavírání spojení pomocí zprávy GOAWAY
. RFC definuje proces pro pomalé uzavření spojení, který zahrnuje nejprve odeslání první zprávy GOAWAY
, která nestanovuje omezení pro otevírání nových proudů, a později odeslání další, která už zakazuje otevírání dalších proudů.
Tento mechanismus postupného odmítání ale není odolný proti škodícím klientům, protože ponechává připojení příliš dlouho zranitelné a nezastavuje příchozí požadavky. Místo toho by měl být proces nastaven tak, aby okamžitě omezil vytváření datových toků.
Zbývá tedy rozhodnout, která spojení jsou zákeřná a snaží se o útok. Klient rušící požadavky není automaticky útočník, protože možnost resetu pomáhá lépe řídit zpracování požadavků. Typickými situacemi jsou případy, kdy prohlížeč již dříve požadovaný obsah nepotřebuje, protože uživatel už web opustil.
Omezení útoku může mít více podob, ale většinou se soustředí na sledování statistik připojení a používání různých metrik určení užitečnosti jednotlivých připojení. Například pokud má spojení více než 100 požadavků, přičemž více než polovina z nich byla zrušena, může být klient kandidátem na obrannou reakci. Rozsah a typ reakce závisejí na riziku pro každou platformu, ale reakce se mohou lišit, od vynucení zpráv GOAWAY
až po okamžité uzavření spojení TCP.
Útoky už probíhají
Na problém upozornily společnosti Amazon Web Services (AWS), Cloudflare a Google, které velké útoky vedené touto metodou pozorují od srpna letošního roku. Útočníci jsou schopni takto odeslat a resetovat stovky milionů požadavků za sekundu. Útok proto dostal i označení CVE-2023–44487.
Tímto útokem může být ohrožen každý, kdo na internetu poskytuje služby založené na protokolu HTTP. Zranitelné mohou být webové aplikace, služby a rozhraní API na serveru nebo proxy serveru schopném komunikovat pomocí HTTP/2. Provozovatelé by měli ověřit, že jimi provozované servery nejsou zranitelné a měli by použít záplaty k omezení dopadu tohoto typu útoku. Pokud spravujete nebo provozujete vlastní server podporující protokol HTTP/2, měli byste okamžitě aktualizovat na méně zranitelné verze, jakmile budou k dispozici.
Vývojáři webového serveru Nginx zveřejnili vlastní informace, které zahrnují i podrobnosti týkající se obrany proti útoku. Nginx spoléhá na výchozí limit keepalive, který zabraňuje tomuto typu útoku. Vytváření dalších připojení za účelem obcházení limitu odhaluje záškodníky prostřednictvím standardních nástrojů pro monitorování a varování na čtvrté vrstvě.
Vývojáři doporučují rozumná nastavení souvisejících voleb, která zmírňují dopady útoku Rapid Reset:
keepalive_requests
by mělo být ponecháno výchozí nastavení 1000 požadavkůhttp2_max_concurrent_streams
by mělo zůstat na výchozím nastavení 128 proudůlimit_conn
vynucuje omezení počtu spojení povolených od jednoho klienta – tato volba by měla být přidána s rozumným nastavením vyvažujícím výkon aplikace a bezpečnostlimit_req
vynucuje omezení počtu požadavků, které budou zpracovány v daném čase od jednoho klienta – tato volba by měla být přidána s rozumným nastavením vyvažujícím výkon aplikace a bezpečnost