iOS應用程序安全(20)-本地數據存儲及其安全性(NSUserDefaults, CoreData, Sqlite, Plist 文件)(轉)

原文網址:http://resources.infosecinstitute.com/iOS-application-security-part-20-local-data-storage-nsuserdefaults-coredata-sqlite-plist-files/

版權聲明:自由轉載-非商用-保持署名

本文我們將看看應用在本地存儲數據有哪些方法以及這些不同方法的安全性。

我們將會在一個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/$iosversion 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文件的代碼。


[plain]

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];

[/plain]

如你所見,我們能夠給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的語法非常類似。

[plain]

PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings];

[bindings setObject:@"XYZ" forKey:@"authToken"];

[/plain]

下面是一段從keychain中取數據的代碼。

[plain]

PDKeychainBindings *bindings = [PDKeychainBindings sharedKeychainBindings];

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

[/plain]

一些小技巧

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

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

本文原文IOS Application Security Part 20 – Local Data Storage (NSUserDefaults, CoreData, Sqlite, Plist files)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章