iOS APP之本地?cái)?shù)據(jù)存儲(chǔ)(譯)

最近工作中完成了項(xiàng)目的用戶信息本地存儲(chǔ)骑歹,查閱了一些本地存儲(chǔ)加密方法等相關(guān)資料叁温。期間發(fā)現(xiàn)了一個(gè)來(lái)自印度理工學(xué)院(IIT)的信息安全工程師的個(gè)人博客回俐,寫了大量有關(guān)iOS Application security的文章镊绪。
  個(gè)人感覺寫的還不錯(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,廢話不多說(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)行。這樣做的目的是為了證明在前面文章中的操作都可以通過Xcode來(lái)把這些應(yīng)用運(yùn)行在模擬器上吆玖。當(dāng)然筒溃,你也可以使用前面文章中的步驟把這應(yīng)用安裝到設(shè)備上。

NSUserDefaults
  保存用戶信息和屬性的一個(gè)非常普通的方法就是使用NSUserDefaults沾乘。保存在NSUserDefaults中的信息在你的應(yīng)用關(guān)閉后再次打開之后依然存在怜奖。保存信息到NSUserDefaults的一個(gè)例子就是保存用戶是否已登錄的狀態(tài)。我們把用戶的登錄狀態(tài)保存到NSUserDefaults以便用戶關(guān)閉應(yīng)用再次打開應(yīng)用的時(shí)候翅阵,應(yīng)用能夠從NSUserDefaults獲取數(shù)據(jù)歪玲,根據(jù)用戶是否登錄展示不同的界面。有些應(yīng)用也用這個(gè)功能來(lái)保存機(jī)密數(shù)據(jù)掷匠,比如用戶的訪問令牌滥崩,以便下次應(yīng)用登錄的時(shí)候,它們能夠使用這個(gè)令牌來(lái)再次認(rèn)證用戶讹语。
  從我的github可以下載例子應(yīng)用钙皮,運(yùn)行起來(lái)。你可以得到下面的界面募强,現(xiàn)在輸入一些信息到與NSUserDefaults相關(guān)的文本框株灸,然后點(diǎn)擊下面的“Save in NSUserDefaults”崇摄。這樣數(shù)據(jù)就保存到NSUserDefaults了擎值。


  許多人不知道的是保存到NSUserDefaults的數(shù)據(jù)并沒有加密,因此可以很容易的從應(yīng)用的包中看到逐抑。NSUserDefaults被存在一個(gè)以應(yīng)用的bundle id為名稱的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)樗亲罱薷牡摹?br>

  進(jìn)入到應(yīng)用的bundle里面贤徒。通過NSUserDefaults保存的數(shù)據(jù)都可以在如下圖所示的Library -> Preferences -> $AppBundleId.plist文件中找到芹壕。

  打開這個(gè)plist文件,我們可以清楚的看到這個(gè)文件的內(nèi)容接奈。

  有時(shí)候踢涌,plist文件會(huì)以二進(jìn)制格式保存,因此可能第一下看到會(huì)覺得不可讀序宦。你可以用plutil工具把它轉(zhuǎn)成xml格式睁壁,或者直接用iExplorer在設(shè)備上查看。

Plist 文件
  另一種保存數(shù)據(jù)普遍用的方法就是plist文件互捌。Plist文件應(yīng)該始終被用來(lái)保存那些非機(jī)密的文件潘明,因?yàn)樗鼈儧]有加密,因此即使在非越獄的設(shè)備上也非常容易被獲取疫剃。已經(jīng)有漏洞被爆出來(lái)钉疫,大公司把機(jī)密數(shù)據(jù)比如訪問令牌,用戶名和密碼保存到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];

如你所見城菊,我們能夠給plist文件指定路徑。我們可以搜索整個(gè)應(yīng)用的所有plist文件碉克。在這里凌唬,我們找到一個(gè)叫做userinfo.plist的文件。


  可以看到漏麦,它包含了我們剛剛輸入的用戶名/密碼的組合客税。

CoreData和Sqlite文件
  因?yàn)镃oreData內(nèi)部使用Sqlite來(lái)保存信息,因此我們這里將只會(huì)介紹下CoreData撕贞。如果你不知道什么是CoreData更耻,下面是從蘋果文檔介紹CoreData截的圖。


  因此捏膨,基本上秧均,CoreData可以用來(lái)創(chuàng)建一個(gè)model食侮,管理不同對(duì)象的關(guān)系,把數(shù)據(jù)保存到本地目胡,然后當(dāng)你查詢的時(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è)表名開頭都會(huì)被追加一個(gè)Z。這意味著真正的實(shí)體名稱是STORIES淘邻,如我們?cè)诠こ痰脑创a文件看到的那樣茵典。

  我們可以非常容易的導(dǎo)出這個(gè)表的所有值。請(qǐng)卻表headers的狀態(tài)是on宾舅。

  正如我們看到的那樣统阿,默認(rèn)的,保存在CoreData的數(shù)據(jù)都是沒有加密的筹我,因此可以輕易的被取出扶平。因此,我們不應(yīng)該用 CoreData保存機(jī)密數(shù)據(jù)蔬蕊。 有些庫(kù)包裝了一下CoreData, 聲稱能夠保存加密數(shù)據(jù)结澄。也有些庫(kù)能夠把數(shù)據(jù)加密保存到設(shè)備上,不過不使用CoreData岸夯。例如麻献,Salesforce Mobile SDK 就使用了一個(gè)被稱為SmartStore的功能來(lái)把加密數(shù)據(jù)以"Soups"的形式保存到設(shè)備上。

Keychain
  有些開發(fā)者不太喜歡把數(shù)據(jù)保存到Keychain中猜扮,因?yàn)閷?shí)現(xiàn)起來(lái)不那么直觀勉吻。不過,把信息保存到Keychain中可能是非越獄設(shè)備上最安全的一種保存數(shù)據(jù)的方式了破镰。而在越獄設(shè)備上餐曼,沒有任何事情是安全的。這篇文章展示了使用一個(gè)簡(jiǎn)單的wrapper類鲜漩,把數(shù)據(jù)保存到keychain是多么的簡(jiǎn)單源譬。使用這個(gè)wrapper來(lái)保存數(shù)據(jù)到keychain就像把數(shù)據(jù)保存到NSUserDefaults那么簡(jiǎn)單。下面就是一段把字符串保存到keychain的代碼孕似。請(qǐng)注意和使用NSUserDefaults的語(yǔ)法非常類似踩娘。

PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings];
[bindings setObject:@"XYZ" forKey:@"authToken"];

下面是一段從keychain中取數(shù)據(jù)的代碼。

PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings];
NSLog(@"Auth token is %@",[bindings objectForKey:@"authToken"]]);

一些小技巧
  正如之前討論過的那樣喉祭,沒有任何信息在越獄設(shè)備上是安全的养渴。攻擊者能夠拿到Plist文件,導(dǎo)出整個(gè)keychain泛烙,替換方法實(shí)現(xiàn)理卑,并且攻擊者能做他想做的任何事情。不過開發(fā)者能夠使用一些小技巧來(lái)使得腳本小子從應(yīng)用獲得信息變得更難蔽氨。比如把文件加密放到本地設(shè)備上藐唠。這里這篇文章詳細(xì)的討論了這一點(diǎn)○木浚或者你可以使得攻擊者更難理解你的信息宇立。比如考慮要把某個(gè)用戶的認(rèn)證令牌(authentication token)保存到keychain當(dāng)中,腳本小子可能就會(huì)導(dǎo)出keychain中的這個(gè)數(shù)據(jù)自赔,然后試圖劫持用戶的會(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ì)開始尋找其它應(yīng)用的漏洞尔苦。另一個(gè)簡(jiǎn)單技巧就是在每個(gè)真正的值保存之前都追加一個(gè)常量字符串
  在接下來(lái)的文章里行施,我們將討論使用GDB進(jìn)行運(yùn)行時(shí)分析。

譯  者:MysticCoder
出  處:http://www.cnblogs.com/mysticCoder/
關(guān)于作者:專注于iOS項(xiàng)目開發(fā)蛾号。如有問題或建議,請(qǐng)多多賜教展运!
版權(quán)聲明:本文版權(quán)歸作者和博客園共有活逆,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明拗胜,且在文章頁(yè)面明顯位置給出原文鏈接。
特此聲明:所有評(píng)論和私信都會(huì)在第一時(shí)間回復(fù)埂软。也歡迎園子的大大們指正錯(cuò)誤,共同進(jìn)步勘畔∷模或者直接私信我

聲援博主:如果您覺得文章對(duì)您有幫助,可以點(diǎn)擊文章右下角【推薦】一下炫七。您的鼓勵(lì)是作者堅(jiān)持原創(chuàng)和持續(xù)寫作的最大動(dòng)力!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末懦尝,一起剝皮案震驚了整個(gè)濱河市壤圃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伍绳,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,002評(píng)論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件效床,死亡現(xiàn)場(chǎng)離奇詭異权谁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)旺芽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)运嗜,“玉大人悯舟,你說(shuō)我怎么就攤上這事〉衷酰” “怎么了岭参?”我有些...
    開封第一講書人閱讀 169,787評(píng)論 0 365
  • 文/不壞的土叔 我叫張陵演侯,是天一觀的道長(zhǎng)利耍。 經(jīng)常有香客問我盔粹,道長(zhǎng)隘梨,這世上最難降的妖魔是什么舷嗡? 我笑而不...
    開封第一講書人閱讀 60,237評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮捻脖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘中鼠。我一直安慰自己可婶,他們只是感情好援雇,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評(píng)論 6 398
  • 文/花漫 我一把揭開白布惫搏。 她就那樣靜靜地躺著,像睡著了一般筐赔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茴丰,一...
    開封第一講書人閱讀 52,821評(píng)論 1 314
  • 那天贿肩,我揣著相機(jī)與錄音,去河邊找鬼尸曼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛冤竹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鹦蠕,決...
    沈念sama閱讀 41,236評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼钟病,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了肠阱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤走趋,失蹤者是張志新(化名)和其女友劉穎噪伊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姨伟,經(jīng)...
    沈念sama閱讀 46,716評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豆励,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評(píng)論 3 343
  • 正文 我和宋清朗相戀三年肆糕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诚啃。...
    茶點(diǎn)故事閱讀 40,928評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡始赎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出造垛,到底是詐尸還是另有隱情,我是刑警寧澤办斑,帶...
    沈念sama閱讀 36,583評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站乡翅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏尚洽。R本人自食惡果不足惜靶累,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望潮酒。 院中可真熱鬧凛忿,春花似錦竞川、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)戈咳。三九已至壕吹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耳贬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工顷蟆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腐魂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,378評(píng)論 3 379
  • 正文 我出身青樓削樊,卻偏偏與公主長(zhǎng)得像兔毒,于是被迫代替她去往敵國(guó)和親沛硅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绕辖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • keychain app官方鏈接 重要的事情說(shuō)三遍 使用keychain group的時(shí)候仪际,測(cè)試一定要使用真機(jī)! ...
    Rxiaobing閱讀 3,210評(píng)論 1 5
  • 數(shù)據(jù)存儲(chǔ) sqlite中插入特殊字符的方法和接收到處理方法肯适。 除’其他的都是在特殊字符前面加“/”成榜,而 ' -> ...
    b485c88ab697閱讀 7,325評(píng)論 2 32
  • 這個(gè)世界上有關(guān)于青春的迷茫誰(shuí)都有過,這不我也來(lái)了…… 這兩天被兩個(gè)問題困擾一個(gè)是有關(guān)于獨(dú)立赎婚,一個(gè)是有關(guān)于興趣。無(wú)論...
    小張張大皮皮閱讀 165評(píng)論 0 0
  • 我們對(duì)那些高大的宏偉的東西 習(xí)慣性的會(huì)肅然起敬 但其實(shí)我們並不知道自己在尊敬什麼
    憨憨爹閱讀 111評(píng)論 0 0
  • 我一直喜歡的一本雜志 青春美文里有一個(gè)欄目是 微微道來(lái)。 一直是 那一個(gè)女子在寫撩嚼。我很喜歡她的文字。后來(lái)關(guān)注...
    水弋月閱讀 282評(píng)論 0 2