互聯(lián)網(wǎng)公司的安全體系基本上以運(yùn)維安全,應(yīng)用安全,業(yè)務(wù)安全三管齊下。而移動應(yīng)用安全則在應(yīng)用安全中占據(jù)半壁江山,尤其對于移動端產(chǎn)品為主的公司而言,SDL的主要實(shí)踐對象就是移動應(yīng)用。
隨著智能手機(jī)和其他移動設(shè)備的爆發(fā)式普及,移動應(yīng)用已成為互聯(lián)網(wǎng)公司業(yè)務(wù)重要的業(yè)務(wù)方向。本文以移動兩大平臺之一的安卓為主線,介紹移動應(yīng)用所面臨的安全風(fēng)險(xiǎn)和解決方案。其中包含評估方法以及應(yīng)對的思路,這些思路可以相應(yīng)的借鑒于其他平臺上。定義客戶端應(yīng)用安全的范圍是什么,風(fēng)險(xiǎn)有哪些,攻擊的來源,移動操作系統(tǒng)所提供的工具。在了解這些基本的判斷之后,當(dāng)一些新的技術(shù)出現(xiàn),我們?nèi)匀豢梢杂靡延械臉?biāo)準(zhǔn)去應(yīng)對。
1、業(yè)務(wù)架構(gòu)分析
移動應(yīng)用很少會單獨(dú)存在,多數(shù)情況下會作為互聯(lián)網(wǎng)業(yè)務(wù)流程中的承載平臺出現(xiàn)。如果業(yè)務(wù)同時(shí)存在傳統(tǒng)Web頁面服務(wù)模式,兩者從邏輯上處于并行的關(guān)系,只是不同的表現(xiàn)形式。作為一種運(yùn)行在用戶控制設(shè)備上的應(yīng)用,業(yè)務(wù)服務(wù)端應(yīng)該假設(shè)客戶端提交的信息存在各種可能,在設(shè)計(jì)時(shí)需要關(guān)注哪些邏輯適合放在移動端,哪些邏輯需要保留在服務(wù)端。涉及業(yè)務(wù)核心數(shù)據(jù)的行為,例如游戲中的物品掉落,支付行為的判斷,賬號信息的更改等都需要在業(yè)務(wù)服務(wù)端進(jìn)行判斷,而非客戶端。這些分割需要從設(shè)計(jì)階段對移動客戶端能做哪些行為進(jìn)行限定。
從整體業(yè)務(wù)角度來看,業(yè)務(wù)邏輯為皮,移動應(yīng)用端的展示為毛。如何避免移動客戶端做不應(yīng)承擔(dān)的判斷,如何將應(yīng)用安全和業(yè)務(wù)服務(wù)端邏輯進(jìn)行劃定是首先需要明確的。
2、移動操作系統(tǒng)安全簡介
圖1是安卓系統(tǒng)的架構(gòu)。
圖1 Android體系架構(gòu)
硬件設(shè)備:安卓可運(yùn)行在范圍廣泛的硬件上,并且支持某些硬件特有的安全功能,例如ARM v6的eXecute-Never功能。
安卓操作系統(tǒng):底層為Linux內(nèi)核,所有設(shè)備資源都通過該層提供,包括相機(jī),GPS數(shù)據(jù)、藍(lán)牙、電話、網(wǎng)絡(luò)等服務(wù)。
安卓應(yīng)用:通常使用Java開發(fā),運(yùn)行在Dalvik/ART虛擬機(jī)中,除此之外還包括一些二進(jìn)制的組件。應(yīng)用中不論是虛擬機(jī)還是二進(jìn)制的部分都在相同的安全域,也就是該應(yīng)用的沙盒中。
現(xiàn)代移動操作系統(tǒng)和早期操作系統(tǒng)相比有一定的優(yōu)勢,以Windows為例,在不斷更新的過程中,會被過去的理念和代碼實(shí)現(xiàn)所拖累。而安卓和iOS作為之后設(shè)計(jì)開發(fā)的操作系統(tǒng),在設(shè)計(jì)上加入了一些新的理念。此外現(xiàn)代操作系統(tǒng)如安卓中包含了大量的漏洞利用緩解技術(shù),例如ASLR,SELinux,F(xiàn)ORTIFY_SOURCE編譯選項(xiàng)等技術(shù)。這些技術(shù)能進(jìn)一步提高利用漏洞的難度,降低漏洞利用成功率。
由于這些措施的運(yùn)用,在未越獄或root的設(shè)備上,更多的需要考慮應(yīng)用自身遇到的安全問題。應(yīng)用需要信任并借用底層系統(tǒng)提供功能。
安卓在設(shè)計(jì)時(shí)已經(jīng)考慮并集成了很多安全相關(guān)的功能和組件,一款普通的應(yīng)用在設(shè)計(jì)和開發(fā)過程中都可能用到這些。
一款安全應(yīng)用大體的結(jié)構(gòu)內(nèi)容包括:數(shù)據(jù)安全性,服務(wù)安全性,應(yīng)用權(quán)限安全性,以及其他一些內(nèi)容。
3、簽名管理
為了確定應(yīng)用的來源,無論安卓還是iOS都會對應(yīng)用的簽名進(jìn)行檢查,確保用戶安裝的應(yīng)用來源可控。在來源檢查上iOS環(huán)境下更加可控一些,造成這種情況的原因很多,但最重要的一點(diǎn)是對應(yīng)用市場的控制力。對于應(yīng)用開發(fā)方,應(yīng)該保護(hù)好本公司用于應(yīng)用簽名的私鑰,推薦的解決方案是建立簽名服務(wù)器,開發(fā)者上傳需要簽名的應(yīng)用,服務(wù)器完成簽名后提供下載。簽名服務(wù)可對申請應(yīng)用簽名的人員進(jìn)行權(quán)限控制,并包含日志記錄,保存上傳應(yīng)用副本等功能,這樣做的好處是降低私鑰泄露的風(fēng)險(xiǎn)。
另外一點(diǎn)和簽名相關(guān)的注意事項(xiàng)是,在同一家公司內(nèi)的應(yīng)用推薦使用相同的簽名密鑰,避免不同的應(yīng)用使用不同的簽名,這樣不僅便于之后的發(fā)布和管理,在技術(shù)上也便于之后可能存在的應(yīng)用間通信需求。無論iOS中的Keychain Access Group和安卓權(quán)限定義中要求的同簽名來源(level=Signature)都要求應(yīng)用被相同的密鑰簽名。
4、應(yīng)用沙盒及權(quán)限
安卓和iOS作為之后設(shè)計(jì)開發(fā)的操作系統(tǒng),在設(shè)計(jì)上加入了一些新的理念,其中重要的一點(diǎn)是通過沙盒(Sandbox)對各應(yīng)用間的權(quán)限隔離,并在限定應(yīng)用行為邊界后,通過按需申請應(yīng)用權(quán)限的方式規(guī)范各應(yīng)用的行為。這樣就將單個應(yīng)用面臨的風(fēng)險(xiǎn)和其他應(yīng)用以及操作系統(tǒng)相隔離。
在安卓系統(tǒng)上,在接觸任何系統(tǒng)資源前,應(yīng)用都要通過權(quán)限檢查,如圖2所示。
圖2 應(yīng)用權(quán)限檢查
是如何實(shí)現(xiàn)沙盒的?安卓和iOS內(nèi)核都源自*nix類系統(tǒng)內(nèi)核,對應(yīng)用沙盒的技術(shù)實(shí)現(xiàn)都是基于操作系統(tǒng)提供的用戶機(jī)制。每個在系統(tǒng)上安裝的應(yīng)用,如果沒有特殊設(shè)定(SYSTEM或者安卓中SHARED-UID模式),都會有系統(tǒng)分配給應(yīng)用一個獨(dú)特的用戶ID(UID),單憑該UID,應(yīng)用無法使用任何應(yīng)用外的設(shè)備資源。只有當(dāng)應(yīng)用在安裝時(shí)預(yù)先申請了某些系統(tǒng)權(quán)限后,才會被準(zhǔn)許進(jìn)行權(quán)限對應(yīng)的操作。
以安卓系統(tǒng)為例,申請系統(tǒng)權(quán)限需要按照如下格式在應(yīng)用的AndroidManifest.xml文件中添加uses-permission的標(biāo)簽段。
<uses-permission android:name="string"android:maxSdkVersion="integer" />
其中android:name屬性就是將要申請的權(quán)限名稱。
此外,應(yīng)用在申請系統(tǒng)提供的權(quán)限的同時(shí),也可以聲明創(chuàng)建新的自定義權(quán)限,并且和應(yīng)用內(nèi)提供的一些模塊相關(guān)聯(lián)。在下面的實(shí)例中,應(yīng)用自定義了名為com.example.project.DEBIT_ACCT的權(quán)限,并且和com.example.project.FreneticActivity模塊關(guān)聯(lián),之后如果其他應(yīng)用需要調(diào)用該模塊,就需要在自己的AndroidManifest.xml文件中聲明使用com.example.project.DEBIT_ACCT:
<manifest . . . >
<permission android:name="com.example.project.DEBIT_ACCT" . . . />
<uses-permission android:name="com.example.project.DEBIT_ACCT" />
. . .
<application . . .>
<activity android:name="com.example.project.FreneticActivity"
android:permission="com.example.project.DEBIT_ACCT"
. . . >
. . .
</activity>
</application>
</manifest>
從上面的描述可以了解到,應(yīng)用既可以作為權(quán)限的申請方,也可以提供自定義權(quán)限供其他應(yīng)用使用,而這些自定義權(quán)限相配合的是背后各種組件。
5、應(yīng)用安全風(fēng)險(xiǎn)分析
在應(yīng)用和業(yè)務(wù)邏輯已經(jīng)剝離的情況下,仍然可能存在嚴(yán)重的安全風(fēng)險(xiǎn)。首先需要意識到這些風(fēng)險(xiǎn)的根源是應(yīng)用實(shí)現(xiàn)形態(tài)的多樣性。在提倡模塊化的今天,應(yīng)用在實(shí)現(xiàn)過程中會分為數(shù)量眾多的模塊來實(shí)現(xiàn),這些模塊相互耦合,向模塊外提供調(diào)用接口,或主動或被動的接收外部數(shù)據(jù)并影響內(nèi)部邏輯。通過梳理這些接口和數(shù)據(jù)來源,可以獲取到安全風(fēng)險(xiǎn)的來源列表。
這些調(diào)用接口的形式是多樣的,應(yīng)用既可以在同系統(tǒng)下的組件層面提供各種服務(wù),也可能開放網(wǎng)絡(luò)端口接受數(shù)據(jù)請求。此外客戶端應(yīng)用還更多的涉及文件內(nèi)容的展示;各類型的視頻,音頻,文檔,圖片,皮膚等公有和自定義文件類型的展示,網(wǎng)頁內(nèi)容展示也給移動端應(yīng)用帶來了風(fēng)險(xiǎn)。在處理外部的數(shù)據(jù)過程中,會影響應(yīng)用內(nèi)部的邏輯。除了傳統(tǒng)的數(shù)據(jù)來源,由于現(xiàn)代操作系統(tǒng)已經(jīng)進(jìn)行了應(yīng)用間的權(quán)限隔離,如何避免同系統(tǒng)中其他應(yīng)用竊取特定的權(quán)限也是需要關(guān)注的方面。下面是一些具體的風(fēng)險(xiǎn)列表:
應(yīng)用間通信(IPC):提供接口的組件權(quán)限,信息泄露,本地的數(shù)據(jù)加密和文件權(quán)限等,以安卓為例,IPC接口包括Content Provider,Broadcast Receiver,Activity,Service等形式。
遠(yuǎn)程數(shù)據(jù):開放端口接收數(shù)據(jù),接收的各類型文件,應(yīng)用的自動升級,數(shù)據(jù)傳輸明文等兩類目標(biāo):用戶:內(nèi)容偽造,導(dǎo)致不能正確判斷;程序:代碼實(shí)現(xiàn)上的漏洞,代碼執(zhí)行,權(quán)限竊取和繞過。從嚴(yán)重程度來看,首先需要注意遠(yuǎn)程來源數(shù)據(jù)。
6、安全應(yīng)對
對于大多數(shù)應(yīng)用來說,都會使用到自身代碼之外的三方邏輯,這些邏輯可能存在于調(diào)用庫中或作為獨(dú)立組件被使用,這些邏輯可能引入安全問題。對于三方的選擇,建議選取保持更新的開源項(xiàng)目,查看項(xiàng)目升級日志中修補(bǔ)過的安全列表,確認(rèn)應(yīng)用中將要使用的版本是否已經(jīng)修補(bǔ)已知安全問題,并訂閱此項(xiàng)目的版本更新郵件,能在之后發(fā)布安全更新時(shí)第一時(shí)間評估影響。
具體到自身代碼的引入的問題,需要符合最小化原則。舉例來說,對只需要應(yīng)用自身使用到的組件,不提供給其他應(yīng)用;對于不需要開放的端口,限定監(jiān)聽在特定的IP;對于本地保存的數(shù)據(jù)庫或文件等,嚴(yán)格的限定讀寫權(quán)限等。除此之外,另外兩方面就是在需要時(shí)提供完善的認(rèn)證和加密機(jī)制。以WormHole系列漏洞為例,利用的風(fēng)險(xiǎn)來源是開放的端口,而這些端口在移動網(wǎng)絡(luò)上的訪問沒有任何限制,并且在進(jìn)行高危邏輯前沒有做好認(rèn)證,這就是最小化原則和認(rèn)證機(jī)制的一個反例。
7、安全評估
(1)代碼審計(jì)
iOS開發(fā)Xcode環(huán)境可使用整合的Clang Static Analyzer,而安卓Java代碼可以使用FindBugs來完成代碼安全審計(jì)。
(2)應(yīng)用加固
目前有一些在線的應(yīng)用安全加固服務(wù)。用戶可上傳需要加固的應(yīng)用,服務(wù)器接收應(yīng)用后會從安全,逆向和調(diào)試難度等方面對應(yīng)用進(jìn)行評估,并按照用戶需要提供在這些方面完成更改后的版本供下載。
8、關(guān)于移動認(rèn)證
為了方便用戶登錄認(rèn)證,通常移動應(yīng)用通過保存登錄信息或者加上簡單的本地認(rèn)證方式(如手勢密碼或者數(shù)字PIN碼)來使用戶免于輸入完整的流程。
以支付寶為例,限定數(shù)額以下的付款甚至不需要認(rèn)證。這背后有很多需要背景數(shù)據(jù)收集,從第一次正常登錄時(shí)設(shè)備本身的信息,包括用戶日常操作行為收集的大數(shù)據(jù)等。在發(fā)現(xiàn)異常時(shí),就會觸發(fā)完整的認(rèn)證過程了。當(dāng)然在攻擊者完全控制手機(jī)的情況,如果所有認(rèn)證信息的要素都可以通過手機(jī)獲取到,例如保存的認(rèn)證信息,動態(tài)認(rèn)證短信等,更多能夠做到的也只有提高攻擊的成本,而不能完全避免認(rèn)證信息的盜用。