Googleov Project Zero otkrio kako zaobići Samsungov Knox hipervizor (popravljeno u siječanjskoj zakrpi)

U najnovijem postu na blogu Project Zero, tim je otkrio način zaobilaženja Samsungove zaštite jezgre u stvarnom vremenu, nazvane Knox Hypervisor.

Googleov Project Zero tim potvrdio je niz eksploatacija koje omogućuju napad na Samsungove telefone s navodno sigurnim sigurnosnim paketom Samsung Knox. Blog navodi da su sve ranjivosti proslijeđene Samsungu koji je zapravo izdao popravke za njih u ažuriranju softvera u siječnju.


Pozadina

Kao dio sigurnosnog softverskog paketa Samsung Knox koji je predstavio Samsung, postoji dio softvera koji se nalazi između Android aplikacija i kernela koji se zove Hipervizor. Ovo se može koristiti kao dodatni sloj za dodatnu zaštitu Android uređaja. Samsung Knox Hypervisor zove se "Zaštita kernela u stvarnom vremenu" ili skraćeno RKP, kako ću ga spominjati u ostatku ovog članka.

Kernel se nalazi ispod RKP-a u hrpi Android softvera, a aplikacije koje se izvode na uređaju nalaze se na vrhu. Ideja koja stoji iza RKP-a je pružiti dodatni sloj sigurnosti za uređaj jer svi zahtjevi (memorija i drugi resursi) koje aplikacije na Kernel moraju prvo proći kroz Knox, koji pokušava otkriti radi li aplikacija nešto ne bi trebalo. RKP također pruža sigurnost kroz nejasnoće s dodatnim slojem za skrivanje osjetljivih informacija koje bi aplikacija mogla upotrijebiti za kompromitiranje uređaja.

Post na blogu ide prilično duboko u to kako funkcionira Android memorija, RKP i operativni sustavi općenito, pa sam ga sažeto i pojednostavio kako bih dao brzi pregled onoga što je otkriveno. Ipak, potičem vas da pročitate cijeli članak ako imate vremena, jer je vrlo poučan.


Eksploatacija #1:

KASLR ili Kernel Address Space Layout Randomization je proces mijenjanja lokacije koda kernela u memoriji za nasumični iznos pri dizanju sustava. Svaki put kad se uređaj pokrene kernel se učitava u drugi adresni prostor (područje u memoriji). Ideja je otežati pronalaženje gdje se kod kernela nalazi kako bi ga se napalo jer se nakon svakog dizanja kod kernela "pomakne" za slučajnu količinu u memoriji. Ovo zvuči kao izvrstan korak za sprječavanje potencijalnih napadača, ali nedavnih istraživanje pokazalo je da to zapravo možete pobijediti bez potrebe za softverskom greškom ili ranjivošću, jer je KASLR zapravo vrlo teško implementirati na robustan način protiv lokalnih napadača.

U slučaju RKP softvera, mogućnost zaobilaženja KASLR-a zapravo je jednostavnija od gore navedenog istraživanja. Memorija svih Android uređaja je navedena pomoću pokazivača i kako bi se uređaji zaštitili od napada, svaki put kada Android uređaji ispisuju ili ispisuju (bilo na zaslon ili arhivirati za zapisnike ili otklanjanje pogrešaka), reference pokazivača su anonimizirane, - što onemogućuje otkrivanje kamo pokazivač zapravo pokazuje prilikom čitanja izlaz.

Zamislite memorijske pokazivače poput uličnog znaka koji pokazuje na lokaciju, a anonimiziranje kao zamagljivanje toga. Slično kao i televizija, anonimiziranje se provodi nakon snimanja, Android također primjenjuje ovo anonimiziranje u izlaznom vremenu i samo ako je anonimiziranje ispravno konfigurirano, a autor navodi da je svaki uređaj na koji je naišao imao ispravno konfiguriranu anonimizaciju pokazivača. Ovo može zvučati kao da je vrlo teško razbiti, ali sve što trebate učiniti je pronaći jedan pokazivač (mislite na ulični znak) koji nije bio anonimiziran (zamagljen) od strane programera kernela (pazite da ovo nije vaš prosječni programer Android aplikacija) kada je pokazivač zapisan u zapisnike ili na drugu lokaciju, npr. zaslon ili a datoteka.

Dakle, ako možete pronaći pokazivač koji nije bio anonimiziran, tada možete izračunati nasumični pomak adrese jezgre kao razliku između to dvoje. Zanimljivo je da autor nije mogao pronaći pokazivač koji se može iskoristiti u kernelu, ali ga je pronašao unutar RPK-a gdje su programeri zaboravili anonimizirati pokazivač u izlazu za otklanjanje pogrešaka (bilježenje), do čega je došlo putem slovoslagač. Za anonimiziranje pokazivača u Androidu morate upotrijebiti poseban kod i ispada da su programeri RPK-a greškom upotrijebili mala slova 'k' umjesto an veliko slovo 'K'. Stoga je bilo relativno jednostavno otkriti količinu nasumičnog pomaka koda kernela i napasti ga.


Eksploatacija #2:

Sljedeći iskorištavanje je malo složenije: Samsung Knox štiti vaš uređaj primjenom skupa pravila na memoriju uređaja za zaustavljanje zlonamjernog koda. Pravila su sljedeća:

  1. Sve stranice (kod u memoriji), s izuzetkom koda kernela, označene su kao "Privilegirano Izvrši nikad" (što znači da se kod ovdje nikada ne može pokrenuti)
  2. Podatkovne stranice jezgre (podaci koje koristi program u memoriji) nikada nisu označene kao izvršne (tako da se kod ovdje nikada ne može pokrenuti)
  3. Kodne stranice jezgre (kôd u memoriji) nikada nisu označene za pisanje (tako da ih zlonamjerni kod ne može promijeniti)
  4. Sve stranice kernela označene su kao samo za čitanje u tablici prijevoda faze 2 (tablica koja se nalazi između aplikacije i kernela kako bi se dodatno spriječilo da aplikacije znaju o stvarnim memorijskim lokacijama)
  5. Svi unosi prijevoda memorije označeni su kao samo za čitanje za aplikacije.

Usredotočit ćemo se na pravilo 3 jer je ovdje autor pronašao problem s provedbom gore navedenih pravila. RPK zapravo označava memoriju za kernel kao samo za čitanje, no kao previd u KASL-u otkrivena je rupa koja je dovela do pisanje koda u odjeljak koji je navodno "samo za čitanje".. Kako bi se prikrila lokacija kernela u vrijeme dizanja, memorija se dodjeljuje kernelu, ali ta je količina memorije puno veća od tekstualnog segmenta kernela. Dodjeljivanjem veće količine memorije znatno je teže pronaći stvarni kod kernela koji bi mogao biti bilo gdje, a kao što smo vidjeli gore, pomiče se nasumično pri svakom pokretanju uređaja.

_text i _etext označavaju zaštićeni raspon

Autor je uspio potvrditi da je memorija koju koristi kernel doista označena kao "samo za čitanje", međutim ostatak te velike količine memorije korištene za skrivanje kernela je ne označen kao "samo za čitanje". To je zato što RKP štiti samo područje koje sadrži tekst kernela nakon primjene KASLR slajda.


Eksploatacija #3

U trećem podvigu autor je mogao pristupiti još jednom području memorije koje bi također trebalo biti ograničeno samo na čitanje. RKP štiti memoriju i koristi a Registar konfiguracije hipervizora (HCR) za kontrolu ključnih operacija jezgre. Svrha HCR-a je dopustiti važeće i stvarne operacije jezgre za pristup registrima i blokiranje zlonamjernih napada. To čini provjerom poziva upućenih registrima koji upravljaju značajkama virtualizacije. HCR je konfiguriran za blokiranje specifičnih operacija kojima bi se normalno upravljalo dopuštajući RKP-u da odabere hoće li dopustiti ili zabraniti zahtjev.

U ovom iskorištavanju HCR kontrola je bila ne pokrivajući dva registra to se pokazalo vrlo važnim. Autor je kopao duboko u priručnik ARM Reference i otkrio da mu je prvi registar omogućio da u osnovi isključi RKP za aplikacije. "Kontrolni registar sustava za EL1 (SCTLR_EL1) pruža kontrolu na najvišoj razini nad sustavom, uključujući memorijski sustav." U savršenom svijetu aplikacija bi koristila memoriju koja je mapirana putem RKP-a kako bi RKP mogao kontrolirati čemu aplikacija može pristupiti. Međutim, isključivanje ovog registra omogućilo je RKP biti onemogućen učinkovitim vraćanjem uređaja na način na koji je radio prije instaliranja RKP-a - što znači da je uređaj mapiran u fizičku memoriju bez dodatne sigurnosti koju pruža RKP. To je zauzvrat značilo da je autor mogao čitati i pisati u memoriju koja je izvorno i ispravno blokirana RKP softverom.

Drugi registar koji je promašen imao je suptilniji učinak, ali u konačnici jednako razoran za sigurnost. The Registar kontrole prijevoda za EL1 (TCR_EL1) registar izravno se odnosi na količinu memorije s kojom radi aplikacija koja se naziva stranica. RKP je tvrdo kodiran na veličinu stranice od 4 kB jer AARCH64 Linux kerneli (kao što je Android) koriste veličinu prijevoda od 4 KB. Dotični registar (TCR_EL1) postavlja ARM skupove čipova na veličinu memorije koja se treba vratiti. Ispostavilo se da ovaj registar nije zaštićen od strane HCR-a i stoga ga napadač može promijeniti kao što ga je autor promijenio na veličinu stranice od 64kb.

To znači da kada RKP ispuni zahtjev, stvarna količina dostupne memorije sada iznosi 64 kb umjesto 4 kb. Razlog je taj što ARM čipset još uvijek kontrolira veličinu stranice, a eksploatacija je postavila na 64kb. Budući da RKP štiti memoriju od pisanja, kao dio pravila navedenih u exploit #2, memorija je i dalje zapravo zaštićena. Ali ovdje je kvaka - budući da je RKP tvrdo kodiran na 4 kb, ne mijenja se na veličinu stranice od 64 kb kada je registar ažuriran, pa zaštićeno je samo prvih 4kb memorije dopuštajući napadaču da učini što god želi s preostalih 60kb.


Eksploatacija #4

Posljednji exploit koji autor prikazuje je referenciranje memorije u kojoj se nalazi RKP softver, tako da bi napadač mogao napasti sam RKP softver. Jedan trik za zaustavljanje ove vrste napada koji također koriste Linux kerneli je demapiranje vašeg programa iz adresnog prostora virtualne memorije tako da ga aplikacije ne mogu napasti jer ga ne mogu referencirati.

Zapamtite da se memorija sastoji od pokazivača i tablica koje mapiraju fizičku memoriju u virtualnu memoriju. Kao normalna obrana u ovoj vrsti napada, RKP demapira sam sebe tako da ne može biti napadnut. Međutim, tamo gdje jezgra ne pruža takve mogućnosti, RKP dopušta da se dio memorije mapira i označi kao Čitanje/Pisanje. Jedina provjera je da se ne radi o samoj temeljnoj jezgri jer RKP ne provjerava jesu li adrese za koje se traži da budu mapirane područje gdje se sam RKP nalazi u memoriji. Uglavnom, RKP dopušta da se ponovno preslika natrag u adresni prostor kojem aplikacije mogu pristupiti i kao sporedni utjecaj na memorija se automatski označava kao čitanje/pisanje tako da napadač sada može koristiti memoriju kako god želi.


Zaključak

Jedan od najvećih problema s četiri gore navedena iskorištavanja je to što autor spominje kako bi ih bilo teško izvesti zbog nedostatka funkcija u osnovnoj jezgri Androida. Ironično, sigurni RKP Hypervisor pružao je sve alate koji su bili potrebni za izvođenje napada. Dokazuje se da ponekad dobronamjerni softver uzrokuje više problema nego što ih rješava i sretni smo što imamo ljude poput Gal Beniaminija spremni zaprljati ruke i testirati odgovara li dokumentacija onome što softver zapravo radi.

Iako ovi podvigi djeluju zastrašujuće i čine da Knox zvuči vrlo ranjivo, želio bih sve uvjeriti da su svi ovi problemi popravljeno u siječanjskom ažuriranju od Samsunga. Nadalje, ovi exploiti zahtijevaju vrlo duboko razumijevanje ARM procesora i programiranja, tako da je prepreka za korištenje ovih exploita astronomski visoka.


Izvor: Projekt Zero