Android 安全架構及許可權控制機制剖析

發表於2012-08-16

來源:IBM DeveloperWorks

簡介: Android 是業界流行的開源移動平臺,受到廣泛關注併為多個手機制造商作為手機的作業系統平臺,因此,研究其安全架構及許可權控制機制具有非常的重要性。本文從 Android 層次化安全架構入手,詳細地介紹 Android 平臺的安全架構及其許可權控制機制,涵蓋 Android 應用程式許可權申請方法等,並從原始碼實現層面來解析該機制。

Android 層次化安全架構

Android 作為一個移動裝置的平臺,其軟體層次結構包括了一個作業系統(OS),中介軟體(MiddleWare)和應用程式(Application)。根據 Android 的軟體框圖,其軟體層次結構自下而上分為以下幾個層次:

●作業系統層(OS)

●各種庫(Libraries)和 Android 執行環境(RunTime)

●應用程式框架(Application Framework)

●應用程式(Application)

以下分別介紹 Andoid 各個層次的軟體的重點及其相關技術:

(1)作業系統層(OS)

Android 使用 Linux2.6 作為作業系統,Linux2.6 是一種標準的技術,Linux 也是一個開放的作業系統。Android 對作業系統的使用包括核心和驅動程式兩部分,Android 的 Linux 核心為標準的 Linux2.6 核心,Android 更多的是需要一些與移動裝置相關的驅動程式。主要的驅動如下所示:

●顯示驅動(Display Driver):常用基於 Linux 的幀緩衝(Frame Buffer)驅動

●Flash 記憶體驅動(Flash Memory Driver)

●照相機驅動(Camera Driver):常用基於 Linux 的 v4l(Video for )驅動。

●音訊驅動(Audio Driver):常用基於 ALSA(Advanced Linux Sound Architecture,高階 Linux 聲音體系)驅動

●WiFi 驅動(Camera Driver):基於 IEEE 802.11 標準的驅動程式

●鍵盤驅動(KeyBoard Driver)

●藍芽驅動(Bluetooth Driver)

●Binder IPC 驅動:Andoid 一個特殊的驅動程式,具有單獨的裝置節點,提供程式間通訊的功能。

●Power Management(能源管理)

(2)各種庫(Libraries)和 Android 執行環境(RunTime)

本層次對應一般嵌入式系統,相當於中介軟體層次。Android 的本層次分成兩個部分一個是各種庫,另一個是 Android 執行環境。本層的內容大多是使用 C++ 實現的。 在其中,各種庫包括:

●C 庫:C 語言的標準庫,這也是系統中一個最為底層的庫,C 庫是通過 Linux 的系統呼叫來實現。

●多媒體框架(MediaFrameword):這部分內容是 Android 多媒體的核心部分,基於 PacketVideo(即 PV)的 OpenCORE,從功能上本庫一共分為兩大部分,一個部分是音訊、視訊的回放(PlayBack),另一部分是則是音視訊的紀錄(Recorder)。

●SGL:2D 影像引擎。

●SSL:即 Secure Socket Layer 位於 TCP/IP 協議與各種應用層協議之間 , 為資料通訊提供安全支援。

●OpenGL ES 1.0 :本部分提供了對 3D 的支援。

●介面管理工具(Surface Management):本部分提供了對管理顯示子系統等功能。

●SQLite:一個通用的嵌入式資料庫

●WebKit:網路瀏覽器的核心

●FreeType:點陣圖和向量字型的功能。

Android 的各種庫一般是以系統中介軟體的形式提供的,它們均有的一個顯著特點就是與移動裝置的平臺的應用密切相關。 Android 執行環境主要指的虛擬機器技術—— Dalvik。Dalvik 虛擬機器和一般 JAVA 虛擬機器(Java VM)不同,它執行的不是 JAVA 標準的位元組碼(bytecode )而是 Dalvik 可執行格式(.dex)中執行檔案。在執行的過程中,每一個應用程式即一個程式(Linux 的一個 Process)。 二者最大的區別在於 Java VM 是以基於棧的虛擬機器(Stack-based),而 Dalvik 是基於暫存器的虛擬機器(Register-based)。顯然,後者最大的好處在於可以根據硬體實現更大的優化,這更適合移動裝置的特點。

(3)應用程式框架(Application Framework)

Android 的應用程式框架為應用程式層的開發者提供 APIs,它實際上是一個應用程式的框架。由於上層的應用程式是以 JAVA 構建的,因此本層次提供的首先包含了 UI 程式中所需要的各種控制元件: 例如: Views ( 檢視元件 ) 包括 lists( 列表 ), grids( 柵格 ), text boxes( 文字框 ), buttons( 按鈕 ) 等,甚至一個嵌入式的 Web 瀏覽器。一個 Android 的應用程式可以利用應用程式框架中的以下幾個部分: Activity (活動)、Broadcast Intent Receiver (廣播意圖接收者)、Service (服務)、Content Provider (內容提供者)。

(4)應用程式(Application)

Android 的應用程式主要是使用者介面(User Interface),通常以 JAVA 程式編寫,其中還可以包含各種資原始檔(放置在 res 目錄中)。JAVA 程式及相關資源經過編譯後,將生成一個 APK 包。Android 本身提供了主螢幕(Home),聯絡人(Contact),電話(Phone),瀏覽器(Browsers)等眾多的核心應用。同時應用程式的開發者還可以使用應用程式框架層的 API 實現自己的程式。

圖 1. Android 分層安全架構圖

Android 安全架構及許可權控制機制剖析

Android 的元件模型(Component Model)

Android 系統中包括 4 種元件:

(1)Activity

Activity 就是一個介面,這個介面裡面可以放置各種控制元件。例如:Task Manager 的介面、Root Explorer 的介面等;Activity 是為使用者操作而展示的視覺化使用者介面。例如說,一個 activity 可以展示一個選單項列表供使用者選擇,或者顯示一些包含說明的照片。一個短訊息應用程式可以包括一個用於顯示做為傳送物件的聯絡人的列表的 activity,一個給選定的聯絡人寫簡訊的 activity 以及翻閱以前的簡訊和改變設定的 activity。儘管

它們一起組成了一個內聚的使用者介面,但其中每個 activity 都與其它的保持獨立。每個都是以 Activity類為基類的子類實現。
一個應用程式可以只有一個 activity,或者,如剛才提到的簡訊應用程式那樣,包含很多個。而每個 activity 的作用以及其數目,自然取決於應用程式及其設計。一般情況下,總有一個應用程式被標記為使用者在應用程式啟動的時候第一個看到的。從一個 activity 轉向另一個的方式是靠當前的 activity 啟動下一個。

每個 activity 都被給予一個預設的視窗以進行繪製。一般情況下,這個視窗是滿屏的,但它也可以是一個小的位於其它視窗之上的浮動視窗。一個 activity 也可以使用超過一個的視窗。例如,在 activity 執行過程中彈出的一個供使用者反應的小對話方塊,或是當使用者選擇了螢幕上特定專案後顯示的必要資訊。

視窗顯示的可視內容是由一系列檢視構成的,這些檢視均繼承自 View基類。每個檢視均控制著視窗中一塊特定的矩形空間。父級檢視包含並組織它子檢視的佈局。葉節點檢視(位於檢視層次最底端)在它們控制的矩形中進行繪製,並對使用者對其直接操作做出響應。所以,檢視是 activity 與使用者進行互動的介面。例如說,檢視可以顯示一個小圖片,並在使用者指點它的時候產生動作。Android 有很多既定的檢視供使用者直接使用,包括按鈕、文字域、卷軸、選單項、核取方塊等等。

(2)Service

服務是執行在後臺的功能模組。如檔案下載、音樂播放程式等;服務沒有視覺化的使用者介面,而是在一段時間內在後臺執行。例如說,一個服務可以在使用者做其它事情的時候在後臺播放背景音樂、從網路上獲取一些資料或者計算一些東西並提供給需要這個運算結果的 activity 使用。每個服務都繼承自 Service基類。

一個媒體播放器播放播放列表中的曲目是一個不錯的例子。播放器應用程式可能有一個或多個 activity 來給使用者選擇歌曲並進行播放。然而,音樂播放這個任務本身不應該為任何 activity 所處理,因為使用者期望在他們離開播放器應用程式而開始做別的事情時,音樂仍在繼續播放。為達到這個目的,媒體播放器 activity 應該啟用一個執行於後臺的服務。而系統將在這個 activity 不再顯示於螢幕之後,仍維持音樂播放服務的執行。
可以連線至(繫結)一個正在執行的服務(如果服務沒有執行,則啟動之)。連線之後,可以通過那個服務暴露出來的介面與服務進行通訊。對於音樂服務來說,這個介面可以允許使用者暫停、回退、停止以及重新開始播放。

(3)Content Provider

它是 Android 平臺應用程式間資料共享的一種標準介面,它以類似於 URI(Universal Resources Identification)的方式來表示資料,如:content://contacts/people/1101;內容提供者將一些特定的應用程式資料供給其它應用程式使用。資料可以儲存於檔案系統、SQLite 資料庫或其它方式。內容提供者繼承於 ContentProvider基類,為其它應用程式取用和儲存它管理的資料實現了一套標準方法。然而,應用程式並不直接呼叫這些方法,而是使用一個 ContentResolver物件,呼叫它的方法作為替代。ContentResolver 可以與任意內容提供者進行會話,與其合作來對所有相關互動通訊進行管理。

(4)Broadcast Receiver

Broadcast Receiver 是一個專注於接收廣播通知資訊,並做出對應處理的元件。很多廣播是源自於系統程式碼的。例如,通知時區改變、電池電量低、拍攝了一張照片或者使用者改變了語言選項。應用程式也可以進行廣播,例如通知其它應用程式一些資料下載完成並處於可用狀態。

應用程式可以擁有任意數量的 Broadcast Receiver 以對所有它感興趣的通知資訊予以響應。所有的接收器均繼承自 BroadcastReceiver基類。
Broadcast Receiver 沒有使用者介面。然而,它們可以啟動一個 activity 來響應它們收到的資訊,或者用 NotificationManager來通知使用者。通知可以用很多種方式來吸引使用者的注意力──閃動背燈、震動、播放聲音等等。一般來說是在狀態列上放一個持久的圖示,使用者可以開啟它並獲取訊息。

與此元件相關的概念是 Intent,Intent 是一個對動作和行為的抽象描述,負責元件之間程式之間進行訊息傳遞。而 Broadcast Receiver 元件則提供了一種把 Intent 作為一個訊息廣播出去,由所有對其感興趣的程式對其作出反應的機制。舉個簡單的例子,為了實現一個系統啟動後播放音樂的功能,則可以定義 Intent 為 android.intent.action.BOOT_COMPLETED,由 Broadcast Receiver 元件將其進行廣播,而系統中的 Media Player 接收到該資訊後則進行播放。

如上所述,4 個元件之間的關係如下圖:

圖 2. Android 各元件關係圖

Android 安全架構及許可權控制機制剖析

Android 的許可權分類

根據使用者的使用過程體驗,可以將 Android 涉及的許可權大致分為如下三類:

(1)Android 手機所有者許可權:自使用者購買 Android 手機後,使用者不需要輸入任何密碼,就具有安裝一般應用軟體、使用應用程式等的許可權;

(2)Android root 許可權:該許可權為 Android 系統的最高許可權,可以對所有系統中檔案、資料進行任意操作。出廠時預設沒有該許可權,需要使用 z4Root 等軟體進行獲取,然而,並不鼓勵進行此操作,因為可能由此使使用者失去手機原廠保修的權益。同樣,如果將 Android 手機進行 root 許可權提升,則此後使用者不需要輸入任何密碼,都將能以 Android root 許可權來使用手機。

(3)Android 應用程式許可權:Android 提供了豐富的 SDK(Software development kit),開發人員可以根據其開發 Android 中的應用程式。而應用程式對 Android 系統資源的訪問需要有相應的訪問許可權,這個許可權就稱為 Android 應用程式許可權,它在應用程式設計時設定,在 Android 系統中初次安裝時即生效。值得注意的是:如果應用程式設計的許可權大於 Android 手機所有者許可權,則該應用程式無法執行。如:沒有獲取 Android root 許可權的手機無法執行 Root Explorer,因為執行該應用程式需要 Android root 許可權。

Android 系統許可權定義

Android 系統在 /system/core/private/android_filesystem_config.h 標頭檔案中對 Android 使用者 / 使用者組作了如下定義,且許可權均基於該使用者 / 使用者組設定。

 

值得注意的是:每個應用程式在安裝到 Android 系統後,系統都會為其分配一個使用者 ID,如 app_4、app_11 等。以下是 Calendar 和 Terminal 軟體在 Android 系統中程式瀏覽的結果(其中,黑色字型標明的即為應用分配的使用者 ID):

在 Android 系統中,上述使用者 / 使用者組對檔案的訪問遵循 Linux 系統的訪問控制原則,即根據長度為 10 個字元的許可權控制符來決定使用者 / 使用者組對檔案的訪問許可權。該控制符的格式遵循下列規則:

●第 1 個字元:表示一種特殊的檔案型別。其中字元可為 d( 表示該檔案是一個目錄 )、b( 表示該檔案是一個系統裝置,使用塊輸入 / 輸出與外界互動,通常為一個磁碟 )、c( 表示該檔案是一個系統裝置,使用連續的字元輸入 / 輸出與外界互動,如串列埠和聲音裝置 ),“.”表示該檔案是一個普通檔案,沒有特殊屬性。

●2 ~ 4 個字元:用來確定檔案的使用者 (user) 許可權;

●5 ~ 7 個字元:用來確定檔案的組 (group) 許可權;

●8 ~ 10 個字元:用來確定檔案的其它使用者 (other user,既不是檔案所有者,也不是組成員的使用者 ) 的許可權。

●第 2、5、8 個字元是用來控制檔案的讀許可權的,該位字元為 r 表示允許使用者、組成員或其它人可從該檔案中讀取資料。短線“-”則表示不允許該成員讀取資料。

●第 3、6、9 位的字元控制檔案的寫許可權,該位若為 w 表示允許寫,若為“-”表示不允許寫。

●第 4、7、10 位的字元用來控制檔案的製造許可權,該位若為 x 表示允許執行,若為“-”表示不允許執行。

舉個例子,“drwxrwxr– 2 root root 4096 2 月 11 10:36 lu”表示的訪問控制許可權(黑色字型標明)為:因為 lu 的第 1 個位置的字元是 d,所以由此知道 lu 是一個目錄。第 2 至 4 位置上的屬性是 rwx,表示使用者 root 擁有許可權列表顯示 lu 中所有的檔案、建立新檔案或者刪除 lu 中現有的檔案,或者將 lu 作為當前工作目錄。第 5 至 7 個位置上的許可權是 rwx,表示 root 組的成員擁有和 root 一樣的許可權。第 8 至 10 位上的許可權僅是 r–,表示不是 root 的使用者及不屬於 root 組的成員只有對 lu 目錄列表的許可權。這些使用者不能建立或者刪除 lu 中的檔案、執行 junk 中的可執行檔案,或者將 junk 作為他們的當前工作目錄。

Android 應用程式許可權申請

每個應用程式的 APK 包裡面都包含有一個 AndroidMainifest.xml 檔案,該檔案除了羅列應用程式執行時庫、執行依賴關係等之外,還會詳細地羅列出該應用程式所需的系統訪問。程式設計師在進行應用軟體開發時,需要通過設定該檔案的 uses-permission 欄位來顯式地向 Android 系統申請訪問許可權。

AndroidMainifest.xml 檔案用途

AndroidManifest.xml 主要包含以下功能:

1、說明 application 的 java 資料包,資料包名是 application 的唯一標識;

2、描述 application 的 component;

3、說明 application 的 component 執行在哪個 process 下;

4、宣告 application 所必須具備的許可權,用以訪問受保護的部分 API,以及與其他 application 的互動;

5、宣告 application 其他的必備許可權,用以 component 之間的互動;

6、列舉 application 執行時需要的環境配置資訊,這些宣告資訊只在程式開發和測試時存在,釋出前將被刪除;

7、宣告 application 所需要的 Android API 的最低版本級別,例如 1.0,1.1,1.5;

8、列舉 application 所需要連結的庫;

 

AndroidManifest.xml 檔案的結構及元素

AndroidManifest.xml 檔案的結構、元素,以及元素的屬性,可以在 Android SDK 文件中檢視詳細說明。而在看這些眾多的元素以及元素的屬性前,需要先了解一下這些元素在命名、結構等方面的規則:

1、元素:在所有的元素中只有 和 是必需的,且只能出現一次。如果一個元素包含有其他子元素,必須通過子元素的屬性來設定其值。處於同一層次的元素,這些元素的說明是沒有順序的。

2、屬性:按照常理,所有的屬性都是可選的,但是有些屬性是必須設定的。那些真正可選的屬性,即使不存在,其也有預設的數值項說明。除了根元素 的屬性,所有其他元素屬性的名字都是以 android: 字首的;

3、定義類名:所有的元素名都對應其在 SDK 中的類名,如果你自己定義類名,必須包含類的資料包名,如果類與 application 處於同一資料包中,可以直接簡寫為“.”;

4、多數值項:如果某個元素有超過一個數值,這個元素必須通過重複的方式來說明其某個屬性具有多個數值項,且不能將多個數值項一次性說明在一個屬性中;

5、資源項說明:當需要引用某個資源時,其採用如下格式:@[package:]type:name。例如

6、字串值:類似於其他語言,如果字元中包含有字元“\”,則必須使用轉義字元“\\”;

下面結合 cookie 例項中的 AndroidManifest.xml 檔案來說明一下,原 XML 檔案如下:

除了頭部的 XML 資訊說明外,首先是 manifest 項(也就是根節點),其屬性包括:schemas URL 地址、包名(moandroid.cookie),以及程式的版本說明。其次是 manifest 的子節點 application,其屬性包括:程式圖示、程式名稱。前面帶有 @ 表示引用資源,例如:@drawable/icon 表示引用的是 drawable 資源中的 icon,可以在其源工程的 res/drawable 中找到。然後就是 application 的子節點 activity,其屬性包括:activity 的名稱、activity 的標籤名,其子節點 intent-filter 則是對 activity 的說明。

而在 intent-filter 中,action android:name=”android.intent.action.MAIN”和 category android:name=”android.intent.category.LAUNCHER”用以說明程式啟動時的入口 activity 是哪個。如果這兩個屬性值中分別含有 MAIN 和 LAUNCHER,則說明它就是啟動程式時的入口活動。uses-sdk android:minSdkVersion=”3 ″說明程式使用的 Android SDK 的最低版本,其中 1 表示 Android 1.0,2 表示 Android 1.1,而 3 則表示 Android 1.5。

如何進行應用程式許可權申請

如下所示,文中黑體標記的部分為應用程式許可權申請內容:

如上述檔案描述中加下劃線的斜體部分,該檔案的作用是說明該軟體需要傳送簡訊的功能。

Android 定義了百餘種 permission,可供開發人員使用,具體詳見網址:http://developers.androidcn.com/reference/android/Manifest.permission.html。

在檔案中,使用者還可以自定義許可權。permission 就是自定義許可權的宣告,可以用來限制 app 中特殊元件,特性與 app 內部或者和其他 app 之間訪問。寫了一個引用自定義許可權的例子,在安裝 app 的時候,提示許可權:

定義許可權如下:

宣告的含義如下;

android:label:許可權名字,顯示給使用者的,值可是一個 string 資料,例如這裡的“自定義許可權”。

android:description:比 label 更長的對許可權的描述。值是通過 resource 檔案中獲取的,不能直接寫 string 值,例如這裡的”@string/test”。

android:name:許可權名字,如果其他 app 引用該許可權需要填寫這個名字。

android:protectionLevel:許可權級別,分為 4 個級別:

○normal:低風險許可權,在安裝的時候,系統會自動授予許可權給 application。

○dangerous:高風險許可權,系統不會自動授予許可權給 app,在用到的時候,會給使用者提示。

○signature:簽名許可權,在其他 app 引用宣告的許可權的時候,需要保證兩個 app 的簽名一致。這樣系統就會自動授予許可權給第三方 app,而不提示給使用者。

○signatureOrSystem:這個許可權是引用該許可權的 app 需要有和系統同樣的簽名才能授予的許可權,一般不推薦使用。

值得注意的是:通過測試發現一種特殊的情況,應用程式可以在程式執行時申請 root 許可權,如下圖,在使用 Android Terminal Emulator 時嘗試使用 su 命令切換到 root 使用者。若使用者已通過 hacking 的方式使得 Android 系統獲得了 root 許可權,則可以允許該程式以 root 使用者許可權執行;反之即算使用者選擇“允許”,也不能使程式以 root 使用者許可權執行。

圖 3. Android 使用者許可權賦予示意圖

Android 安全架構及許可權控制機制剖析

Android 系統對應用程式許可權申請的處理方式分析

對 Android 原始碼中的如下檔案進行分析:

●InstallAppProgress.java:其路徑為 \packages\apps\PackageInstaller\src\com\android\packageinstaller\InstallAppProgress.java;

●PackageInstallerActivity.java:其路徑為 \packages\apps\PackageInstaller\src\com\android\packageinstaller\PackageInstallerActivity.java;

●AppSecurityPermissions.java:其路徑為 \frameworks\base\core\java\android\widget\AppSecurityPermissions.java

總結得出如下圖所示的 Android 系統對應用程式授權申請的處理流程:

●進入處理應用程式授權申請的入口函式;

●系統從被安裝應用程式的 AndroidManifest.xml 檔案中獲取該應用正常執行需申請的許可權列表;

●顯示對話方塊,請求使用者確認是否滿足這些許可權需求;

●若同意,則應用程式正常安裝,並被賦予相應的許可權;若否定,則應用程式不被安裝。系統僅提供給使用者選擇“是”或者“否”的權利,沒有選擇其中某些許可權進行授權的權利。

圖 4. Android 使用者許可權賦予示意圖

Android 安全架構及許可權控制機制剖析

相關文章