Az alábbi cikket Ys. írta a 0x90 blogon, és mivel a cikksorozata kapcsolódik az iPhone-hoz, mi érdekesnek gondoljuk a számotokra is, így ezeket engedelmével egymás után át is emelnénk ide, a Szifonra.
***
Ez a mai rész is kicsit ki fog lógni az eddigi vonalból, ugyanis most az iPhone-okban és iPadekben lévő NAND flash-t vesszük szemügyre. Ne kedvetlenítsen el senkit az, hogy most nem fogunk gdb-vel meg disassemblerrel varázsolni: komoly hatásai vannak a témának az alkalmazások biztonságára.
A NAND flash fantasztikus találmány és mobileszközökben sokkal inkább használható, mint a hagyományos, tányéros-fejes-motoros kialakítású mágneses háttértárolók (ezeket az eszközöket a köznyelvben vinyónak is nevezik): nem tartalmaz mozgó alkatrészeket, emiatt sokkal ellenállóbb a környezeti hatásoknak és jóval kevesebbet fogyaszt, azonkívül jóval magasabb adatsűrűséget lehet elérni rajta, pluszban még olcsóbb is előállítani nagy mennyiségben. Kész főnyeremény gyártási szempontból.
A fenit előnyöknek azonban vannak meglehetősen komoly hátrányai is: ezek közül az egyik legfontosabb az, hogy a NAND flash-ben jóval magasabb a hibás elemi tárolóegységek (cellák) száma: ezek egy része már a gyártási folyamat során “kerül bele” az eszközbe, a többi meg az üzemszerű használat során. A gyártók tesztelik a legyártott darabokat, mielőtt kitolnák őket a kapun és a detektált hibás cellákat megjelölik az eszköz egy speciális területén egy listában, hogy később ne akarjon beléjük senki adatot rakni. Erről még lesz szó a későbbiekben.
A másik komoly hátránya a technológiának a meglepően alacsony újraírhatóság: függ a konkrét érték (illetve a függvény, ami megmondja a meghibásodási valószínűséget az írások számának függvényében) a gyártótól, de nagyságrendileg 10.000 és 100.000 közötti újraírást bír ki egy-egy cella. Egy-egy cellába a technológia fejlődésével egyre több és több bitnyi adatot tuszkolnak bele a gyártók: a technológia hajnalán egy bitet tárolt egy cella (ezeket Single Level Cell-nek, azaz SLC-nek hívják), most már eljutottunk oda, hogy 2-3 bitnyi infomáció is tárolható bennük (Multi Level Cell, MLC). A növekvő adatsűrűség azonban érzékenyebbé teszi az eszközt az öregedésre, MLC technológiájú cellák esetében már csak 10.000 körüli az újraírások száma. Ez döbbenetesen kevés.
Fontos észben tartani, hogy a hagyományos merevlemezekkel ellentétben a NAND tárolókból nem lehet tetszőleges elemi cellát kinyerni, azaz nem RAM: az adatokat allokációs egységekben vagy lapokban (allocation unit és page) tartják nyilván. Egy-egy ilyen lap mérete 512 és 8192 byte között van tipikusan, a kapacitással együtt szokott növekedni. A felhasználói élmény szempontjából azonban ez sok mindent nem befolyásol: a flash elképesztően alacsony válaszideje és átviteli sebessége elfedi ezt a limitációt. Törlési szempontból több lapot magasabb szinten kezelnek együtt, ezeket az egységeket blokkoknak hívják: egy-egy blokk tipikusan jóval nagyobb, mint a mágneses merevlemezek egy-egy szektora.
Az iPhone-okban található flash fizikai tulajdonságait a /private/var/mobile/Library/Logs/ADDataStore.sqlitedb adatbázis tartalmazza:
white-iPhone:/private/var/mobile/Library/Logs root# sqlite3 ADDataStore.sqlitedb
SQLite version 3.7.2
Enter “.help” for instructions
sqlite> .mode line
sqlite> select * from Scalars;
[…]
key = com.apple.NANDInfo.NumVirtualBlocks
daysSince1970 = 15504
value = 1952
key = com.apple.NANDInfo.PagesPerVirtualBlock
daysSince1970 = 15504
value = 1024
key = com.apple.NANDInfo.BytesPerPage
daysSince1970 = 15504
value = 8192
key = com.apple.NANDInfo.NumLogicalReads
daysSince1970 = 15504
value = 1818078
key = com.apple.NANDInfo.NumLogicalWrites
daysSince1970 = 15504
value = 1386756
key = com.apple.NANDInfo.NumFreeVirtualBlocks
daysSince1970 = 15504
value = 1573
key = com.apple.NANDInfo.NumWearLevelOps
daysSince1970 = 15504
value = 6937
key = com.apple.NANDInfo.NumPhysicalReads
daysSince1970 = 15504
value = 2851387
key = com.apple.NANDInfo.NumPhysicalWrites
daysSince1970 = 15504
value = 2475079
key = com.apple.NANDInfo.NumPhysicalErases
daysSince1970 = 15504
value = 5455
[…]
Amikor írunk az eszközre, a blokkot alkotó lapok sorfolytonosan íródnak bele a cellákba. Lemezműveletek szempontjából az alábbiak az egységek:
- Olvasás: lap
- Írás: lap
- Törlés: blokk(!)
Az utóbbihoz némi magyarázat. A NAND flash különbözik a hagyományos merevlemezektől abban is, hogy nem szimmetrikus a nullák egy egyesek közötti átmenet – a vinyón a fej egyszerűen átüti a vonatkozó adategységet és csókolom. A NAND flashben ezzel szemben bitszintű 1-esből 0-ra lehet csak “olcsón” változtatni, fordítva kizárólag úgy lehet menni, hogy az egész blokkot feltöltjük 1-esekkel (azaz töröljük), majd a maradék 1-est visszaütjük 0-ra, kivéve azt a bitet, amit változtatni szeretnénk. Ha tehát a b1001-ből (0x09) szeretnénk b1101-et csinálni (0x0D), akkor első lépésben feltöltjük b1111-gyel a vonatkozó adattároló egységet, majd egy bitet átütünk. Ez pedig, ha hozzávesszük a limitált újraírhatóságot, igencsak drágává teszi a “sok kicsit írunk”-megközelítést.
A gyártók is tudják ezt a limitációt, éppen ezért mindent megtesznek azért, hogy ennek a jelenségnek a hatását a lehető legjobban szétterítsék az eszköz cellái között. A NAND flash tárolókon saját szoftver fut, ami gyakorlatilag egy köztes réteget képez a hagyományos fájlrendszer és a fizikai réteg között: két legfontosabb feladata a rossz cellák listájának karbantartása és az, hogy a gyakran írt adatokat folyamatosan “áramoltassa” az eszközben valamilyen algoritmus szerint, hogy szétterítse a sokszori írás hatását.
Két módszert használnak a fenti jelenségre a gyártók: az egyik a hagyományos hibajavító kódolás (Error Correcting Code, ECC), a másik pedig a wear levelingnek nevezett technika, ami szétteríti az írásokat az eszköz lehető legszélesebb tartományában.
A fenti jelenség az oka annak, hogy hagyományos naplózó fájlrendszert (Ext3, Ext4, NTFS, HFS stb.) nagyon nem fair rárakni ilyen eszközökre, ugyanis a napló írása folyamatosan gyilkolja a cellákat. Sok eszköz a belső NAND flash védelmére YAFFS(2)-t használ.
Milyen hatásai van mindennek az alkalmazások biztonságára? Három dolgot írtam fel, gondolatébresztőnek.
- Az iOS-ben a NAND flash tulajdonságai miatt (is) ennyire bonyolult a titkosítás megvalósítása és az oprendszer ahol lehet, elkerüli az adatok törlését. Adatvisszanyerési és forensic szempontból ez igen fontos dolog.
- Az alkalmazások, amelyek pl. sqlite adatbázisban tartják nyilván a dolgaikat, komoly extramunkával tudják csak elérni, hogy fizikailag semmisüljön meg az általuk beleírt és törölni kívánt rekord.
- Ha már egyszer rátettél valamit a fájlrendszerre az alkalmazásoddal, akkor azt nagyon nehéz kiszedni onnét úgy, hogy ne lehessen visszanyerni valahogy, ha ellopják az eszközt. Gondold meg jól, hogy mit írsz ki.
No comment yet, add your voice below!