iOS APP之本地數據存儲(譯)

jopen 8年前發布 | 33K 次閱讀 IOS CoreData 數據存儲 iOS開發 移動開發

最近工作中完成了項目的用戶信息本地存儲,查閱了一些本地存儲加密方法等相關資料。期間發現了一個來自印度理工學院(IIT)的信息安全工程師的個人博客,寫了大量有關iOS Application security的文章。

個人感覺寫的還不錯,實用性比較強,加之閱讀難度不大,于是趁著工作日無聊之際,小翻譯了一篇。

原文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,廢話不多說。上譯文:

iOS應用安全(20) - 本地數據存儲

-2013.10.26

-發表自 Prateek Gianchandani

在這篇文章中,我們將要看看應用中存儲數據到本地的一些不同的方法以及這些方法的安全性。

我們將會在一個demo上這些這些測試,你可以從我的 github 賬號上下載這個例子程序。對于CoreData的例子,你可以從 下載例子程序。本例有一個不同點就是我們將會在模擬器上運行這些應用,而不是在設備上運行。這樣做的目的是為了證明在前面文章中的操作都可以通過Xcode來把這些應用運行在模擬器上。當然,你也可以使用 前面文章中的步驟 把這應用安裝到設備上。

NSUserDefaults

保存用戶信息和屬性的一個非常普通的方法就是使用NSUserDefaults。保存在NSUserDefaults中的信息在 你的應用關閉后再次打開之后依然存在。保存信息到NSUserDefaults的一個例子就是保存用戶是否已登錄的狀態。我們把用戶的登錄狀態保存到 NSUserDefaults以便用戶關閉應用再次打開應用的時候,應用能夠從NSUserDefaults獲取數據,根據用戶是否登錄展示不同的界面。 有些應用也用這個功能來保存機密數據,比如用戶的訪問令牌,以便下次應用登錄的時候,它們能夠使用這個令牌來再次認證用戶。

從我的 github 可以下載例子應用,運行起來。你可以得到下面的界面,現在輸入一些信息到與NSUserDefaults相關的文本框,然后點擊下面的“Save in NSUserDefaults”。這樣數據就保存到NSUserDefaults了。

許多人不知道的是保存到NSUserDefaults的數據并沒有加密,因此可以很容易的從應用的包中看到。 NSUserDefaults被存在一個以應用的bundle id為名稱的plist文件中。 首先,我們需要找到我們應用的bundle id。因為我們在模擬器上運行,我們可以在/Users/$username/Library/Application Support/iPhone Simulator/$ios version of simulator/Applications/找到應用。我這的路徑是:“Users/prateekgianchandani/Library /Application Support/iPhone Simulator/6.1/Applications”。

一旦我們找到那個目錄,我們可以看到一堆應用。我們可以用最近修改的日期找到我們的應用,因為它是最近修改的。

進入到應用的bundle里面。通過NSUserDefaults保存的數據都可以在如下圖所示的Library -> Preferences -> $AppBundleId.plist文件中找到。

打開這個plist文件,我們可以清楚的看到這個文件的內容。

有時候,plist文件會以二進制格式保存,因此可能第一下看到會覺得不可讀。你可以用plutil工具把它轉成xml格式,或者直接用iExplorer在設備上查看。

Plist 文件

另一種保存數據普遍用的方法就是plist文件。 Plist文件應該始終被用來保存那些非機密的文件,因為它們沒有加密,因此即使在非越獄的設備上也非常容易被獲取 。已經有 漏洞 被爆出來,大公司把機密數據比如訪問令牌,用戶名和密碼保存到plist文件中。在下面的demo中,我們輸入一些信息并保存到plist文件。

下面是把數據保存到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文件指定路徑。我們可以搜索整個應用的所有plist文件。在這里,我們找到一個叫做userinfo.plist的文件。

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

CoreData和Sqlite文件

因為CoreData內部使用Sqlite來保存信息,因此我們這里將只會介紹下CoreData。如果你不知道什么是CoreData,下面是從蘋果文檔介紹CoreData截的圖。

因此,基本上,CoreData可以用來創建一個model,管理不同對象的關系,把數據保存到本地,然后當你查詢的時候從本地緩存中獲取它們。本例中,我們將使用一個demo,位于 github 。運行起來,你會發現它只是一個簡單的RSS feed。

這個應用用CoreData保存數據。一個非常重要的一點就是CoreData內部使用sql,因此所有文件都以.db文件保存。我們到這個app的bundle中去看看。 在這個app的bundle中,你可以看到那里有一個MyCoreData.sqlite的文件。

我們可以用sqlite3分析。我這slite文件的地址是:~/Library/Application Support/iPhone Simulator/6.1/Applications/51038055-3CEC-4D90-98B8-A70BF12C7E9D/Documents.

我們可以看到,這里有個叫做ZSTORIES的表。在Core Data中,每個表名開頭都會被追加一個Z。這意味著真正的實體名稱是STORIES,如我們在工程的源碼文件看到的那樣。

我們可以非常容易的導出這個表的所有值。請卻表headers的狀態是on。

正如我們看到的那樣,默認的,保存在CoreData的數據都是沒有加密的,因此可以輕易的被取出。因此,我們不應該用 CoreData保存機密數據。 有些庫包裝了一下CoreData, 聲稱能夠保存加密數據。也有些庫能夠把數據加密保存到設備上,不過不使用CoreData。例如,Salesforce Mobile SDK 就使用了一個被稱為 SmartStore 的功能來把加密數據以"Soups"的形式保存到設備上。

Keychain

有些開發者不太喜歡把數據保存到Keychain中,因為實現起來不那么直觀。 不過,把信息保存到Keychain中可能是非越獄設備上最安全的一種保存數據的方式了 。 而在越獄設備上, 沒有任何事情 是安全的。 這篇文章 展 示了使用一個簡單的wrapper類,把數據保存到keychain是多么的簡單。使用這個wrapper來保存數據到keychain就像把數據保存到 NSUserDefaults那么簡單。下面就是一段把字符串保存到keychain的代碼。請注意和使用NSUserDefaults的語法非常類似。

PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings];
[bindings setObject:@"XYZ" forKey:@"authToken"];
 下面是一段從keychain中取數據的代碼。
PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings];
NSLog(@"Auth token is %@",[bindings objectForKey:@"authToken"]]);

一些小技巧

正如之前討論過的那樣,沒有任何信息在越獄設備上是安全的。攻擊者能夠拿到Plist文件,導出整個keychain, 替換 方法實現,并且攻擊者能做他想做的任何事情。 不過開發者能夠使用一些小技巧來使得腳本小子從應用獲得信息變得更難。 比如把 文件加密 放到本地設備上。 這里 這篇文章詳細的討論了這一點。或者你可以 使得攻擊者更難理解你的信息 。比如考慮要把某個用戶的認證令牌(authentication token)保存到keychain當中,腳本小子可能就會導出keychain中的這個數據,然后試圖劫持用戶的會話。我們只需再把這個認證令牌字符串 反轉 一下(reverse),然后再保存到keychain中,那么攻擊者就不太可能會知道認證令牌是反轉保存的。當然,攻擊者可以追蹤你的應用的每一個調用,然后理解到這一點,但是, 一個如此簡單的技術就能夠讓腳本小子猜足夠的時間,以至于他們會開始尋找其它應用的漏洞 。另一個 簡單技巧 就是在每個真正的值保存之前 都追加一個常量字符串

在接下來的文章里,我們將討論使用GDB進行運行時分析。

譯 者:MysticCoder

出 處: http://www.cnblogs.com/mysticCoder/

關于作者:專注于iOS項目開發。如有問題或建議,請多多賜教!

版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。

特此聲明:所有評論和私信都會在第一時間回復。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我

聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角 【推薦】 一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!

來自: http://www.cnblogs.com/mysticCoder/p/5121671.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!