Rezumat
1. Introducere
2. Context
3. Modelul de Amenințare
4. Găsirea Gadget-urilor de Scurgere de Etichete
5. Gadget-uri TIKTAG
6. Atacuri din Lumea Reală
6.1. Atacarea Chrome
7. Evaluare
8. Lucrări conexe
9. Concluzie și Referințe
\
Pentru a demonstra exploatabilitatea gadget-urilor TIKTAG în atenuarea bazată pe MTE, această secțiune dezvoltă două atacuri din lumea reală împotriva Chrome și a kernel-ului Linux (Figura 9). Există mai multe provocări în lansarea atacurilor din lumea reală folosind gadget-uri TIKTAG. În primul rând, gadget-urile TIKTAG trebuie executate în spațiul de adrese țintă, ceea ce necesită ca atacatorul să construiască sau să găsească gadget-uri din sistemul țintă. În al doilea rând, atacatorul trebuie să controleze și să observe starea cache-ului pentru a scurge rezultatele verificării etichetelor. În continuare, demonstrăm atacurile din lumea reală folosind gadget-uri TIKTAG pe două sisteme reale: browser-ul Google Chrome (§6.1) și kernel-ul Linux (§6.2), și discutăm strategiile de atenuare.
\ 6.1. Atacarea Chrome
Browser Un browser web reprezintă o suprafață primară de atac pentru atacurile bazate pe web, deoarece procesează conținut web neautorizat, cum ar fi JavaScript și HTML. Mai întâi prezentăm modelul de amenințare (§6.1.1) și oferim un gadget TIKTAG construit în motorul JavaScript V8 (§6.1.2). Apoi, demonstrăm eficacitatea gadget-urilor TIKTAG în exploatarea browser-ului (§6.1.3) și discutăm strategiile de atenuare (§6.1.4).
\ ==6.1.1. Modelul de Amenințare.== Urmăm modelul tipic de amenințare al atacurilor asupra browser-ului Chrome, unde atacatorul urmărește să exploateze vulnerabilitățile de corupție a memoriei în procesul de randare. Presupunem că utilizatorul victimă vizitează site-ul web controlat de atacator, care servește o pagină web malițioasă. Pagina web include HTML și JavaScript create special, care exploatează vulnerabilitățile de corupție a memoriei în procesul de randare al victimei. Presupunem că toate tehnicile de atenuare de ultimă generație ale Chrome sunt implementate, inclusiv ASLR [18], CFI [15], izolarea site-ului [53] și sandbox-ul V8 [56]. În plus, ca o apărare ortogonală, presupunem că procesul de randare activează etichetarea MTE aleatorie în PartitionAlloc [2].
\ ==6.1.2. Construirea Gadget-ului TIKTAG.== În mediul JavaScript V8, TIKTAG-v2 a fost construit cu succes și a scurs etichetele MTE ale oricărei adrese de memorie. Cu toate acestea, nu am găsit un gadget TIKTAG-v1 constructibil, deoarece constrângerea temporală strânsă între BR și CHECK nu a fost fezabilă în tehnica noastră de evadare speculativă din sandbox-ul V8 (§A).
Gadget-ul V8 TikTag-v2. Figura 8 este gadget-ul TIKTAG-v2 construit în motorul JavaScript V8 și codul său pseudo-C după compilarea JIT. Cu acest gadget, atacatorul poate afla dacă eticheta ghicită Tg se potrivește cu eticheta Tm atribuită la target_addr. Atacatorul pregătește trei array-uri, slow, victim, probe, și o valoare idx. slow este un Unit8Array cu o lungime de 64 și este accesat în BR pentru a declanșa predicția greșită a ramurii. victim este un Float64Array cu lungimea 64, care este accesat pentru a declanșa forwarding-ul store-to-load. probe este un Uint8Array cu lungimea 512 și este accesat în
\ TEST pentru a scurge rezultatul verificării etichetei. O valoare idx de tip Number este utilizată în accesul în afara limitelor al victim. Valoarea idx este aleasă astfel încât victim[idx] să indice spre targetaddr cu o etichetă ghicită Tg (adică, (Tg«56)|targetaddr). Pentru a accesa speculativ target_addr în afara sandbox-ului V8, am valorificat tehnica de evadare speculativă din sandbox-ul V8 pe care am descoperit-o în timpul cercetării noastre, pe care o detaliem în §A. Linia 8 din Figura 8a este blocul BR al gadget-ului TIKTAG-v2, declanșând predicția greșită a ramurii cu slow[0].
\ Linia 12-13 este blocul CHECK, care efectuează forwarding-ul store-to-load cu victim[idx], accesând target_addr cu o etichetă ghicită Tg. Când acest cod este compilat JIT (Figura 8b), se efectuează o verificare a limitelor, comparând idx cu victim.length. Dacă idx este un index în afara limitelor, codul returnează undefined, dar dacă încărcarea câmpului victim.length durează mult timp, CPU-ul execută speculativ instrucțiunile următoare de store și load.
\ După aceea, linia 17 implementează blocul TEST, care accesează probe cu valoarea forwarded val ca index. Din nou, o verificare a limitelor pe val față de lungimea probe este precedată, dar această verificare reușește deoarece PROBEOFFSET este mai mic decât lungimea array-ului probe. Ca rezultat, probe[PROBEOFFSET] este pus în cache doar când forwarding-ul store-to-load reușește, ceea ce este cazul când Tg se potrivește cu Tm.
\ ==6.1.3. Atacul de bypass MTE Chrome.== Figura 9a ilustrează atacul general de bypass MTE asupra browser-ului Chrome cu primitiva arbitrară de scurgere de etichete a gadget-urilor TIKTAG. Presupunem o vulnerabilitate de depășire a buffer-ului în procesul de randare, unde exploatarea unei vulnerabilități temporale (de exemplu, use-after-free) este în mare parte aceeași. Vulnerabilitatea depășește un pointer (adică, vuln_ptr) către un obiect vulnerabil (adică, objvuln), corupând obiectul adiacent (adică, objtarget).
\ Cu aplicarea MTE a PartitionAlloc, cele două obiecte au etichete diferite cu o probabilitate de 14/15. Pentru a evita ridicarea unei excepții, atacatorul trebuie să se asigure că etichetele objvuln și objtarget sunt aceleași. TIKTAG-v2 poate fi utilizat pentru a scurge eticheta objvuln ( 1 ) și objtarget ( 2 ). Dacă ambele etichete scurse sunt aceleași, atacatorul exploatează vulnerabilitatea, care nu ar ridica o eroare de verificare a etichetei ( 3 ). În caz contrar, atacatorul eliberează și realocă objtarget și revine la primul pas până când etichetele se potrivesc.
\ ==Declanșarea Cache Side-Channel.== Pentru a exploata cu succes un gadget TIKTAG, atacatorul trebuie să îndeplinească următoarele cerințe:
i) antrenarea ramurii,
ii) controlul cache-ului, și
iii) măsurarea cache-ului. Toate cele trei cerințe pot fi îndeplinite în JavaScript.
În primul rând, atacatorul poate antrena predictorul de ramuri rulând gadget-ul cu slow[0] diferit de zero și idx în limite, și declanșa predicția greșită a ramurii în BR cu valoarea zero în slow[0] și idx în afara limitelor.
În al doilea rând, atacatorul poate elimina liniile de cache ale slow[0], victim.length și probe[PROBE_OFFSET] cu tehnici de eliminare a cache-ului JavaScript [8, 21, 70].
În al treilea rând, atacatorul poate măsura starea cache-ului probe[PROBE_OFFSET] cu un cronometru de înaltă rezoluție bazat pe SharedArrayBuffer [16, 58].
\ ==Exploatarea Vulnerabilităților de Corupție a Memoriei.== Date fiind etichetele MTE scurse, atacatorul poate exploata vulnerabilitățile de corupție a memoriei spațiale și temporale în renderer. Strategia de atac este în mare parte aceeași ca atacurile tradiționale de corupție a memoriei, dar trebuie să se asigure că vulnerabilitatea nu ridică o eroare de verificare a etichetei utilizând etichetele scurse. Detaliem în continuare strategia de atac în §C.
\ ==6.1.4. Atenuare.== Pentru a atenua atacurile de bypass MTE bazate pe gadget TIKTAG în procesul de randare al browser-ului, pot fi folosite următoarele atenuări:
i) Sandbox conștient de execuția speculativă: Pentru a opri atacatorii să lanseze atacuri bazate pe TIKTAG dintr-un mediu sandbox precum sandbox-ul V8, sandbox-ul poate fi fortificat prin prevenirea oricărui acces speculativ la memorie dincolo de regiunea de memorie a sandbox-ului. În timp ce browser-ele web moderne folosesc un sandbox pentru a izola conținuturile web neautorizate de renderer, adesea neglijează căile speculative.
\ De exemplu, sandbox-ul Chrome V8 [56] și sandbox-ul Safari Webkit [1] nu mediază complet căile speculative [27]. Pe baza tehnicilor actuale de compresie a pointerilor [64], căile speculative pot fi restricționate la regiunea sandbox prin mascarea biților superiori ai pointerilor.
\ ii) Bariera de speculație: Așa cum se sugerează în §5, plasarea unei bariere de speculație după BR pentru gadget-urile TIKTAG potențiale poate preveni atacurile de scurgere speculativă a etichetelor. Cu toate acestea, această atenuare poate să nu fie aplicabilă în mediul browser-ului critic pentru performanță, deoarece poate introduce un overhead semnificativ de performanță.
\ iii) Prevenirea construcției gadget-ului: Așa cum se sugerează în §5.2, gadget-ul TIKTAG-v2 poate fi atenuat prin adăugarea de instrucțiuni între instrucțiunile store și load. Un gadget TIKTAGv1, deși nu am găsit unul exploatabil, poate fi atenuat prin adăugarea de instrucțiuni între o ramură și accesele la memorie, după cum se descrie în §5.1.
\ 6.2. Atacarea Kernel-ului Linux
Kernel-ul Linux pe ARM este utilizat pe scară largă pentru dispozitive mobile, servere și dispozitive IoT, făcându-l o țintă atractivă de atac. Exploatarea unei vulnerabilități de corupție a memoriei în kernel poate escalada privilegiile utilizatorului, iar astfel MTE este un mecanism de protecție promițător pentru kernel-ul Linux. Atacurile bazate pe TIKTAG împotriva kernel-ului Linux prezintă provocări unice diferite de atacul asupra browser-ului (§6.1).
\ Acest lucru se datorează faptului că spațiul de adrese al atacatorului este izolat de spațiul de adrese al kernel-ului unde va fi executat gadget-ul. În continuare, mai întâi prezentăm modelul de amenințare al kernel-ului Linux (§6.2.1) și oferim un gadget TIKTAG proof-of-concept pe care l-am descoperit în kernel-ul Linux (§6.2.2). În final, demonstrăm eficacitatea gadget-urilor TIKTAG în exploatarea vulnerabilităților kernel-ului Linux (§6.2.3).
\ ==6.2.1. Modelul de Amenințare.== Modelul de amenințare de aici este în mare parte același ca cel al atacurilor tipice de escaladare a privilegiilor împotriva kernel-ului. În mod specific, ne concentrăm pe kernel-ul Android Linux bazat pe ARM, întărit cu protecții implicite ale kernel-ului (de exemplu, KASLR, SMEP, SMAP și CFI). Presupunem în plus că kernel-ul este întărit cu o soluție de etichetare aleatorie MTE, similară soluțiilor MTE gata de producție, Scudo [3].
\ Pentru a fi specific, fiecare obiect de memorie este etichetat aleatoriu, iar o etichetă aleatorie este atribuită când un obiect este eliberat, prevenind astfel atât corupțiile de memorie spațiale, cât și temporale. Atacatorul este capabil să ruleze un proces neprivilegiat și urmărește să își escaladeze privilegiul prin exploatarea vulnerabilităților de corupție a memoriei în kernel. Se presupune că atacatorul cunoaște vulnerabilitățile de corupție a memoriei kernel-ului, dar nu cunoaște nicio etichetă MTE a memoriei kernel-ului. Declanșarea corupției de memorie între obiectele kernel-ului cu
\ etichete nepotrivite ar ridica o eroare de verificare a etichetei, ceea ce este nedorit pentru exploatările din lumea reală. O provocare critică în acest atac este că gadget-ul trebuie construit prin reutilizarea codului kernel-ului existent și executat prin apelurile de sistem pe care atacatorul le poate invoca. Deoarece arhitectura ARMv8 separă tabelele de pagini ale utilizatorului și kernel-ului, gadget-urile din spațiul utilizatorului nu pot accesa speculativ memoria kernel-ului. Această configurație este foarte diferită de modelul de amenințare al atacului asupra browser-ului (§6.1), care a valorificat codul furnizat de atacator pentru a construi gadget-ul. Am exclus și construcția gadget-ului bazată pe eBPF [17, 28], deoarece eBPF nu este disponibil pentru procesul Android neprivilegiat [33].
\ ==6.2.2. Gadget-ul Kernel TikTag==. După cum se descrie în §4.1, gadget-urile TIKTAG trebuie să îndeplinească mai multe cerințe, iar fiecare cerință implică provocări în mediul kernel-ului.
În primul rând, în BR, o predicție greșită a ramurii ar trebui declanșată cu cond_ptr, care ar trebui să fie controlabil din spațiul utilizatorului. Deoarece procesoarele AArch64 recente izolează antrenamentul de predicție a ramurilor între utilizator și kernel [33], antrenamentul ramurii trebuie efectuat din spațiul kernel-ului.
În al doilea rând, în CHECK, guessptr ar trebui dereferențiat. guessptr ar trebui creat din spațiul utilizatorului astfel încât să includă o etichetă ghicită (Tg) și să indice spre adresa kernel-ului (adică, target_addr) pentru a scurge eticheta (Tm). Spre deosebire de mediul JavaScript al browser-ului (§6.1), datele furnizate de utilizator sunt puternic sanitizate în apelurile de sistem, deci este dificil să creezi un pointer kernel arbitrar.
\ De exemplu, accessok() se asigură că pointer-ul furnizat de utilizator indică spre spațiul utilizatorului, iar macrocomanda arrayindexnospec previne accesul speculativ în afara limitelor cu indexul furnizat de utilizator. Astfel, guessptr ar trebui să fie un pointer kernel existent, în mod specific pointer-ul vulnerabil care cauzează corupția memoriei. De exemplu, un pointer atârnat în use-after-free (UAF) sau un pointer în afara limitelor în depășirea buffer-ului poate fi utilizat. În final, în TEST, testptr ar trebui dereferențiat, iar testptr ar trebui să fie accesibil din spațiul utilizatorului. Pentru a ușura măsurarea stării cache-ului, test_ptr ar trebui să fie un pointer din spațiul utilizatorului furnizat printr-un argument de apel de sistem.
\ ==Gadget-uri Descoperite.== Am analizat manual codul sursă al kernel-ului Linux pentru a găsi gadget-ul TIKTAG care îndeplinește cerințele menționate anterior. Ca rezultat, am găsit un gadget TIKTAG-v1 potențial exploatabil în sndtimeruserread() (Figura 10). Acest gadget îndeplinește cerințele TIKTAG-v1 (§5.1). La linia 10 (adică, BR), instrucțiunea switch declanșează predicția greșită a ramurii cu o valoare controlabilă de utilizator tu->tread (adică, condptr). La liniile 14-17 (adică, CHECK), tread (adică, guessptr) este dereferențiat de patru instrucțiuni de încărcare. tread indică spre un obiect struct sndtimer_tread64 pe care atacatorul îl poate aloca și elibera arbitrar.
\ Dacă o vulnerabilitate temporală transformă tread într-un pointer atârnat, acesta poate fi utilizat ca guessptr. La linia 20, (adică, TEST), un pointer buffer din spațiul utilizatorului (adică, testptr) este dereferențiat în copytouser. Deoarece acest gadget nu este direct accesibil din spațiul utilizatorului, am făcut o mică modificare a codului kernel-ului; am eliminat returnarea timpurie pentru cazul implicit la linia 6. Acest lucru asigură că buffer-ul este accesat doar pe calea speculativă pentru a observa diferența de stare a cache-ului datorită execuției speculative.
\ Deși această modificare nu este realistă într-un scenariu real, demonstrează potențiala exploatabilitate a gadget-ului dacă se fac schimbări similare de cod. Am descoperit mai multe gadget-uri potențial exploatabile, dar nu am putut observa diferența de stare a cache-ului între potrivirea și nepotrivirea etichetelor. Totuși, considerăm că există un potențial puternic pentru exploatarea acelor gadget-uri. Lansarea atacurilor bazate pe TIKTAG implică inginerie complexă și sensibilă, și astfel nu am putut experimenta cu toate cazurile posibile.
\ În special, TIKTAG-v1 se bazează pe reducerea speculației la evenimentele de cale greșită, care pot include, de asemenea, erori de traducere a adreselor sau alte excepții în calea de predicție greșită a ramurii. Deoarece apelurile de sistem implică fluxuri de control complexe, reducerea speculației poate să nu fie declanșată conform așteptărilor. În plus, mai multe gadget-uri pot deveni exploatabile când se modifică codul kernel-ului. De exemplu, un gadget TIKTAG-v1 în ip6mr_ioctl() nu a prezentat un comportament de scurgere a etichetei MTE când a fost apelat din calea sa de apel de sistem (adică, ioctl). Cu toate acestea, gadget-ul avea scurgere de etichete când a fost portat la alte syscall-uri (de exemplu, write) cu un flux de control simplu.
\ ==6.2.3. Atacul de bypass MTE Kernel.== Figura 9b ilustrează atacurile de bypass MTE asupra kernel-ului Linux. Luând ca exemplu o vulnerabilitate use-afterfree, presupunem că atacatorul a identificat un gadget TIKTAG corespunzător, SysTikTagUAF(), capabil să scurgă rezultatul verificării etichetei pointer-ului atârnat creat de vulnerabilitate. De exemplu, gadget-ul TIKTAG-v1 în sndtimeruser_read() (Figura 10) poate scurge rezultatul verificării etichetei tread, care poate deveni un pointer atârnat printr-o vulnerabilitate use-after-free sau double-free.
\ Atacul procedează după cum urmează: În primul rând, atacatorul eliberează un obiect kernel (adică, objvuln) și lasă pointer-ul său (adică, vuln_ptr) ca un pointer atârnat ( 1 ). Apoi, atacatorul alocă un alt obiect kernel (adică, objtarget) la adresa objvuln cu SysAllocTarget() ( 2 ). Apoi, atacatorul invocă SysTikTag() cu un buffer din spațiul utilizatorului (adică, ubuf) ( 3 ), și scurge rezultatul verificării etichetei (adică, Tm == Tg) măsurând latența de acces a ubuf ( 4 ). Dacă etichetele se potrivesc, atacatorul declanșează SysExploitUAF(), un apel de sistem care exploatează vulnerabilitatea use-after-free ( 5 ). În caz contrar, atacatorul realocă objtarget până când etichetele se potrivesc.
\ ==Declanșarea Cache Side-Channel.== Ca în §6.1.3, o exploatare reușită a gadget-ului TIKTAG necesită i) antrenarea ramurii, ii) controlul cache-ului și iii) măsurarea cache-ului. Pentru antrenarea ramurii, atacatorul poate antrena predictorul de ramuri și declanșa speculația cu condiții de ramură controlate de utilizator din spațiul utilizatorului. Pentru controlul cache-ului, atacatorul poate goli buffer-ul din spațiul utilizatorului (adică, ubuf), în timp ce adresa de memorie a kernel-ului poate fi eliminată prin cache line bouncing [25]. Pentru măsurarea cache-ului, latența de acces a ubuf poate fi măsurată cu contorul virtual (adică, CNTVCT_EL0) sau un cronometru bazat pe contor de memorie (adică, rezoluție aproape de ciclul CPU).
\ ==Exploatarea Vulnerabilităților de Corupție a Memoriei.== Gadget-urile TIKTAG permit ocolirea MTE și exploatarea vulnerabilităților de corupție a memoriei kernel-ului. Atacatorul poate invoca gadget-ul TIKTAG în kernel pentru a declanșa speculativ corupția memoriei și a obține rezultatul verificării etichetei. Apoi, atacatorul poate obține rezultatul verificării etichetei și declanșa corupția memoriei doar dacă etichetele se potrivesc. Detaliem procesul de atac de bypass MTE al kernel-ului Linux în §D.
\ ==6.2.4. Atenuare.== Pentru a atenua gadget-ul TIKTAG în kernel-ul Linux, dezvoltatorii kernel-ului ar trebui să ia în considerare următoarele atenuări:
i) Bariera de speculație: Barierele de speculație pot atenua eficient gadget-ul TIKTAG-v1 în kernel-ul Linux. Pentru a preveni atacatorii să scurgă rezultatul verificării etichetei prin buffer-ul din spațiul utilizatorului, funcțiile kernel-ului care accesează adresele din spațiul utilizatorului, cum ar fi copytouser și copyfromuser, pot fi întărite cu bariere de speculație. După cum se descrie în §5.1, scurgerea rezultatelor verificării etichetelor cu acces store poate fi atenuată prin plasarea unei bariere de speculație înainte de accesul store (adică, TEST).
\ De exemplu, pentru a atenua gadget-urile care valorifică copytouser, o barieră de speculație poate fi inserată înainte de invocarea copytouser. Pentru gadget-urile care utilizează acces load la buffer-ul din spațiul utilizatorului, barierele atenuează gadget-urile dacă sunt inserate între ramură și accesul la memoria kernel-ului (adică, CHECK). De exemplu, pentru a atenua gadget-urile care valorifică copyfromuser, dezvoltatorii kernel-ului ar trebui să analizeze cu atenție baza de cod a kernel-ului pentru a găsi modelul de ramură condițională, acces la memoria kernel-ului și copyfromuser(), și să insereze o barieră de speculație între ramură și accesul la memoria kernel-ului.
\ ii) Prevenirea construcției gadget-ului: Pentru a elimina gadget-urile TIKTAG potențiale în kernel-ul Linux, codul sursă al kernel-ului poate fi analizat și remediat. Deoarece gadget-urile TIKTAG pot fi, de asemenea, construite prin optimizări de compilator, poate fi efectuată o analiză binară. Pentru fiecare gadget descoperit, instrucțiunile pot fi reordonate sau pot fi inserate instrucțiuni suplimentare pentru a preveni construcția gadget-ului, urmând strategiile de atenuare din §5.1 și §5.2.
:::info Autori:
:::
:::info Această lucrare este disponibilă pe arxiv sub licența CC 4.0.
:::
\


