Így működik a TaiG jailbreak

Ez a cikk legalább 1 éve frissült utoljára. A benne szereplő információk a megjelenés idején pontosak voltak, de mára elavultak lehetnek.

Jonathan Levin (@Technologeeks) indított egy – egyelőre két cikket számláló – sorozatot a TaiG jailbreak működéséről. Ennek során viszonylag részleteibe menően tárgyalja a különféle exploitok kihasználásának mechanizmusát. A sorozat eddig megjelent két cikkének egy kicsit átdolgozott (helyenként a kevésbé érdekes részleteken átsikló, máshol a nem elég részletesen kifejtett lépéseket jobban megmagyarázó) fordítását szeretnénk most a kedves érdeklődő olvasók elé tárni.

TaiG_jailbreak

Fontos megjegyezni, hogy a TaiG a cikk írásának pillanatában legfrissebb iOS-verzión, a 8.1.3-on már nem működik, tehát a pontos technikai információk feltárásával nem okozunk kárt azoknak, akik ezeket az exploitokat fel szerették volna használni egy jövőbeli jailbreakhez. (Amennyiben nem lennének még befoltozva az itt megemlített biztonsági rések, akkor az ilyen jellegű cikkek az Apple-t segítenék a hibák megtalálásában és javításában.)

Eszközök és előkészületek

A TaiG alapvetően egy windowsos alkalmazás. A Panguval ellentétben (amely VMware-en virtualizált Windows 7-en lefagyott) szépen elfut virtuális gépen is. [Ezt e sorok írója is megerősítheti személyes tapasztalatai alapján – a szerk.] Természetesen, a legérdekesebb rész, maga a jailbreakelés az iOS-készüléken zajlik, de azért a “telepítő” asztali alkalmazásra is érdemes vetni egy pillantást. Jonathan a következő programokat használta a windowsos app visszafejtéséhez:

– Process Explorer és Process Monitor: két, Mark Russinovich által fejlesztett, haladó képességekkel felszerelt folyamatvizsgáló eszköz. Előbbi magukról a futó programokról nyújt információkat (hasonlóan, ahogyan azt egy debugger teszi), utóbbi pedig a rendszerhívásokat figyeli és naplózza.

– IDA: a legtöbb képességgel felszerelt disassembler (és általános reverse engineering eszköz) Windowsra.

– WinDBG: egy népszerű windowsos debugger.

A jailbreak iOS-es részének szóra bírásához a következő eszközök álltak rendelkezésre:

– FileMon: Jonathan saját fájlrendszeresemény-figyelője.

– fs_usage: egy kdebug-alapú eszköz, amit a szerző arra használt, hogy leellenőrizze saját FileMon programjának a helyességét.

– jtool: ez a disassembler szintén a szerző saját billentyűzetéből való (nagyjából az “otool” helyettesítésére szolgál, de annál többet tud, és szebb a kimenete is.)

Jonathan egyébként egy Pangu segítségével előre jailbreakelt készüléket használt. Ez azért volt nagy segítség, mert a futásidejű, “élő” programelemzés sokkal könnyebb, mint a statikus analízis – abból, hogy a program mit csinál, egyszerűbb rájönni, hogy hogyan működik, mint abból, ha egyszerűen van egy óriási adag assembly kódunk, amit órákon keresztül bámulunk…

A windowsos alkalmazás

A programnak a számítógépen (tehát a készüléken kívül) futó része annyira nem érdekes; a lényeg gyakorlatilag egy pár pontban összefoglalható:

– a végrehajtható fájl mérete hatalmas: több, mint 50 MB. Ez azért van, mert az egy szem bináris DATA szegmensébe “erőforrásként” be van ágyazva az összes fájl, mappa, segédprogram, stb., ami a jailbreakhez szükséges.

– A program első ránézésre nem használja az Apple által az iTunes-szal való kommunikációhoz készített könyvtárait és azok függőségeit (például AppleMobileDevice, CoreFoundation); ha kicsit belenézünk a kódba, akkor viszont látjuk, hogy azokat dinamikusan tölti be az LdrLoadDll() függvény segítségével (talán azért nem a megszokott LoadLibrary() függvényt használja, hogy ne legyen annyira feltűnő? Ki tudja…).

Az app egyébként az összes, az Apple-féle DLL-ekben megtalálható függvény és egyéb szimbólum címét lekéri, habár azoknak csak kis részét használja ténylegesen (például a CoreFoundation többségét, a MobileDevice és hasonló DLL-ekből pedig az AMRestoreRegisterForDeviceNotification(), AMDeviceCopyValue(), stb. függvényeket.)

A releváns kódrészletről készült disassemblyt a következő képen láthatjátok:

windows_dynload

Az iOS-es rész

Amint az a legtöbb esetben szokott lenni, a teljes jailbreakeléshez több exploit együttes kihasználására van szükség. Az eddigi összes jailbreak a következő “algoritmus” alapján működött:

  1. A készüléken futó folyamatnak ki kell törnie a sandboxból, hogy tetszőleges fájlokat és mappákat elérjen.
  2. Tetszőleges (digitálisan alá nem írt) kód futtatásának engedélyezése – ez általában vagy egy ROP-támadással, vagy az aláírások ellenőrzésének teljes kikapcsolásával működik. A TaiG az utóbbi technikát használja.
  3. Rendszergazdai (root) jogosultság megszerzése – ez szintén egy, az iOS-ben eleve meglévő, root alatt futó bináris ROP-támadásával, vagy egy launch daemon telepítésével oldható meg (utóbbihoz is szükséges a sandboxon kívül eső fájlokhoz való hozzáférés, hogy elhelyezhessük azt a plist fájlt a megfelelő helyen, amely a launchd-nek megmondja, hogy a mi saját programunkat rootként indítsa el.)

Az exploitok

1.: AFC (CVE-2014-4480)

Az AFC (Apple File Conduit) az a szolgáltatás az iOS-ben, amely a készüléken lévő fájlok elérésére szolgál. Ezzel kommunikál az iTunes (illetve jelen esetben a TaiG) az AFC*() függvények segítségével. Az AFC tehát tud írni, olvasni, le- és feltölteni, valamint törölni fájlokat – persze “hivatalosan” csak az iOS-ből nyilvánosan látható könyvtárban, a /var/mobile/Media helyre.

Mivel az AFC képes a fájlok írására, ezért őt használhatja a jailbreak mintegy “belépési pontnak”. Az előbb említett Media könyvtárban létrehoz egy olyan könyvtárszerkezetet, ami a root fájlrendszer szerkezetét tükrözi:

list_1

Ez azért jó, mert hasznosnak bizonyul, amikor kihasználunk egy hibát a…

2. DeveloperDiskImage support

…rendszerében.

A DDI egy lemezképfájl (.dmg), amely a fejlesztéshez szükséges eszközöket tartalmaz (ezek például akkor kellenek, amikor az Xcode-ban dolgozunk, de a készüléken futtatjuk az alkalmazást – ekkor a számítógépen futó debuggernek valahogyan csatlakoznia kell az iOS-en futó programhoz.).

A DDI fel-“mount”-olásakor annak tartalma összefésülésre kerül az iOS fájlrendszerével. Ez azt jelenti, hogy ha sikerül egy ügyesen megszerkesztett DDI-t készítenünk és felmountolnunk, akkor a megfelelő szimbolikus linkek létrehozásával gyakorlatilag azt a fájlt érjük el, amelyiket csak akarjuk. Ráadásul amennyiben ütközés van a fájlrendszerben, azaz a felcsatolt image-ben megvan egy olyan fájl, ami az OS-ben eredetileg is létezik, akkor az image-ben lévő fájl felülírja azt (legalábbis átmenetileg).

Tetszőleges disk image hozzáadása azonban nem annyira egyszerű, mert a képfájl digitálisan alá van írva. Egy klasszikus támadással viszont ez is kijátszható, ugyanis van az aláírást ellenőrző kódban egy…

3. Race condition

Az ellenőrzést végző kódban található egy ősrégi hiba. A párhuzamos programozást művelők bizonyára tiszta és őszinte utálattal gondolnak a “TOCTOU” betűszóra, amely az angol “Time-of-Check to Time-of-Use” kifejezés rövidítése. A szókapcsolat arra utal, hogy ha egy bizonyos feltételt ellenőrzünk (jelen esetben azt, hogy érvényes-e a .DMG aláírása), akkor többszálú környezetben nem lehetünk biztosak abban (legalábbis valamilyen szinkronizációs mechanizmus, például mutexek használata nélkül, ami – úgy látszik – itt kimaradt a számításból), hogy a közvetlenül az ellenőrzés után végrehajtott művelet (itt tudniillik a DMG felcsatolása) megfelel az ellenőrzött feltételnek.

A TaiG által 30% és 40% közöttinek mutatott időben pontosan ez történik: a TaiG feltölt egy, a jailbreakeléshez szükséges fájlokat tartalmazó, természetesen alá nem írt image-et, “input” fájlnévvel, majd egy érvényes aláírással rendelkező, ártatlan lemezképfájlt is, “input2” néven. Ezek után megpróbálja utóbbit az MSP (MobileStorageProxy) segítségével felmountolni, miközben gyorsan kicseréli azt az okosított “input”-ra. Nyilván a race condition nem üt be elsőre, ezért a program ismételten újrapróbálkozik, azonban körülbelül 30 másodpercen belül egyszercsak sikerül a művelet, és az MSP csatolja a hamisított képfájlt.

list_2

4. A hamisított disk image

A “hamis” lemezképfájlban, a /Volumes/DeveloperLib könyvtárban találhatóak a /usr/lib tartalmát felülíró .dylib fájlok, valamint a com.apple.dyld/enable-dylibs-to-override-cache fájl, aminek a jelenléte arra utasítja az iOS dinamikus linkerét (dyld), hogy figyelmen kívül hagyja a shared library cache-et.

A shared library cache egyébként iOS 3.1 óta létezik: ez gyakorlatilag egyetlen óriási fájl, ami az iOS-ben lévő összes dinamikus könyvtár – .dylib – kódját tartalmazza, és azoknak a hatékonyabb használatát, gyorsabb és memóriatakarékosabb betöltését teszi lehetővé. Ez viszont azt jelenti, hogy alapállapotban a /usr/lib mappa teljesen üres (csakúgy, ahogy a /Library/Frameworks és a /System/Library/Frameworks mappák bundle-jeiben sincsenek tényleges binárisok!), és a rendszer ezeket figyelmen kívül hagyja, mert a cache-et használja helyettük – ezzel ellehetetlenítve a dylib-ek felülírását. Kivéve persze, ha ezt a mechanizmust a fent leírt módon kikapcsoljuk…

Íme a hamis disk image tartalmának egy részlete:

forged_DMG

Miért is kell nekünk ez a sok dylib? Nos, ezt a zseniális exploitot még az evasi0n készítői találták ki. Az AMFId (Apple Mobile File Integrity Daemon), a fájlok digitális aláírását ellenőrző szolgáltatásba – talán “modularitás!” felkiáltással? – nincsen beépítve maga az aláírást ellenőrző kód. Ehelyett azt kiszedték egy különálló library-be, a libmis.dylib-be, és az onnan exportált függvények visszatérési értékére alapozza az AMFId a döntését (nevezetesen azt, hogy enged-e futtatni egy adott végrehajtható fájlt vagy libet).

Egy speciálisan megszerkesztett dylib segítségével azonban megtehetjük azt, hogy az összes ilyen függvény lazy linking-hez szükséges “csonkját” (symbol stub) átirányítjuk pl. egy határozott kCFBooleanTrue-ra vagy CFEqual()-ra. Ekkor bármit is talál az AMFId, mindenre azt fogja mondani, hogy “igen, futhat”.

Természetesen a dolog nem ilyen egyszerű, a függvényeket hívni szokás, a CoreFoundation logikai “igaz” konstansát pedig csupán vissza szeretnénk adni visszatérési értékként, nem pedig függvényként hívni, de az alapvető mechanizmus a dinamikus szimbólumok eltérítésén alapul.

Az aláírásellenőrzést azonban még egy korábbi szakaszban is meg kell kerülni, ugyanis a saját libmis.dylib-ünk nincsen aláírva, tehát eleve be sem tudnánk tölteni – hacsak nem találunk valahol máshol is egy újabb hibát, például magában a…

5. DYLD

…azaz a dinamikus linker (dynamic linker, dynamic loader) binárisában. Ezt a hibát szintén nyilvánosságra hozta az Apple, CVE-2014-4455 azonosítóval. Egyébként ez már – szégyenszemre – nem az első alkalom, hogy a Mach-O fájlok kezelésével kapcsolatos biztonsági rés van a rendszerben.

A TaiG-ben lévő libmis.dylib-en lefuttatva az otool disassemblert, az reklamálni fog, hogy a fájl inkonzisztens. A szerző által írt jtool utility egyenesen elcrashelt, amikor a hibás formátumú library-vel találkozott. Azonban a megfelelő korlátellenőrzés (bounds checking) hozzáadása után kiderült, hogy a turpisság magában a dylib fájlban rejlik: a szegmensek egyes részei átlapolt memóriacímeken vannak. Ezt a DYLD nem mindig kezeli megfelelően, így a hiba kihasználható a fent leírt módon az egyes szimbólumok felüldefiniálására és a signature checking kikapcsolására. Íme, a jtool futtatásának az eredménye, győződjetek meg ti magatok is az átlapolódó szegmensekről:

list_3

Ha mindez készen van, akkor már nincs más dolgunk, “csupán” bejuttatni a jailbreak állandóságát biztosító (untethering) binárist, ami újramountolja a gyökérkönyvtárat tartalmazó fájlrendszert írhatóként (az eredetileg csak olvasható ugyanis), megpatcheli a kernelt, és elvégez még egy pár, inkább kényelmi szempontból fontos dolgot. Ez a fájl a /taig/taig helyen található. A következő részben ennek a működéséről lesz szó.

Ezek még érdekelhetnek:


  1. Írhatnátok cikket erről az nvram módosításos dologról is, hogy a magyar olvasókban is tudatosuljon. Elég tanulságos eset, nem kéne mindenkinek mindent letölteni. Óvatosabban kéne a jailbreakkel bánni, főleg, hogy az emberek nagy része nem ért hozzá (bár sokuk pont az ellenkezőjét hiszik). Ez mostanában még inkább igaz, mióta egyre inkább egykattintásos jailbreakek jelennek meg. Attól még, hogy a jailbreak folyamata (felhasználói részről) ennyire egyszerű, maga a jailbreak továbbra is bonyolult, akár veszélyes is lehet (már akinek számít az eszköze), ha nem figyelünk oda eléggé.

  2. Nekem még mindig a régi PSP törés tetszett a legjobban, amikor egy PNG kiterjesztésű képet kellett feltolni a gépre, majd a beépített képnézővel megnyitni. A néző szarrá fagyott tőle, de a képfileben elrejtett JB kód lefutott és lett egy szép feltört konzol 🙂

  3. @LordFanThomas: a jailbreaktől önmagában nem fogsz tudni tört appokat telepíteni, ahhoz mindig is külön csomag telepítése volt szükséges, és ez most, az egykattintásos jailbreakek idején sincs másképp. a warez kapcsán már számtalaszor leírtuk, hogy mik a lehetséges problémák, NVRAM ide vagy oda.

    @dnp: ha jól emlékszem, a legelső iOS-es (akkor még iPhoneOS) jailbreak, a jailbreakme is ezen a PNG-s elven működött, csak ott a Safariban a weboldalt kellett megnyitni, ami betöltötte a megfelelő PNG-t.

  4. @Jadeye: Persze, egyértelmű. Nem is a warezről beszéltem, hiszen az egésznek köze nincs hozzá, még a tört tweakekhez sem (legalábbis elvben nem – aztán ki tudja, bigboss-ba is becsúszhat egy-két ilyen package, de előbb-utóbb úgyis lekerül).

  5. @Jadeye: A dolognak továbbra sincs semmi köze a tört appokhoz. A tört tweakekhez sem alapvetően, hiszen pl. elég egy OpenSSH (és egy nem megváltoztatott jelszó), hogy visszaállíthatatlanul tönkretegyék az eszközödet. Ez sokak számára a hétvégén vált világossá (a basebandes módosítgatáson kívül én is azt hittem, nincs már mód örökre brickelni az iPhone-t). De mindegy is. Ha tudatosan csinálsz mindent, elvileg nem lehet baj, de az sem garantál semmit.

  6. @LordFanThomas: “pl. elég egy OpenSSH (és egy nem megváltoztatott jelszó), hogy visszaállíthatatlanul tönkretegyék az eszközödet”
    ad.1.: ki telepít az egyszeri felhasználók közül OpenSSH-t? (és pláne miért?)
    ad.2.: aki OpenSSH-t telepít, és aktív állapotban hagy, nem változtat jelszót?

    ha valaki ész nélkül csinál bármit, ott minden mindegy; a nagy hatalommal nagy felelősség is jár.

  7. @LordFanThomas: a wareznak annyi köze van a dologhoz (Jadeye általában erre szokott utalni), hogy a nemhivatalos forrásból származó (jellemzően tört, de nem muszáj…) alkalmazások, tweakek tartalmazhatnak malware-t (ahogyan erre volt is már példa, ha jól emlékszem). Nyilván az, hogy egy szoftver el lett “lopva”, az magában még nem “veszély” – a veszély az, ha ismeretlen az eredete, és ki tudja, ki és mit tett bele.

    A jailbreakkel pedig nem települ automatikusan az OpenSSH. (Nyilván nem véletlenül…) – aki meg direkte fölteszi, az pedig változtassa meg a két jelszót. A veszélyforrást jelentő kiegészítők telepítése nem a jailbreak hibája, hanem a felhasználóé. “Guns don’t kill people; people do.”

  8. Ha már jailbreak, lenne egy kérdésem a hozzáértőktől. Remélem nem törlik a kérdésemet, mert hiába tenném fel egy 3 évvel ezelőtti hirhez, a kutya se olvasná el. Szóval: volt jópár éve egy 3gs-em, amit jailbreakeltem még akkor. Letöltöttem egy omnibusz nevü appot,elméletileg valami buszmenetrend volt. Azóta már a negyedik iphonomat nyüvöm, most egy hatost, de minden egyes telefonomon ujrainditás után feltelepül az omnibusz app. Fogalmam nincs honnan jön, már egyáltalán nem jailbreakelek a 3gs óta. Van valakinek ötlete, hogyan tudnám véglegesen elpusztitani? Segitséget előre is nagyon megköszönöm! /természetesen lehet törölni, de ujrainditás után ujra megjelenik/

  9. @H2CO3: Persze, nyilvánvaló, magam is ezt írtam. Miután ekkora felhajtás volt a dolog körül a külföldi fórumokon, gondoltam meg lehetne említeni a magyar felhasználóknak is. A hétvégén jópár ember tette tönkre az eszközét egy bootlogo miatt, amin már a restore sem segít. Az események hatására sokakban most világosult meg, hogy ilyen szinten tönkre tehetjük mobilunkat, ha nem figyelünk oda. Látva, hogy ennyi ember nem volt tisztában a dologgal, gondoltam újra érdemes lenne felhívni a figyelmet, hogy csak csínján a tweakekkel, egyebekkel (tény, hogy sokszor le volt már írva, de eddig én is azt hittem, nem lehet bajom, hiszen ha bármi lenne, csak egy restore és kész).
    Ja, és nem jövök rá, hogyan lehet mobilról taggelni/replyt írni.

  10. @somax: az omnibusz egy webclip, tehát webes parancsikon, nem app. hogy törlés után újraindítva miért kerül ki megint, annak valószínűleg az az oka, hogy a rendszernek nincs joga letörölni. az egyes készülékek között a backupból való visszaállítással együtt ez is visszaáll. megoldás? készíts egy backupot, majd iBackupBot segítségével töröld ki belőle a webclipet (meg kell keresni a backupban, fejből passzolom, hogy hol van), és az így módosított backupot állítsd vissza a készülékre.

    @LordFanThomas: “eddig én is azt hittem, nem lehet bajom, hiszen ha bármi lenne, csak egy restore és kész”
    jusson eszedbe, hogy az iPhone 2G esetén a basebandet és a bootloadert flashelte meg a BootNeuter, amivel szintén okozhatott volna visszaállíthatatlan hibát. vagy ott volt még szintén az iPhone 2G idején, amikor a ZiPhone-nal “kezelt” készülékekben tönkrevágta Zibri a jailbreak során a Wi-Fi-t, és lett jó pár brick. vagy ott van kicsit későbbről, amikor valaki xx135-ös vagy későbbi 3GS-re tesz fel iPad basebandet, tönkrevágva ezzel a basebandet. (valamilyen szinten maga az iPad baseband is problémás volt évekig az elvesztett GPS miatt, majd lett iPad baseband downgrade.) vagy a fuzzyband, amivel az 5.8-as bootloaderes készülékek esetén downgrade-elhető volt a baseband. igaz, ezek közül összesen csak a BootNeuter és a fuzzyband a Cydiából telepíthető.

  11. @Jadeye: Látom nem sikerül megértetni magam, nyilván nem fogalmaztam egyértelműen, amiért elnézést kérek. Már a baseband-es dolgot is említettem, tudtam róla annak idején, de most, jailbreak előtt újra utánanéztem a dolgoknak. Jelenleg, iPhone 6-nál nem is igen találtam rá módot (kivéve a MAC adress módosítást, de az nem érint, és azt vissza lehet csinálni), és egészen a hétvégéig nem is tudtam (tudtunk?) róla, hogy ez lehetséges, amíg többen tönkre nem tették a mobiljukat. Ezután egy fejlesztő össze is dobott egy tweaket (KilliOS), amivel bebizonyította, hogy elő lehet idézni – méghozzá elég könnyen – permanent bricket. De ezek szerint ez csak számomra volt újdonság, szóval mégegyszer elnézést kérek.

Írd le a véleményedet! (Moderációs elveinket ide kattintva olvashatod.)

Hozzászólás írásához be kell jelentkezned!