“iOS應(yīng)用安全權(quán)威指南”讀書筆記
????????“第一部分”為iOS基礎(chǔ)辫樱,共包括一爹凹、二姆泻、三章
第一章:iOS安全模型
? ? ? ? App Store對開發(fā)者來說,應(yīng)用程序的審核流程是令人沮喪的黑箱操作届垫。蘋果的審核流程和方法并不對外公開,有時候你搞不清楚什么功能允許使用全释,什么功能禁止使用装处。蘋果提供了正式的知道手冊(https://developer.apple.com/appstore/resources/approval/guidelines.html),但是遵守了指導(dǎo)的應(yīng)用同樣會被拒絕。
? ? ? ? 蘋果使用App Store來控制和限制iOS平臺上應(yīng)用程序的功能,這就意味著如果想要實現(xiàn)某些特定的功能妄迁,唯一的手段就是將設(shè)備越獄或騙過應(yīng)用商店的審查寝蹈。
? ? ? ? 官方的應(yīng)用審查永遠無法抓到那些鉆空子的惡意程序,所以需要另外一套高效的機制登淘,來阻止惡意程序破壞整個操作系統(tǒng)的安全箫老。
? ? ? ? 先來看一下iOS基本的安全組件是如何阻止惡意攻擊和保護數(shù)據(jù)的。
安全啟動
? ? ? ? 當啟動一臺iOS設(shè)備時(開機)黔州,系統(tǒng)首先會從只讀的引導(dǎo)ROM中讀取初始化指令耍鬓,即系統(tǒng)引導(dǎo)程序。這個引導(dǎo)ROM包含蘋果官方權(quán)威認證的公鑰流妻,它會驗證底層啟動加載器(LLB)的簽名牲蜀,一旦通過驗證就啟動它(它指LLB)。LLB會做一些基礎(chǔ)工作绅这,然后驗證第二級引導(dǎo)程序iBoot涣达。iBoot啟動后,設(shè)備就可以進入恢復(fù)模式或啟動內(nèi)核证薇。在iBoot驗證完內(nèi)核簽名的合法性之后峭判,整個啟動程序進入正軌:加載驅(qū)動程序、檢驗設(shè)備棕叫、啟動系統(tǒng)守護進程林螃。
? ? ? ? 這個信任鏈確保所有的系統(tǒng)組件都由蘋果寫入、簽名俺泣、分發(fā)疗认。應(yīng)用程序啟動時也會用信任鏈去審查簽名。所有的應(yīng)用都必須直接或間接由蘋果簽名伏钠。
? ? ? ? 越獄的工作原理正是攻擊這一信任鏈横漏。越獄工作的作者需要找到這一信任鏈條上的漏洞,從而禁掉鏈條中負責(zé)驗證的組件熟掂。破解引導(dǎo)ROM通常是最可取的方式缎浇,因為該組件不會因蘋果今后的軟件更新而改變。
沙盒機制
? ? ? ? 蘋果的沙盒機制赴肚,歷史上被稱為安全帶素跺,是一種基于FreeBSD系統(tǒng)TrustedBSD框架的強制訪問控制(MAC)機制。它采用一種類似Lisp的配置語言來描述哪些資源系統(tǒng)可以訪問誉券,哪些禁止訪問指厌。這些資源主要包括文件、系統(tǒng)服務(wù)踊跟、網(wǎng)絡(luò)連接踩验、內(nèi)存資源等。
? ? ? ? MAC機制不同與傳統(tǒng)的訪問控制機制(比如自助訪問控制(DAC)),它不允許主體操作對象箕憾。DAC最常見的形式就是UNIX系統(tǒng)的用戶牡借、組和其他權(quán)限,所有這些都可以被授予讀袭异、寫钠龙、或執(zhí)行的權(quán)限。在DAC系統(tǒng)中扁远,用戶如果擁有一個對象的所有權(quán)俊鱼,也就擁有該對象的修改權(quán)限。
? ? ? ? 在OS X中你可以部分控制應(yīng)用程序的沙盒功能畅买,但是在iOS平臺中并闲,一般只能訪問應(yīng)用程序的包目錄:應(yīng)用可以讀寫儲存在該位置的文件。(也有例外谷羞,圖片在應(yīng)用程序包目錄之外帝火,但第三方應(yīng)用程序還是可以直接訪問)
? ? ? ? 安卓的訪問機制與MAC不同,安卓實現(xiàn)了一個更加傳統(tǒng)的DAC模型湃缎,應(yīng)用程序都有自己的用戶ID和屬于該ID的文件夾犀填,其權(quán)限管理嚴格按照傳統(tǒng)的UNIX文件權(quán)限管理運作。雖然MAC和DAC這兩種機制工作起來都沒有問題嗓违,但MAC的擴展性總體來說還是更強一些九巡。比如,除了應(yīng)用程序目錄隔離蹂季,MAC還可以限制網(wǎng)絡(luò)訪問或系統(tǒng)守護進程的操作冕广。
數(shù)據(jù)保護和全盤加密
? ? ? ? iOS一直是移動設(shè)備文件加密的先去。iOS提供全盤加密偿洁,還為開發(fā)者提供了數(shù)據(jù)保護API撒汉,用于進一步保護自己的文件。這兩個機制可以實現(xiàn)遠程抹除設(shè)備數(shù)據(jù)涕滋,在設(shè)備丟失的情況下保護用戶數(shù)據(jù)免于泄漏睬辐。
? ? ? ? iOS設(shè)備通常為全天候運行設(shè)計,它們的內(nèi)部儲存不容易被輕易拆卸宾肺。如果一個攻擊者想要不通過驗證就從設(shè)備中獲取敏感信息溯饵,他必須把設(shè)備完全拆解,然后將閃存連接到一個自定義的接口來直接讀取數(shù)據(jù)爱榕。不過從設(shè)備中獲取數(shù)據(jù)有幾個更簡單的方法:代碼執(zhí)行漏洞瓣喊、越獄等,因此幾乎沒有人會去拆手機黔酥。
? ? ? ? 但這并不意味著iOS的全盤文件系統(tǒng)加密毫無用處,它對于下面兩個安全特性來說是必要的:安全刪除文件、遠程設(shè)備擦除跪者。傳統(tǒng)安全擦除文件的方法不適用于iOS設(shè)備棵帽,主要原因是iOS設(shè)備使用固態(tài)磁盤SSD作為儲存。固態(tài)磁盤采用了減少磨損的機制渣玲,因此執(zhí)行覆蓋文件的操作無法真正覆蓋硬盤中的舊數(shù)據(jù)逗概。解決方案是確保文件被一個安全位置上的密鑰加密,這樣請求銷毀數(shù)據(jù)時忘衍,可以直接丟棄該密鑰逾苫。iOS中使用的密鑰加密是分層級的,只需簡單地丟棄一個加密密鑰就能夠徹底銷毀整層的數(shù)據(jù)枚钓,甚至是銷毀整個文件系統(tǒng)铅搓。
? ? ? ? 加密密鑰的層級
? ? ? ? iOS文件系統(tǒng)中用于數(shù)據(jù)加密的密鑰是分等級的,也就是說搀捷,用密鑰來加密其他密鑰星掰,這樣蘋果就能更精確的控制數(shù)據(jù)什么時候可用。一個基本的分層結(jié)構(gòu)如圖1-1所示:
? ? ????文件密鑰File Key⑤是針對每個文件獨立生成嫩舟,儲存在文件的元數(shù)據(jù)中氢烘。不同保護級別的文件需要使用不同強度的加密密鑰。
????????層級密鑰Class Key④的作用是專門為那些特殊數(shù)據(jù)提供不同級別的保護家厌。在最先的iOS版本中播玖,默認的保護等級是NSFileProtectionNone;從iOS5開始饭于,默認的保護等級變成了NSFileProtectionCompleteUntilFirstUserAuthentication蜀踏。
? ? ? ? 文件系統(tǒng)密鑰Filesystem Key③是一種全局加密密鑰,當元數(shù)據(jù)被層級密鑰加密后镰绎,我們使用文件系統(tǒng)密鑰來加密涉及文件安全的元數(shù)據(jù)脓斩。
? ? ? ? 設(shè)備密鑰Device Key①通常被稱為UID密鑰,每一臺設(shè)備唯一畴栖,只能通過硬件的AES引擎訪問随静,操作系統(tǒng)無法直接獲得。這是系統(tǒng)的主密鑰吗讶,它用來加密文件系統(tǒng)密鑰和層級密鑰燎猛。如果啟用了用戶密碼User Passcode②,它將與設(shè)備密鑰結(jié)合起來加密層級密鑰照皆。
? ? ? ? 一旦設(shè)置密碼重绷,這個密鑰等級也允許開發(fā)者自己決定本地儲存的數(shù)據(jù)該如何被保護,包括在設(shè)備鎖定時是否能被訪問膜毁、數(shù)據(jù)能否備份到其他設(shè)備等昭卓。
? ? ? ? 鑰匙串API
? ? ? ? iOS提供了要鑰匙串API來儲存少量機密信息愤钾。開發(fā)者可以用來儲存密碼、加密密鑰一級那些不能被其他應(yīng)用訪問的敏感信息候醒。調(diào)用鑰匙串API主要通過securityd守護進程來完成能颁,即從SQLite數(shù)據(jù)庫中提取數(shù)據(jù)。開發(fā)者可以指定在什么情況下應(yīng)用可以讀取密鑰倒淫,這和數(shù)據(jù)保護API類似伙菊。
? ? ? ? 數(shù)據(jù)保護API
? ? ? ? 數(shù)據(jù)保護API利用文件系統(tǒng)加密、鑰匙串和用戶密碼敌土,提供了一個額外的針對文件的保護層镜硕,開發(fā)者可以根據(jù)需要使用。這限制了某些進程在系統(tǒng)層面上讀取文件返干。這個API最常用的場景是當設(shè)備鎖定時確保數(shù)據(jù)不可用兴枯。
? ? ? ? 數(shù)據(jù)保護的強度很大程度上取決于iOS設(shè)備運行的版本。隨著版本更迭犬金,默認的數(shù)據(jù)保護等級會發(fā)生變化念恍。在新創(chuàng)建的iOS應(yīng)用程序中,數(shù)據(jù)保護默認對所有應(yīng)用數(shù)據(jù)開啟晚顷,這種狀態(tài)在啟動設(shè)備后的第一次解鎖都生效峰伙。可在Xcode-Capabilities中有個Data Protection默認已打開该默。
防御代碼漏洞:ASLR瞳氓、XN和其他機制
? ? ? ? iOS使用兩套標準機制來預(yù)防代碼執(zhí)行攻擊:地址空間結(jié)構(gòu)隨機化(ARLR)和XN bit(eXecute Never的縮寫,標記該段內(nèi)存區(qū)域不包含可執(zhí)行代碼)栓袖。每次執(zhí)行程序時匣摘,ASLR都會隨機分配程序、數(shù)據(jù)裹刮、堆和棧的內(nèi)存位置音榜。共享庫的內(nèi)存位置只在每次系統(tǒng)重啟時隨機設(shè)置。函數(shù)和庫的內(nèi)存地址很難預(yù)測捧弃,這就預(yù)防了緩沖區(qū)溢出攻擊(return-to-libc)赠叼,這種攻擊依賴于基本庫函數(shù)的已知地址。
? ? ? ? XN bit违霞,一般對應(yīng)非ARM平臺的NX(No-eXecute)bit嘴办,允許操作系統(tǒng)將某段內(nèi)存標記為不可執(zhí)行,這是由CPU來控制的买鸽。在iOS中涧郊,這個機制默認應(yīng)用在程序的棧和堆上。這意味著眼五,哪怕攻擊者可以將惡意代碼注入程序的堆和棧妆艘,他們也無法重定向程序來執(zhí)行攻擊代碼彤灶。
? ? ? ? 每個程序都有一段既能寫又能執(zhí)行的內(nèi)存,前提是它必須經(jīng)過蘋果官方簽名授權(quán)系統(tǒng)的簽名双仍。Safari瀏覽器中的JavaScript即時(JIT)編譯器會用到這段內(nèi)存枢希。你平時在程序中經(jīng)常使用的WebView并不具備訪問相同功能的權(quán)利桌吃,這樣就可以避免代碼執(zhí)行攻擊朱沃。蘋果一直禁用第三方的JIT,如Chrome就沒有Safari那樣好用茅诱,Chrome只能使用WebView逗物。
越獄檢測
? ? ? ? 越獄的本質(zhì)就是通過一系列步驟來禁掉簽名機制,從而允許設(shè)備運行未經(jīng)蘋果官方審核的應(yīng)用瑟俭。越獄還允許你使用一些便利的開發(fā)和測試工具翎卓。越獄還有一個直觀重要的能力,就是黑箱測試應(yīng)用程序(第六章討論)摆寄。
? ? ? ? 越獄不一定要禁掉iOS的沙盒機制失暴,它只是允許你在沙盒外安裝應(yīng)用程序。安裝在移動用戶主目錄的應(yīng)用程序(即通過蘋果商店安裝)仍然受到沙盒限制微饥。第三方的iOS應(yīng)用程序需要安裝在越獄設(shè)備中權(quán)限更高的/Applications目錄下逗扒。
? ? ? ? 越獄檢測很早就有,不過沒什么用欠橘。它的目的是檢測設(shè)備是否存在不受信任矩肩、未經(jīng)前面的第三方程序,從而判斷設(shè)備是否處在高風(fēng)險環(huán)境中肃续∈蜷荩總體來說,越獄檢測不值得你浪費時間去做始锚,因為它無法阻止一個堅定的攻擊者刽酱。
? ? ? ? 有一段時間,蘋果官方推出過越獄檢測API瞧捌,但很快就在后續(xù)的iOS版本中刪掉了棵里。沒有此API,開發(fā)者也實現(xiàn)了一些越獄檢測方法察郁。目前最流行的越獄檢測方法主要有下面幾種:
? ? ? ? 1衍慎、創(chuàng)建一個新進程,例如調(diào)用fork()皮钠、vfork()稳捆、popen()等方法。這些方法是明顯會被沙盒所禁止的事情麦轰。當然乔夯,越獄系統(tǒng)上的沙盒仍然有效砖织,所以該策略毫無意義,無論你的設(shè)備越獄與否末荐,這種方法對于來自蘋果官方商店的程序來說始終是無效的侧纯。
????????2、讀取沙盒外部的文件甲脏。開發(fā)者通常想要嘗試訪問一些二進制代碼眶熬,這些二進制代碼通常對應(yīng)于ssh、bash块请,還有一些位于Cydia.app目錄和Cydia經(jīng)常使用的apt倉庫等位置娜氏。但這些檢測很容易被繞過,并且Xcon6之類的工具也能幫助用戶繞過這些自動檢查墩新。
? ? ? ? 3贸弥、檢查是否有相關(guān)的方法名。所以不要取名如isJailbroken類似的直白方法名海渊,否則攻擊者可以輕易定位并禁掉越獄檢測绵疲。
舉個栗子:精明的開發(fā)者會嘗試使用_dyld_image_count()和_dyld_get_image_name()來檢查載入的動態(tài)庫數(shù)量和名字,并使用_dyld_get_image_header()來檢查它們在內(nèi)存中的位置臣疑。但是攻擊者可以通過給應(yīng)用打一個二進制補丁來繞過這些檢測盔憨。
? ? ? ?總結(jié)來說,越獄檢測只會減慢攻擊者的攻擊時間朝捆,并不能真正阻止鑒定的攻擊者般渡。所以并沒有什么卵用。
蘋果商店的審查是否有用
? ? ? ? 當開發(fā)一個應(yīng)用或評估其面對的威脅時芙盘,需要將用戶設(shè)備上其他應(yīng)用考慮進來驯用。設(shè)備上任何惡意的第三方應(yīng)用程序都能通過IPC機制與其他應(yīng)用交互,也能竊取用戶私人信息儒老。蘋果官方的應(yīng)用程序?qū)彶槭菍惯@些惡意程序最有利的武器蝴乔。
? ? ? ? 蘋果并沒有公開披露他們的審查技術(shù)。可以確定都是驮樊,蘋果使用了二進制分析和動態(tài)測試技術(shù)薇正。這一過程可以將大部分帶有明顯惡意的應(yīng)用程序拒之門外。盡管蘋果付出了很大努力囚衔,但是事實證明挖腰,一個中等水平的攻擊者完全有能力偽裝一個動態(tài)代碼更新應(yīng)用,讓它通過蘋果商店的審查练湿。攻擊者一般通過以下幾種方式來蒙混過官方商店的審查猴仑。
????????1、WebKit橋接:基于WebKit橋接肥哎,可以通過JavaScript使用一些iOS的原生API辽俗。如PhoneGap(即現(xiàn)在的Cordova框架)疾渣。這種方式可以提供很多有用的功能,但使用它們也意味著應(yīng)用程序的許多邏輯要寫成JavaScript崖飘,因此不需要打包到應(yīng)用中榴捡。舉個栗子:一個開發(fā)者使用JavaScript實現(xiàn)了一個常規(guī)的打開文件功能,然后在應(yīng)用程序?qū)徍似陂g不做任何的惡意操作朱浴。一旦審核通過吊圾,開發(fā)者可以修改設(shè)備的JavaScript,從而獲取設(shè)備上那些本應(yīng)該是禁區(qū)的數(shù)據(jù)赊琳。(第九章將詳細介紹JavaScript與原生代碼的橋接和需要注意的問題)
????????2街夭、動態(tài)修復(fù):通常來說,如果一段代碼沒有經(jīng)過蘋果發(fā)布的密鑰簽名認證躏筏,應(yīng)用程序則無法運行它。iOS有一個特性呈枉,可以讓程序分配一段沒有NX保護的內(nèi)存區(qū)域(即該內(nèi)存區(qū)塊可讀可寫可執(zhí)行)趁尼,里面運行的代碼也不需要經(jīng)過簽名認證。這一機制被蘋果用在了Safari的JIT編譯器上猖辫,以便實現(xiàn)一些功能酥泞。但是蘋果在實現(xiàn)的過程中可能會產(chǎn)生漏洞,這樣第三方應(yīng)用程序就可以執(zhí)行相同的把戲啃憎。舉個栗子:應(yīng)用審查期間芝囤,該應(yīng)用安分守己,但是一旦通過審查辛萍,就遠程操控程序下載新的悯姊、未經(jīng)簽名的代碼并執(zhí)行,整個過程毫無阻礙贩毕。當然現(xiàn)在這個問題已經(jīng)解決了悯许,但是它卻為我們?nèi)绾悟_過審查提供了思路。
? ? ? ? 3辉阶、故意植入不安全的代碼:惡意代碼被打包在應(yīng)用程序自身之中以便其順利可以得到簽名先壕,同樣在審查時應(yīng)用程序從不去調(diào)用這些代碼。一旦獲準上架谆甜,研究人員能夠利用緩沖區(qū)溢出得到漏洞改變應(yīng)用程序的控制流垃僚,使其導(dǎo)向隱藏的惡意代碼。
? ? ? ? 4规辱、內(nèi)嵌解釋器:過去幾年谆棺,蘋果在有許多產(chǎn)品(主要是游戲)使用一個內(nèi)嵌的Lua解釋器來執(zhí)行大部分的內(nèi)在邏輯。惡意程序應(yīng)用可以通過一個類似的解釋器來動態(tài)下載代碼按摘,并在內(nèi)存中執(zhí)行包券。當然纫谅,在官方的應(yīng)用審查時這類惡意代碼還是會隱藏自己。通過此方法我們能增加一個新的功能溅固,行為不端的開發(fā)者也能較為便利地添加一個惡意功能付秕。
小結(jié)
? ? ? ? 蘋果的審查可以幫我們消除那些簡單的惡意程序,但是惡意程序的確可以有方法從審查人員的眼皮底下溜走侍郭。時刻記住在你的應(yīng)用程序中用代碼做好防御询吴。
第二章:Objective-C簡明教程
? ? ? ? 只能說穩(wěn)固而知新吧。簡要的寫一下這章看有沒有值得記錄的內(nèi)容亮元。
????????關(guān)鍵的iOS編程技術(shù)
? ? ? ? Cocoa是一些框架和Objective-C GUI編程API的總稱猛计。Cocoa Touch是Cocoa的一個超集,主要加入了一些移動相關(guān)的API爆捞,如手勢處理和移動設(shè)備圖形用戶界面元素奉瘤。Foundation類是Objective-C類,它構(gòu)成了我們調(diào)用的Cocoa API煮甥。Core Foundation是一種更低級的基于C的類庫盗温,在其上有很多Foundation類。
? ? ? ? .m文件的一個例子:
@interface Kitty : NSObject {
? ? @private NSString *name;
? ? @protected NSURL *homepage;
? ? @public NSString *color;
}
@private只允許從定義該變量的類的內(nèi)部訪問成肘,@protected允許從定義變量的類及其子類中訪問卖局,@public可以從任何類中訪問。默認不寫情況下是@protected双霍。
? ? ? ? Objective-C為.h和.m砚偶,C++為.h和.cpp,Objective-C++(混合了C++和Objective-C的代碼)是.h和.mm文件
? ? ? ? Objective-C中沒有內(nèi)存管理機制洒闸,它使用自動引用計數(shù)ARC來對內(nèi)存進行管理染坯。
? ? ? ? Core Foundation對象可以通過 __bridge 系列關(guān)鍵字來橋接Cocoa對象妙同。
? ? ? ? Objective-C的一些委托方法通常使用should饶米、will竖共、did來修飾一些方法名昙读。should修飾搞乏,通常返回值為BOOL榛斯,可以返回相應(yīng)的YES偎肃、NO來做到是否允許執(zhí)行的操作腿倚。will代表程序?qū)⒁獔?zhí)行某些操作囤萤,如果viewWillAppear:告訴你視圖即將出現(xiàn)昼窗,你就可以在視圖出現(xiàn)之前做一些操作。did表示已經(jīng)進行涛舍,如viewDidAppear:告訴你視圖已經(jīng)出現(xiàn)澄惊。我們寫代碼的時候也可以遵循類似的規(guī)則。
? ? ? ? Objective-C的category機制允許你在運行時給現(xiàn)有的類添加新的方法實現(xiàn),而且不用重新編譯掸驱。category可以添加或替換類的方法實現(xiàn)肛搬,因此,你不用重新實現(xiàn)這個類就能輕松修改它的行為毕贼。不幸的是温赔,使用category很容易導(dǎo)致嚴重的安全問題,因為它們可以通過代碼塊從任意位置侵入你的類鬼癣。
? ? ? ? 蘋果官方對于category是這樣說的:如果你在category中聲明了一個和原類同名的方法陶贼,或和該類的另一個category中的方法重名,那么在運行時究竟哪個方法會被執(zhí)行是不確定的待秃。
? ? ? ? 所以結(jié)論是:category確實方便拜秧,但是盡量少用,它們可能會弄亂代碼章郁,并危害安全枉氮。
? ? ? ? 使用方法swizzling可以替換現(xiàn)有類方法和實現(xiàn)方法,哪怕你根本不擁有這些方法驱犹。方法swizzling功能上類似于category的子類化嘲恍,但是比category更加強大也更方便,你可以直接把原有的方法實現(xiàn)替換????為新的方法實現(xiàn)雄驹,而不是擴展原方法。開發(fā)者往往使用這項技術(shù)實現(xiàn)子類們都需要的通用方法淹辞。
? ? ? ? 如果想要使用swizzling医舆,那么推薦使用便于測試的封裝包,如JRSwizzle象缀。如果應(yīng)用使用swizzling做了一些有風(fēng)險的事情蔬将,蘋果可能會拒絕應(yīng)用上架。
第三章:iOS應(yīng)用剖析
? ? ? ? 要找出應(yīng)用在本地儲存的所有數(shù)據(jù)央星,最快的方法是查看~/Library/Developer/CoreSimulator/Devices目錄霞怀。從Xcode6開始,只要在模擬器上運行過應(yīng)用莉给,Xcode就會根據(jù)當前設(shè)備了類型和系統(tǒng)版本建立一個文件夾并分配一個UUID毙石。相關(guān)的應(yīng)用數(shù)據(jù)被儲存在這個目錄下的兩個位置。其中應(yīng)用的二進制和資源文件(包括.nib文件和圖形文件)都放置在<device ID>/data/Containers/Bundle/Application/<app bundle id>目錄下颓遏。而經(jīng)常變化的動態(tài)數(shù)據(jù)則儲存在~<device ID>/data/Containers/Data/Application/<app bundle id>目錄中徐矩。系統(tǒng)數(shù)據(jù)(如全局配置文件)將儲存在其余的目錄下。
? ? ? ? 右鍵Finder叁幢,前往文件夾輸入~/Library/Developer/CoreSimulator/Devices滤灯,可看到如下圖片內(nèi)容:
? ? 隨便點進一個
? ? 1、查找二進制和資源文件目錄(<device ID>/data/Containers/Bundle/Application/<app bundle id>)
? ? 2、查看下動態(tài)數(shù)據(jù)目錄(<device ID>/data/Containers/Data/Application/<app bundle id>)
對該目錄結(jié)構(gòu)進行一下探索鳞骤,可以勾畫出下圖的大體輪廓:
? ? ? ? 可以使用iExplorer工具來查看安裝應(yīng)用程序的目錄結(jié)構(gòu)窒百。
? ? ? ? 本章,我將介紹一些常見的目錄和iOS應(yīng)用經(jīng)常儲存的數(shù)據(jù)豫尽,還會介紹如何通過代碼的方式與其交互篙梢,以及什么數(shù)據(jù)可能會從中泄漏。
對plist文件進行處理
? ? ? ? iOS將應(yīng)用程序的配置數(shù)據(jù)儲存在屬性列表plist文件中拂募,這些信息都是Core Foundation數(shù)據(jù)類型庭猩,比如CFArray和CFString。從安全角度說陈症,你需要重點檢查plist文件中是不是純文本的值蔼水, 比如證書,它們有可能會被修改從而改變應(yīng)用程序的行為录肯。舉例來說趴腋,默認情況下,支付功能是被禁用的论咏,但是當相應(yīng)的值被修改時优炬,該功能就可以被使用。
? ? ? ? 屬性列表有兩種格式:二進制和XML厅贪。如下XML格式就有很好的可讀性蠢护。
? ? ? ? 如果用命令行查看文件或在代碼中處理plist,就會經(jīng)常遇到二進制格式的plist文件养涮。二進制格式的可讀性對我們而言并不是那么理想葵硕,不過你可以使用plutil(1)命令將plist文件轉(zhuǎn)換成XML格式。
$ plutil -convert xmll Info.plist -o -
$ plutil -convert xmll Info.plist -o Info-xml.plist
$ plutil -convert binary1 Info-xml.plist -o Info-bin.plist
????????第一條命令將一個二進制的plist轉(zhuǎn)換成XML贯吓,然后打印到標準輸出(stdout)懈凹,之后可以通過管道pipe把內(nèi)容傳給less(1)或者類似的命令。
? ? ? ? 第二條命令使用-o filename參數(shù)直接將內(nèi)容輸出到一個文件悄谐。
? ? ? ? 第三條命令介评,binary1轉(zhuǎn)換類型將XML格式的plist轉(zhuǎn)換成二進制格式。
其實XML和二進制格式都能被應(yīng)用識別爬舰,所以也可以不做轉(zhuǎn)換们陆。
設(shè)備目錄
? ? ? ? 從iOS8開始,模擬器平臺(比如iPhone洼专、iPad以及其他的變體設(shè)備)都儲存在以唯一標識符命名的目錄下棒掠。這些標識符由兩部分組成:一部分是從Xcode啟動模擬器時選擇的設(shè)備類型,另一部分是系統(tǒng)版本屁商。所有目錄都有一個plist文件記錄當前的設(shè)備信息烟很。下面是一個例子:(如前往文件夾~/Library/Developer/CoreSimulator/Devices颈墅,進去任意一個設(shè)備目錄,可以找到device.plist文件雾袱,用文本編輯器打開)
在這個plist文件中恤筛,想找出設(shè)備信息并不容易。為了找出設(shè)備信息芹橡,要么去①Devices目錄下查看.default_created.plist文件毒坛,要么使用②grep命令找出所有的device.plist文件。
? ? ? ? ①:我沒找到.default_created.plist或者default_created.plist文件林说。煎殷。不知道是不是書中寫錯了還是我找的目錄錯了。我找到了一個device_set.plist文件腿箩,里面確實有很多device的信息豪直。
? ? ? ? ②:使用grep命令:
? ? 進入正在運行的應(yīng)用程序目錄后,你會看到data目錄珠移,它包含所有的模擬器文件弓乙,還包含應(yīng)用相關(guān)的數(shù)據(jù)。應(yīng)用數(shù)據(jù)被分別放到了三個目錄中钧惧,它們在data/Containers目錄下暇韧,分別是Bundle、Data浓瞪、Shared目錄:
Bundle目錄:
? ? ? ? Bundle目錄中有一個Applications目錄懈玻,該目錄包含設(shè)備上所有的應(yīng)用目錄,這些應(yīng)用目錄用bunle ID命名乾颁。進入某個應(yīng)用目錄酪刀,看到.app文件,右鍵钮孵,顯示包內(nèi)容。.app文件儲存應(yīng)用程序的核心二進制代碼眼滤、圖像資源巴席、本地化信息等,其中Info.plist包含應(yīng)用程序的核心配置信息诅需,包含bundle id漾唉,主程序包、應(yīng)用程序的UI信息以及應(yīng)用程序需要向設(shè)備請求的功能堰塌。Info.plist中值得關(guān)注的一個條目是UIRequiredDeviceCapabilities赵刑,該條目描述了應(yīng)用所需要的系統(tǒng)資源(非必須的條目)。
Data目錄
? ? Data目錄中最重要的是Application子目錄场刑。Data/Application目錄包含了應(yīng)用程序運行所需的其他數(shù)據(jù):參數(shù)設(shè)置般此、緩存、cookie等。這個目錄也是需要重點檢查的對象铐懊,因為大部分數(shù)據(jù)泄露都發(fā)生于此邀桑。
~Library/Developer/CoreSimulator/Devices/<bundle ID>/data/Containers/Data/Application/<app bundle id>/(Doucuments、Library科乎、tmp)
? ? ? ? Documents和Documents/Inbox目錄
? ? ? ? Doucuments目錄主要用來儲存非臨時狀態(tài)的應(yīng)用數(shù)據(jù)壁畸,比如用戶創(chuàng)建的內(nèi)容或應(yīng)用程序在離線狀態(tài)模式下需要的本地緩存信息。如果你在Info.plist中設(shè)置了UIFileSharingEnabled茅茂,那么可以通過iTunes訪問這些文件捏萍。
? ? ? ? 其他應(yīng)用發(fā)送過來的文件儲存在Documents/Inbox目錄中。這些應(yīng)用可以使用UIDocumentInteractionController類來發(fā)送文件空闲。
? ? ? ? 你只能讀取或者刪除儲存在Inbox目錄下的文件令杈。這些來自其他應(yīng)用程序的文件不能寫入你的應(yīng)用目錄里,它們將被一個優(yōu)先級更高的系統(tǒng)進程處理进副。你可以定期刪除這些文件这揣,也可以讓用戶選擇是否刪除,這樣用戶就可以知道這里有沒有敏感信息影斑。
? ? ? ? 如果你正在開發(fā)一個應(yīng)用给赞,想確保磁盤上不會遺留任何敏感信息,那么可以將Inbox目錄中的文檔復(fù)制到另一個位置矫户,從而對數(shù)據(jù)進行保護片迅,然后從Inbox目錄中移除這些文件。
Library目錄
? ? ? ? 從之前的結(jié)構(gòu)圖看到皆辽,Library下有Application Support柑蛇、Caches、Cookies驱闷、Preferences耻台、Saved application state目錄。
Library目錄下的文件可以通過iTunes和iCloud進行備份(Caches目錄除外)
? ? ? ? Application Support目錄
? ? ? ? 由用戶創(chuàng)建和接收的文件不會儲存在Application Support目錄中空另,該目錄主要用來儲存應(yīng)用程序使用的數(shù)據(jù)文件盆耽。該目錄下的文件主要用來支持應(yīng)用程序運行。這些文件可以在應(yīng)用程序安裝時部署扼菠,也可以在應(yīng)用程序創(chuàng)建或從網(wǎng)絡(luò)上下載摄杂。(我的理解:不管你的來源如何,反正用途就是支持應(yīng)用程序運行)
? ? ? ? 默認情況下循榆,iTunes會備份這個目錄下的數(shù)據(jù)到你的計算機和iCloud中析恢。但是如果你不放心將數(shù)據(jù)保存到蘋果的云端,可以通過為新創(chuàng)建的文件設(shè)置NSURLIsEXecutedFromBackupKey屬性來禁止備份到云端秧饮。
? ? ? ? 值得一提的是:蘋果只要求應(yīng)用備份用戶數(shù)據(jù)到iCloud映挂,不要求應(yīng)用備份應(yīng)用數(shù)據(jù)泽篮。如果一個程序允許備份應(yīng)用數(shù)據(jù)到iCloud,那么該應(yīng)用一定會被App Store拒絕上架的袖肥。
? ? ? ? Caches和Caches/Snapshots目錄
? ? ? ? Caches目錄在功能上類似于網(wǎng)頁瀏覽器緩存:所以iTunes不會備份該目錄咪辱。Caches目錄用來存放臨時內(nèi)容,隨著應(yīng)用程序的啟動和退出椎组,這些內(nèi)容將會被丟棄油狂。iOS系統(tǒng)在運行空間不足時會自動刪除這些緩存目錄,不過并不會刪除當前正在運行程序的緩存寸癌。
? ? ? ? Caches目錄有時也會把網(wǎng)頁緩存內(nèi)容儲存在子目錄Caches/com.mycompany.myapp中专筷。該位置有容易泄露敏感信息,因為通過HTTPS進行長時間傳輸?shù)臄?shù)據(jù)可以被iOS緩存蒸苇,如果開發(fā)者沒有禁止數(shù)據(jù)緩存或盡快使緩存數(shù)據(jù)過期磷蛹,那么攻擊者總能在這里唱到甜頭。
? ? ? ? 當應(yīng)用程序進入后臺溪烤,操作系統(tǒng)會自動把當前應(yīng)用的屏幕快照儲存到Snapshots子目錄中味咳,這樣做會無形中把一些敏感信息儲存在本地。操作系統(tǒng)這樣做的目的:當應(yīng)用切回前臺時檬嘀,操作系統(tǒng)可以使用它的屏幕快照創(chuàng)建一個快速的動畫槽驶。(比如截圖有可能會包含用戶的社會保險號碼等等等敏感信息)(看到工行的App做的挺好的,在應(yīng)用切回前臺的時候鸳兽,這張快照是模糊的掂铐,具體怎么操作有待考慮)。
? ? ? ? Cookies目錄
? ? ? ? 由URL加載系統(tǒng)所產(chǎn)生的cookie都儲存在Cookies目錄中揍异。創(chuàng)建NSURLRequest請求時全陨,你將指定相關(guān)的cookie策略,或者使用系統(tǒng)默認的策略衷掷。與OS X系統(tǒng)不同辱姨,iOS上的cookie不會在應(yīng)用之間共享,每個應(yīng)用都有單獨的目錄來儲存自己的cookie戚嗅。
? ? ? ? Preferences目錄
? ? ? ? iOS將應(yīng)用的偏好設(shè)置儲存在此Preferences目錄下炮叶,但是不允許應(yīng)用直接編輯目錄中的文件。取而代之渡处,此目錄下文件的創(chuàng)建、讀取祟辟、操作都通過NSUserDefaults或CFPrefrences API來完成医瘫。
? ? ? ? 請不要將敏感的用戶信息或證書儲存在此。
? ??????Saved application state目錄(保存應(yīng)用程序狀態(tài)的目錄)
? ? ? ? 用戶期待應(yīng)用能記住他們輸入文本框的內(nèi)容和啟用的設(shè)置旧困。如果一個用戶切換到另一個應(yīng)用醇份,片刻后又切換回來稼锅,原先的應(yīng)用可能已經(jīng)在后臺被系統(tǒng)殺掉了。為了在應(yīng)用啟動時使它的界面和之前保持一致僚纷,新版本的iOS通過State Preservation API將對象狀態(tài)信息儲存在Saved Application State目錄中矩距。開發(fā)者可以將需要保存的狀態(tài)的UI標記出來。
? ? ? ? 在保存應(yīng)用狀態(tài)時要相當小心怖竭,這也是一個容易泄露數(shù)據(jù)的地方锥债。(第10章將深入討論如何避免數(shù)據(jù)泄露)。
? ? ? ? tmp目錄
? ? ? ? tmp目錄用來儲存臨時文件痊臭。和Caches目錄一樣哮肚,當你的應(yīng)用停止運行時,該目錄中包含的文件可能會被操作系統(tǒng)自動刪除广匙。此目錄的使用方法和Caches目錄類似允趟。不同之處在于Caches意味著緩存的這些文件可能會被再次獲取或重新創(chuàng)建。比如鸦致,你從遠程服務(wù)器下載了特定的應(yīng)用數(shù)據(jù)潮剪,為了提高性能,會將數(shù)據(jù)緩存在Caches目錄中分唾,如果數(shù)據(jù)消失了抗碰,可以重新去下載。另一方面鳍寂,tmp目錄嚴格儲存著由應(yīng)用產(chǎn)生的臨時數(shù)據(jù)改含,如果這些文件在重新訪問前被刪除,你并不能重新獲取到它們迄汛。此外捍壤,tmp目錄和Caches目錄一樣,都不會備份到iTunes和iCloud鞍爱。
Shared目錄
? ? ? ? Shared目錄是一個特殊的目錄鹃觉,用來為應(yīng)用程序提供一個共享的應(yīng)用組(為了支持iOS8的擴展(extentions)),比如修改通知中心“今日”視圖中的任務(wù)或鍵盤行為睹逃。蘋果要求所有的擴展都必須對應(yīng)一個容器應(yīng)用盗扇,每一個容器應(yīng)用都會擁有自己的應(yīng)用ID。擴展及其容器應(yīng)用可以通過Shared目錄來共享數(shù)據(jù)沉填。例如:應(yīng)用可以使用NSUserDefaults的初始化方法疗隶,指定一個名字來訪問用戶數(shù)據(jù)中共享的數(shù)據(jù)庫,類似于這樣:[[NSUserDefaults alloc] initWithSuiteName:@"com.myorg.mysharedstuff"];
? ? ? ? Shared目錄在日常開發(fā)中并不常用翼闹,但當我們檢查儲存在preferences中的敏感信息或其他隱私數(shù)據(jù)時斑鼻,別忘了這個目錄。