Folytatódik a Pwnie jelöltek bemutatása, ezúttal a kliens-oldali kategória legnagyobb esélyese, Comex jailbreakme.com exploitja kerül röviden elemzésre. Ahogy azt a legötbben tudják, pusztán a jailbreakme.com oldal meglátogatásával el lehetett tüntetni a gyártói korlátozásokat az iOS 4.3.3-as verzióját futtató eszközökön. Ehhez Comex két hibát használt ki: egy, a MobileSafari PDF feldolgozóját érintő problémát, és egy nem megfelelő típuskonverzióból adódó sebezhetőséget a kernelben. Az exploitok létrehozásához használt kódokat nem rég publikálták, a Sogeti pedig részletesen kielemezte a PDF sebezhetőség kihasználásához alkalmazott módszereket, én is ez alapján igyekszem összefoglalni utóbbi exploit szépségeit.
Ahogy az a hibajegyből is kiderül, a PDF olvasó a FreeType betűkészletek, konkrétabban az Adobe Type 1 font programok feldolgozásakor hibázik. Ezek a "programocskák" mondják meg a PDF megjelenítőnek, hogy hogyan kell kirajzolni az egyes karaktereket.
A problémát a callothersubr Type 1 parancs okozza, amely PostScript szubrutinhívást végez. Ehhez paraméterül kapja a szubrutin nevét, argumentumait, és az argumentumok számát. Az argumentumszám negatívra állításával viszont elérhető, hogy a stack pointer az interpreter stackjén kívülre mutasson!
Az interpreter stackje egy T1_DecoderRec_ (ezt ajánlott megnyitni új lapon) struktúra adattagjaként jelenik meg a memóriában. A fenti hiba kihasználásával ennek a struktúrának a tartalma manipulálható, ezen kívül minden Type 1 program hozzáfér a sebezhető t1_decoder_parse_charstrings függvény x és y változóihoz. Az írás/olvasás műveletek azonban nem végezhetőek el közvetlenül, csak a Type 1 interpreteren keresztül, melynek utasításai csak korlátozott mozgásteret biztosítanak. Comex ennek ellenére sikeresen összegyűjtött néhány olyan utasítást, mellyel tetszőleges kódfuttatást érhetett el. Az adathozzáférés a következő parancsok felhasználásával történik:
- push: Konstans stack-re írása. A SP ellenőrzésre kerül végrehajtás előtt
- setcurrentpoint: Két szó beolvasása a stackről az x és y változókba. A SP nem kerül ellenőrzésre
- callothersubr #00: Az x és y változók stackre írása. A SP nem kerül ellenőrzésre, viszont a dekóder struktúrában flex_state!=0 && num_flex_vectors==7 -nek kell fennálnia a végrehajtáshoz
- callothersubr #42: A hibát triggerelő szubrutin-hívás
- hstem3, hmoveto, unknown15: SP állítás
- callothersubr #12: SP visszaállítása a stack tetejére
- callothersubr #20 és #21: Stacken lévő értékek összeadása és kivonsása
- callothersubr #23 és #24: Szavak írása a dekóder struktúra buildchar adattagjába
A dekóder struktúra egy adattagjának (valójában két szavának) beállítása így történhet:
push 1
push 2
setcurrentpoint ; x=1, y=2
; ... 8 parancs a callothersubr #0 előfeltételeinek beállításához ...
push 0xfxxxxxxx ; Egy negatív szám
push 0x2a ; 42
callothersubr ; hiba triggerelés, SP átállítás
; Ha itt push-olunk, már a stacken kívülre írunk!
; Úgy kell beállítani az SP-t, hogy 0-ra mutasson,
; vagy ne legyen probléma a push 0
callothersubr ; x és y stackre írása, az átállított SP szerint
Emellett természetesen szükség lehet memória olvasásra, aritmetikára, feltételes végrehajtásra, stb. Az élet tehát nem egyszerű, de Comex megoldotta - a hibakihasználás lényegében három lépcsőben zajlik:
- A T1_DecoderRec->parse_callback függvény pointer kiolvasása - Ennek alapján határozható meg az ASLR miatti címeltolás, valamint az, hogy éppen 4-es vagy 3GS típusú iPhone-on fut-e a program - a különböző készülékgenerációkban ugyanis más sorrendben helyezkednek el a betöltött könyvtárak, így két szimbólum címének összehasonlításával megállapítható a konkrét típus.
- ROP lánc generálás a készülék típusának megfelelően - A ROP stack a T1_DecoderRec->buildchar adattagban épül fel, ennek segítségével lesz kihasználva a jailbreakhez szükséges kernel hiba.
- Vezérlés átadása a T1_DecoderRec->parse_callback()-en keresztül - Stack pivoting és a parse_callback beállítása az első ROP gadgetre
Ezeknek a lépéseknek a végigjátszása x86-on sem lenne gyerekjáték, a fent vázolt "furcsa gépet" programozva pedig egyszerre tűnik gyönyörűnek és hátborzongatónak a feladat. A GitHubon jól látszik, hogy a mű megalkotásához (ide értve a kernel exploit összegyógyítását is) nagyjából egy éven át kellett nyúzni az iOS-t, de az eredmény magáért beszél: a jailbreakme.com-ot használva több (tíz?)ezren vehették át az irányítást kütyüik felett, lényegében készülékfüggetlenül, megbízhatóan, egyetlen szokatlan parancs begépelése nélkül.