A Google nulladik projektje felfedezte, hogyan lehet megkerülni a Samsung Knox Hypervisor-ját (javítva a januári javításban)

A Project Zero legújabb blogbejegyzésében a csapat felfedezte a Samsung valós idejű kernelvédelmének, a Knox Hypervisornak a megkerülésének módját.

A Google Project Zero csapata számos olyan kizsákmányolást igazolt, amelyek lehetővé teszik a Samsung telefonjait, amelyek az állítólagosan biztonságos Samsung Knox biztonsági csomagot futtatják. A blog megjegyzi, hogy az összes sebezhetőséget átadták a Samsungnak, aki valóban kiadta a javításokat egy januári szoftverfrissítésben.


Háttér

A Samsung által bevezetett Samsung Knox biztonsági szoftvercsomag részeként van egy szoftver, amely az Android alkalmazások és a kernel között helyezkedik el. Hipervizor. Ez további rétegként használható az Android-eszközök további biztonságához. A Samsung Knox Hypervisor neve "Valós idejű kernelvédelem" vagy röviden RKP, ahogy a cikk további részében hivatkozni fogok rá.

A kernel az RKP alatt található az Android szoftververemben, az eszközön futó alkalmazások pedig a tetején. Az RKP mögött meghúzódó ötlet az, hogy egy extra biztonsági réteget biztosítson az eszköz számára, mivel az összes kérést (memória és egyéb erőforrások) A rendszermagba érkező alkalmazásoknak először át kell menniük a Knoxon, amely megpróbálja észlelni, hogy egy alkalmazás csinál-e valamit nem kellene. Az RKP az ismeretlenségen keresztül is biztonságot nyújt egy extra réteggel, amely elrejti az olyan érzékeny információkat, amelyeket egy alkalmazás felhasználhat az eszköz kompromittálására.

A blogbejegyzés meglehetősen mélyen bemutatja, hogyan működik az Android memória, az RKP és általában az operációs rendszerek, ezért összesítettem és leegyszerűsítettem, hogy gyors áttekintést nyújtsak a felfedezésekről. Javasolom, hogy olvassa el a teljes cikket, ha van ideje, mert nagyon tanulságos.


1. kihasználás:

KASLR vagy Kernel Address Space Layout A véletlenszerűsítés az a folyamat, amelynek során rendszerindításkor véletlenszerűen megváltoztatjuk a kernelkód helyét a memóriában. Az eszköz minden indításakor a kernel egy másik címtérbe (memóriaterületre) töltődik be. Az ötlet az, hogy megnehezítsük a kernelkód helyének megtalálását, hogy megtámadhassuk, mert minden rendszerindítás után a kernelkód véletlenszerű mértékben "eltolódik" a memóriában. Ez nagyszerű lépésnek tűnik a potenciális támadók megelőzésére, de nemrég kutatás megmutatta, hogy ez valóban legyőzhető szoftverhiba vagy sebezhetőség nélkül, mivel a KASLR-t valójában nagyon nehéz robusztus módon megvalósítani a helyi támadók ellen.

Az RKP szoftver esetében a KASLR megkerülésének lehetősége valójában egyszerűbb, mint a fent hivatkozott kutatás. Minden Android-eszköz memóriájára mutatók hivatkoznak, és annak érdekében, hogy megvédjék az eszközöket a támadásoktól, amikor androidos eszközök nyomtatnak vagy kiadnak (akár képernyőről, akár naplózáshoz vagy hibakereséshez), a mutató hivatkozásai anonimizáltak, így lehetetlen kideríteni, hogy a mutató hova mutat a Kimenet.

Gondoljon a memóriamutatókra, mint egy utcatáblára, amely egy helyre mutat, és gondoljon az anonimizálásra, mint annak elmosására. Hasonlóan a televízióhoz, az anonimizálás a forgatás után történik, az Android is ezt az anonimizálást alkalmazza a kimeneti időben, és csak akkor, ha az anonimizálás megfelelően van beállítva, és a szerző állítja. hogy minden eszközön, amellyel találkozott, megfelelően van beállítva a mutató anonimizálása. Ez úgy tűnhet, mintha nagyon nehéz megtörni, de mindössze annyit kell tennie, hogy talál egy mutatót (gondoljunk az utcatáblára), amely nem volt anonimizált (elmosódott) a kernel fejlesztője (vigyázat, ez nem az átlagos Android alkalmazásfejlesztő), amikor a mutatót a naplókba vagy más helyre írják, pl. képernyő vagy a fájlt.

Tehát ha talál egy mutatót, amely nem volt anonimizált, akkor kiszámíthatja a kernel véletlenszerű címeltolódását a kettő közötti különbségként. Érdekes módon a szerző nem talált kihasználható mutatót a kernelben, de az RPK-n belül megtalálta. ahol a fejlesztők elfelejtettek anonimizálni egy mutatót a hibakeresési (naplózási) kimenetben, ami egy gépelési hiba. A mutatók anonimizálásához Androidon egy speciális kódot kell használni, és kiderül, hogy az RPK fejlesztői tévedésből egy kisbetű 'k' helyett an nagy "K". Ezért viszonylag egyszerű volt kitalálni a kernelkód véletlenszerű eltolási mennyiségét és megtámadni azt.


2. kihasználás:

A következő kizsákmányolás egy kicsit összetettebb: a Samsung Knox megvédi az eszközt azáltal, hogy szabályokat alkalmaz az eszköz memóriájában a rosszindulatú kódok megállítására. A szabályok a következők:

  1. Minden oldal (kód a memóriában), a kernel kódja kivételével, "Privileged Execute Never"-ként van megjelölve (ez azt jelenti, hogy a kód soha nem futhat le)
  2. A kernel adatoldalai (a program által a memóriában használt adatok) soha nem jelölik végrehajthatónak (tehát a kód soha nem futhat le)
  3. A kernel kódlapjai (a memóriában lévő kód) soha nem jelölik írhatónak (tehát a rosszindulatú kódok nem változtathatják meg)
  4. Az összes kerneloldal írásvédettként van megjelölve a 2. szakasz fordítási táblázatában (az alkalmazás és a kernel között elhelyezkedő táblázat, amely megakadályozza, hogy az alkalmazások ismerjék a valós memóriahelyeket)
  5. Minden memóriafordítási bejegyzés írásvédettként van megjelölve az alkalmazások számára.

A 3. szabályra összpontosítunk, mivel a szerző itt talált problémát a fenti szabályok végrehajtásával kapcsolatban. Az RPK valójában csak olvashatóként jelöli meg a kernel memóriáját, azonban a KASL meghibásodása miatt egy lyukat fedeztek fel, ami kód beírása az állítólagos "csak olvasható" szakaszba. Annak érdekében, hogy a rendszermag helyének elhomályosuljon a rendszerindításkor, memória van lefoglalva a kernel számára, de ez a memóriamennyiség sokkal nagyobb, mint a kernel szövegszegmense. Nagyobb mennyiségű memória lefoglalásával sokkal nehezebb megtalálni a tényleges kernelkódot, amely bárhol lehet, és ahogy fentebb láttuk, véletlenszerűen mozog az eszköz minden indításakor.

A _text és _etext a védett tartományt jelöli

A szerzőnek sikerült megerősítenie, hogy a kernel által használt memória valóban "csak olvasható"-ként van megjelölve, azonban a kernel elrejtésére használt nagy mennyiségű memória többi része nem "csak olvasható" megjelöléssel. Ennek az az oka, hogy az RKP csak a kernel szövegét tartalmazó régiót védi a KASLR dia alkalmazása után.


Exploit #3

A harmadik exploit során a szerző egy másik memóriaterülethez is hozzáférhetett, amelyet szintén csak olvashatóra kell korlátozni. Az RKP védi a memóriát és használja a Hypervisor konfigurációs nyilvántartás (HCR) a kulcsfontosságú kernelműveletek vezérléséhez. A HCR lényege, hogy lehetővé tegye érvényes és valós kernelműveletek számára a regiszterekhez való hozzáférést és a rosszindulatú támadások blokkolását. Ezt a virtualizációs funkciókat szabályozó regiszterek hívásainak ellenőrzésével teszi. A HCR úgy van beállítva, hogy blokkolja azokat a bizonyos műveleteket, amelyeket normál esetben kezelnének, lehetővé téve az RKP számára, hogy eldöntse, engedélyezi vagy tiltja a kérést.

Ebben az exploitban a HCR vezérlése volt nem terjed ki két regiszterre ez nagyon fontosnak bizonyult. A szerző mélyen beleásta magát az ARM Reference kézikönyvébe, és felfedezte, hogy az első regiszter lehetővé tette számára, hogy alapvetően kikapcsolja az RKP-t az alkalmazásokhoz. A "Az EL1 rendszervezérlő regisztere (SCTLR_EL1) a rendszer legfelső szintű vezérlését biztosítja, beleértve a memóriarendszert isEgy tökéletes világban az alkalmazás az RKP-n keresztül leképezett memóriát használná, hogy az RKP szabályozhassa, hogy az alkalmazás mihez férhet hozzá. Ennek a regiszternek a kikapcsolása azonban lehetővé tette a Az RKP letiltása hatékonyan visszaállítja az eszközt az RKP telepítése előtti állapotba – ami azt jelenti, hogy az eszköz a fizikai memóriára van leképezve az RKP által biztosított extra biztonság nélkül. Ez viszont azt jelentette, hogy a szerző képes volt olvasni és írni a memóriába, amelyet eredetileg és megfelelően blokkolt az RKP szoftver.

A második kihagyott regiszter finomabb hatással volt, de végső soron ugyanolyan pusztító hatással volt a biztonságra. A Fordításvezérlő regiszter az EL1-hez (TCR_EL1) regiszter közvetlenül kapcsolódik a memória mennyiségéhez, amellyel az alkalmazás lapként működik. Az RKP 4 kb-os oldalméretre van kódolva, mivel az AARCH64 Linux kernelek (például az Android) 4 KB-os fordítási méretet használnak. A kérdéses regiszter (TCR_EL1) beállítja az ARM chipkészleteket a visszaküldendő memória méretére. Kiderült, hogy ezt a nyilvántartást a HCR nem védi és ezért a támadó megváltoztathatja azt, ahogy a szerző 64 kb-os oldalméretre változtatta.

Ez azt jelenti, hogy amikor az RKP teljesíti a kérést, a ténylegesen elérhető memória mennyisége 4 kb helyett 64 kb. Ennek az az oka, hogy az ARM lapkakészlet továbbra is szabályozza az oldalméretet, és az exploit 64 kb-ra állította be. Mivel az RKP védi a memóriát az írástól, a 2. exploitban felsorolt ​​szabályok részeként a memória továbbra is ténylegesen védett. De itt van a bökkenő: mivel az RKP 4 kb-ra van kódolva, a regiszter frissítésekor nem változik 64 kb-os oldalméretre, így csak az első 4 kb memória védett lehetővé téve a támadó számára amit akar a maradék 60kb-ból.


Exploit #4

A szerző által bemutatott utolsó kizsákmányolás a memória hivatkozása, ahol az RKP szoftver található, így a támadó magát az RKP szoftvert támadhatja meg. Az egyik trükk az ilyen típusú támadások megállítására, amelyet a Linux kernelek is használnak, az, hogy le kell választani a programot a virtuális memória címteréből, így egyetlen alkalmazás sem támadhatja meg, mert nem hivatkozhat rá.

Ne feledje, hogy a memória olyan mutatókról és táblázatokról szól, amelyek leképezik a fizikai memóriát a virtuális memóriára. Az ilyen típusú támadások normál védekezésének megfelelően az RKP feloldja magát, hogy ne lehessen megtámadni. Ha azonban a kernel nem biztosít ilyen képességeket, az RKP lehetővé teszi egy memóriarész leképezését és olvasási/írási megjelölését. Az egyetlen ellenőrzés az, hogy nem maga a mögöttes kernel, mivel az RKP nem ellenőrzi, hogy a leképezésre kért címek az a terület-e, ahol maga az RKP található a memóriában. Alapvetően RKP engedi magát újra feltérképezni vissza a címtérbe, amelyhez az alkalmazások hozzáférhetnek, és oldalként befolyásolják a a memória automatikusan írás/olvasott állapotba kerül így a támadó most úgy használhatja a memóriát, ahogy akarja.


Következtetés

Az egyik legnagyobb probléma a fent felsorolt ​​négy exploittal kapcsolatban, hogy a szerző megemlíti, milyen nehéz lenne ezeket végrehajtani az alap Android kernel funkcióinak hiánya miatt. Ironikus módon a biztonságos RKP Hypervisor minden eszközt biztosított a támadások végrehajtásához. Ez azt mutatja, hogy a jó szándékú szoftverek néha több problémát okoznak, mint amennyit megoldanak, és szerencsések vagyunk, hogy vannak embereink mint például Gal Benimini, aki hajlandó bemocskolni a kezét, és tesztelni, hogy a dokumentáció megegyezik-e a szoftverrel csinál.

Bár ezek a kihasználások ijesztőnek tűnnek, és nagyon sebezhetővé teszik a Knox hangját, szeretnék mindenkit megnyugtatni, hogy ezek a problémák mind januári frissítésben javítva a Samsungtól. Ezen túlmenően ezekhez az exploitokhoz az ARM processzorok és a programozás mélyreható ismerete szükséges, így a belépés előtti akadályok csillagászatilag magasak.


Forrás: Project Zero