iOS APP之本地数据存储(译)
最近工作中完成了項(xiàng)目的用戶(hù)信息本地存儲(chǔ),查閱了一些本地存儲(chǔ)加密方法等相關(guān)資料。期間發(fā)現(xiàn)了一個(gè)來(lái)自印度理工學(xué)院(IIT)的信息安全工程師的個(gè)人博客,寫(xiě)了大量有關(guān)iOS Application security的文章。
? 個(gè)人感覺(jué)寫(xiě)的還不錯(cuò),實(shí)用性比較強(qiáng),加之閱讀難度不大,于是趁著工作日無(wú)聊之際,小翻譯了一篇。
原文IOS Application Security Part 20 – Local Data Storage (NSUserDefaults, CoreData, Sqlite, Plist files)地址http://highaltitudehacks.com/2013/10/26/ios-application-security-part-20-local-data-storage-nsuserdefaults/
真的不難,還是建議大家閱讀原文。OK,廢話(huà)不多說(shuō)。上譯文:
iOS應(yīng)用安全(20) - 本地?cái)?shù)據(jù)存儲(chǔ)
-2013.10.26
-發(fā)表自Prateek Gianchandani
? 在這篇文章中,我們將要看看應(yīng)用中存儲(chǔ)數(shù)據(jù)到本地的一些不同的方法以及這些方法的安全性。
我們將會(huì)在一個(gè)demo上這些這些測(cè)試,你可以從我的github賬號(hào)上下載這個(gè)例子程序。對(duì)于CoreData的例子,你可以從這下載例子程序。本例有一個(gè)不同點(diǎn)就是我們將會(huì)在模擬器上運(yùn)行這些應(yīng)用,而不是在設(shè)備上運(yùn)行。這樣做的目的是為了證明在前面文章中的操作都可以通過(guò)Xcode來(lái)把這些應(yīng)用運(yùn)行在模擬器上。當(dāng)然,你也可以使用前面文章中的步驟把這應(yīng)用安裝到設(shè)備上。
NSUserDefaults
保存用戶(hù)信息和屬性的一個(gè)非常普通的方法就是使用NSUserDefaults。保存在NSUserDefaults中的信息在 你的應(yīng)用關(guān)閉后再次打開(kāi)之后依然存在。保存信息到NSUserDefaults的一個(gè)例子就是保存用戶(hù)是否已登錄的狀態(tài)。我們把用戶(hù)的登錄狀態(tài)保存到 NSUserDefaults以便用戶(hù)關(guān)閉應(yīng)用再次打開(kāi)應(yīng)用的時(shí)候,應(yīng)用能夠從NSUserDefaults獲取數(shù)據(jù),根據(jù)用戶(hù)是否登錄展示不同的界面。 有些應(yīng)用也用這個(gè)功能來(lái)保存機(jī)密數(shù)據(jù),比如用戶(hù)的訪(fǎng)問(wèn)令牌,以便下次應(yīng)用登錄的時(shí)候,它們能夠使用這個(gè)令牌來(lái)再次認(rèn)證用戶(hù)。
從我的github可以下載例子應(yīng)用,運(yùn)行起來(lái)。你可以得到下面的界面,現(xiàn)在輸入一些信息到與NSUserDefaults相關(guān)的文本框,然后點(diǎn)擊下面的“Save in NSUserDefaults”。這樣數(shù)據(jù)就保存到NSUserDefaults了。
許多人不知道的是保存到NSUserDefaults的數(shù)據(jù)并沒(méi)有加密,因此可以很容易的從應(yīng)用的包中看到。 NSUserDefaults被存在一個(gè)以應(yīng)用的bundle id為名稱(chēng)的plist文件中。 首先,我們需要找到我們應(yīng)用的bundle id。因?yàn)槲覀冊(cè)谀M器上運(yùn)行,我們可以在/Users/$username/Library/Application Support/iPhone Simulator/$ios version of simulator/Applications/找到應(yīng)用。我這的路徑是:“Users/prateekgianchandani/Library /Application Support/iPhone Simulator/6.1/Applications”。
一旦我們找到那個(gè)目錄,我們可以看到一堆應(yīng)用。我們可以用最近修改的日期找到我們的應(yīng)用,因?yàn)樗亲罱薷牡摹?/p>
進(jìn)入到應(yīng)用的bundle里面。通過(guò)NSUserDefaults保存的數(shù)據(jù)都可以在如下圖所示的Library -> Preferences -> $AppBundleId.plist文件中找到。
打開(kāi)這個(gè)plist文件,我們可以清楚的看到這個(gè)文件的內(nèi)容。
有時(shí)候,plist文件會(huì)以二進(jìn)制格式保存,因此可能第一下看到會(huì)覺(jué)得不可讀。你可以用plutil工具把它轉(zhuǎn)成xml格式,或者直接用iExplorer在設(shè)備上查看。
Plist 文件
另一種保存數(shù)據(jù)普遍用的方法就是plist文件。Plist文件應(yīng)該始終被用來(lái)保存那些非機(jī)密的文件,因?yàn)樗鼈儧](méi)有加密,因此即使在非越獄的設(shè)備上也非常容易被獲取。已經(jīng)有漏洞被爆出來(lái),大公司把機(jī)密數(shù)據(jù)比如訪(fǎng)問(wèn)令牌,用戶(hù)名和密碼保存到plist文件中。在下面的demo中,我們輸入一些信息并保存到plist文件。
下面是把數(shù)據(jù)保存到plist文件的代碼。
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *filePath = [documentsDirectory stringByAppendingString:@"/userInfo.plist"]; NSMutableDictionary* plist = [[NSMutableDictionary alloc] init]; [plist setValue:self.usernameTextField.text forKey:@"username"]; [plist setValue:self.passwordTextField.text forKey:@"passwprd"]; [plist writeToFile:filePath atomically:YES];如你所見(jiàn),我們能夠給plist文件指定路徑。我們可以搜索整個(gè)應(yīng)用的所有plist文件。在這里,我們找到一個(gè)叫做userinfo.plist的文件。
可以看到,它包含了我們剛剛輸入的用戶(hù)名/密碼的組合。
CoreData和Sqlite文件
因?yàn)镃oreData內(nèi)部使用Sqlite來(lái)保存信息,因此我們這里將只會(huì)介紹下CoreData。如果你不知道什么是CoreData,下面是從蘋(píng)果文檔介紹CoreData截的圖。
因此,基本上,CoreData可以用來(lái)創(chuàng)建一個(gè)model,管理不同對(duì)象的關(guān)系,把數(shù)據(jù)保存到本地,然后當(dāng)你查詢(xún)的時(shí)候從本地緩存中獲取它們。本例中,我們將使用一個(gè)demo,位于github。運(yùn)行起來(lái),你會(huì)發(fā)現(xiàn)它只是一個(gè)簡(jiǎn)單的RSS feed。
這個(gè)應(yīng)用用CoreData保存數(shù)據(jù)。一個(gè)非常重要的一點(diǎn)就是CoreData內(nèi)部使用sql,因此所有文件都以.db文件保存。我們到這個(gè)app的bundle中去看看。 在這個(gè)app的bundle中,你可以看到那里有一個(gè)MyCoreData.sqlite的文件。
我們可以用sqlite3分析。我這slite文件的地址是:~/Library/Application Support/iPhone Simulator/6.1/Applications/51038055-3CEC-4D90-98B8-A70BF12C7E9D/Documents.
我們可以看到,這里有個(gè)叫做ZSTORIES的表。在Core Data中,每個(gè)表名開(kāi)頭都會(huì)被追加一個(gè)Z。這意味著真正的實(shí)體名稱(chēng)是STORIES,如我們?cè)诠こ痰脑创a文件看到的那樣。
我們可以非常容易的導(dǎo)出這個(gè)表的所有值。請(qǐng)卻表headers的狀態(tài)是on。
正如我們看到的那樣,默認(rèn)的,保存在CoreData的數(shù)據(jù)都是沒(méi)有加密的,因此可以輕易的被取出。因此,我們不應(yīng)該用 CoreData保存機(jī)密數(shù)據(jù)。 有些庫(kù)包裝了一下CoreData, 聲稱(chēng)能夠保存加密數(shù)據(jù)。也有些庫(kù)能夠把數(shù)據(jù)加密保存到設(shè)備上,不過(guò)不使用CoreData。例如,Salesforce Mobile SDK 就使用了一個(gè)被稱(chēng)為SmartStore的功能來(lái)把加密數(shù)據(jù)以"Soups"的形式保存到設(shè)備上。
Keychain
有些開(kāi)發(fā)者不太喜歡把數(shù)據(jù)保存到Keychain中,因?yàn)閷?shí)現(xiàn)起來(lái)不那么直觀。不過(guò),把信息保存到Keychain中可能是非越獄設(shè)備上最安全的一種保存數(shù)據(jù)的方式了。而在越獄設(shè)備上,沒(méi)有任何事情是安全的。這篇文章展 示了使用一個(gè)簡(jiǎn)單的wrapper類(lèi),把數(shù)據(jù)保存到keychain是多么的簡(jiǎn)單。使用這個(gè)wrapper來(lái)保存數(shù)據(jù)到keychain就像把數(shù)據(jù)保存到 NSUserDefaults那么簡(jiǎn)單。下面就是一段把字符串保存到keychain的代碼。請(qǐng)注意和使用NSUserDefaults的語(yǔ)法非常類(lèi)似。
PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings]; [bindings setObject:@"XYZ" forKey:@"authToken"]; 下面是一段從keychain中取數(shù)據(jù)的代碼。 PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings]; NSLog(@"Auth token is %@",[bindings objectForKey:@"authToken"]]);一些小技巧
正如之前討論過(guò)的那樣,沒(méi)有任何信息在越獄設(shè)備上是安全的。攻擊者能夠拿到Plist文件,導(dǎo)出整個(gè)keychain,替換方法實(shí)現(xiàn),并且攻擊者能做他想做的任何事情。不過(guò)開(kāi)發(fā)者能夠使用一些小技巧來(lái)使得腳本小子從應(yīng)用獲得信息變得更難。比如把文件加密放到本地設(shè)備上。這里這篇文章詳細(xì)的討論了這一點(diǎn)。或者你可以使得攻擊者更難理解你的信息。比如考慮要把某個(gè)用戶(hù)的認(rèn)證令牌(authentication token)保存到keychain當(dāng)中,腳本小子可能就會(huì)導(dǎo)出keychain中的這個(gè)數(shù)據(jù),然后試圖劫持用戶(hù)的會(huì)話(huà)。我們只需再把這個(gè)認(rèn)證令牌字符串反轉(zhuǎn)一下(reverse),然后再保存到keychain中,那么攻擊者就不太可能會(huì)知道認(rèn)證令牌是反轉(zhuǎn)保存的。當(dāng)然,攻擊者可以追蹤你的應(yīng)用的每一個(gè)調(diào)用,然后理解到這一點(diǎn),但是,一個(gè)如此簡(jiǎn)單的技術(shù)就能夠讓腳本小子猜足夠的時(shí)間,以至于他們會(huì)開(kāi)始尋找其它應(yīng)用的漏洞。另一個(gè)簡(jiǎn)單技巧就是在每個(gè)真正的值保存之前都追加一個(gè)常量字符串。
在接下來(lái)的文章里,我們將討論使用GDB進(jìn)行運(yùn)行時(shí)分析。
?
譯 者:MysticCoder 出 處:http://www.cnblogs.com/mysticCoder/ 關(guān)于作者:專(zhuān)注于iOS項(xiàng)目開(kāi)發(fā)。如有問(wèn)題或建議,請(qǐng)多多賜教! 版權(quán)聲明:本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文鏈接。 特此聲明:所有評(píng)論和私信都會(huì)在第一時(shí)間回復(fù)。也歡迎園子的大大們指正錯(cuò)誤,共同進(jìn)步。或者直接私信我 聲援博主:如果您覺(jué)得文章對(duì)您有幫助,可以點(diǎn)擊文章右下角【推薦】一下。您的鼓勵(lì)是作者堅(jiān)持原創(chuàng)和持續(xù)寫(xiě)作的最大動(dòng)力!
?
轉(zhuǎn)載于:https://www.cnblogs.com/mysticCoder/p/5121671.html
總結(jié)
以上是生活随笔為你收集整理的iOS APP之本地数据存储(译)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 由于权限不足而无法读取配置文件出现的HT
- 下一篇: 昨天登陆页面,无法进入后台,今天攻克了