5.2.2 權限和保護級别 規則書
原書: Android Application Secure Design/Secure Coding Guidebook 譯者: 飛龍 協定: CC BY-NC-SA 4.0
使用内部權限時,請確定遵循以下規則:
5.2.2.1 Android 的系統危險權限隻能用于保護使用者資産(必需)
由于不建議你使用自己的危險權限(請參閱“5.2.2.2 你自己的危險權限不得使用(必需)”),我們将在使用 Android 作業系統的系統危險權限的前提下進行。
不像其他三種類型的權限,危險權限具有這個特性,需要使用者同意授予應用權限,在聲明了危險權限的裝置上安裝應用時,将顯示以下螢幕:随後, 使用者可以知道應用試圖使用的權限級别(危險權限和正常權限),當使用者點選“安裝”時,應用将被授予權限,然後安裝。
應用可以處理開發人員希望保護的使用者資産。 我們必須意識到,危險的權限隻能保護使用者資産,因為使用者隻是授予權限的人。 另一方面,開發人員想要保護的資産不能用上述方法保護。
例如,假設應用具有一個元件,隻與内部應用通信,它不允許從其他公司的任何應用通路該元件,并且通過危險權限的保護來實作。 當使用者根據判斷,向另一家公司的應用授予權限時,需要保護的内部資産可能通過應用授權來利用。 為了在此類情況下保護内部資産,我們建議使用内部定義的簽名權限。
5.2.2.2 不能使用你自己的危險權限(必需)
即使使用内部定義的危險權限,在某些情況下,螢幕提示“請求允許來自使用者的權限”也不會顯示。 這意味着,有時根據使用者判斷來請求權限的特性(危險權限的特征)不起作用。 是以,指導手冊規定“不得使用内部定義的危險權限”。
為了解釋它,我們假設有兩種類型的應用。 第一種類型的應用定義了内部危險權限,并且它讓受此權限保護的元件公開。 我們稱之為
ProtectedApp
。 另一個是我們稱為
AttackerApp
,它試圖利用
ProtectedApp
的元件。 我們還假設
AttackerApp
不僅聲明了使用它的權限,而且還定義了相同的權限。
在以下情況下,
AttackerApp
可以在未經使用者同意的情況下,使用
ProtectedApp
的元件:
- 當使用者安裝
時,安裝将在沒有螢幕提示的情況下完成,它要求使用者授予應用危險權限。AttackerApp
- 同樣,當使用者安裝
時,安裝将會完成而沒有任何特别的警告。ProtectedApp
- 當使用者啟動
後,AttackerApp
可以通路AttackerApp
的元件,而不會被使用者檢測到,這可能會導緻損失。ProtectedApp
這種情況的原因在下面解釋。 當使用者嘗試首先安裝
AttackerApp
時,在特定裝置上,尚未使用
uses-permission
來定義聲明的權限。 沒有發現錯誤,Android 作業系統将繼續安裝。 由于隻有在安裝時使用者才需要同意危險權限,是以已安裝的應用将被視為已被授予權限。 是以,如果稍後安裝的應用的元件受到名稱相同的危險權限的保護,則在未經使用者同意的情況下,事先安裝的應用将能夠利用該元件。
此外,由于在安裝應用時,确儲存在 Android OS 定義的系統危險權限,每次安裝具有
uses-permission
的應用時,都會顯示使用者驗證提示。 隻有在自定義危險權限的情況下才會出現此問題。 在寫這篇文章的時候,還沒有開發出可行方法,在這種情況下保護元件的通路。 是以,你不得使用你自己的危險權限。
5.2.2.3 你自己的簽名權限必需僅在提供方定義(必需)
如“5.2.1.2 如何使用内部定義的簽名權限,在内部應用之間進行通信”中所示,在進行内部應用之間的内部通信時,通過檢查簽名權限,可以確定安全性。 當使用這種機制時,保護級别為簽名的權限的定義,必須寫在具有元件的提供方應用的
AndroidManifest.xml
中,但使用者方應用不能定義簽名權限。
此規則也适用于
signatureOrSystem
權限。原因如下。
我們假設,在提供方應用之前安裝了多個使用者方應用,并且每個使用者方應用,不僅要求提供方應用定義的簽名權限,而且還定義了相同的權限。 在這些情況下,所有使用者方應用都可以在安裝提供方應用之後,立即通路提供方應用。 随後,解除安裝先安裝的使用者方應用時,權限的定義也将被删除,然後該權限将變為未定義。 是以,其餘的使用者方應用将無法通路提供方應用。
以這種方式,當使用者方應用定義了一個自定義權限時,它可能會意外地将權限設定為未定義。是以,隻有提供需要保護的元件的提供方應用才應該定義權限,并且必須避免在使用者方定義權限。
通過如上所述的那樣,自定義權限将在安裝提供方應用時由 Android OS 應用,并且在解除安裝應用時權限将變得未定義。是以,由于權限定義總是對應提供方應用的定義,是以可以提供适當的元件并對其進行保護。請注意,這個觀點成立,是因為對于内部定義的簽名權限,使用者方應用被授予權限,而不管應用在互相通信中的安裝順序 [24]。
[24] 如果使用正常/危險權限,并且使用者方應用安裝在提供方應用之前,則該權限将不會授予使用者方應用,權限仍未定義。 是以,即使在安裝了提供方應用之後,也不能通路元件。
5.2.2.4 驗證内部定義的簽名權限是否由内部應用定義(必需)
實際上,隻有通過
AnroidManifest.xml
聲明簽名權限并使用權限來保護元件,才能說是足夠安全。 此問題的詳細資訊,請參閱“進階主題”部分中的“5.2.3.1 繞過自定義簽名權限的 Android 作業系統特性及其對策”。
以下是安全并正确使用内部定義的簽名權限的步驟。
首先,在
AndroidManifest.xml
中編寫如下代碼:
在提供方應用的
AndroidManifest.xml
中定義内部簽名權限。(權限定義)
例如:
<permission android:name="xxx" android:protectionLevel="signature" />
AndroidManifest.xml
中,使用要保護的元件的權限屬性強制執行權限。 (執行權限)
<activity android:permission="xxx" ... >...</activity>
在每個使用者方應用的
AndroidManifest.xml
中,使用
uses-permission
标簽聲明内部定義的簽名權限,來通路要保護的元件。 (使用權限聲明)
<uses-permission android:name="xxx" />
下面,在源代碼中實作這些:
在處理元件的請求之前,首先驗證内部定義的簽名權限是否由内部應用定義。 如果不是,請忽略該請求。 (保護提供方元件)
在通路元件之前,請先驗證内部定義的簽名權限是否由内部應用定義。 否則,請勿通路元件(使用者方元件中的保護)。
最後,使用 Android Studio 的簽名功能之前,執行下列事情:
使用相同的開發人員密鑰,對所有互相通信的應用的 APK 進行簽名。
在此,對于如何實作“确認内部定義簽名權限已由内部應用定義”的具體要點,請參閱“5.2.1.2 如何使用内部定義的簽名權限,在内部應用之間進行通信”。
signatureOrSystem
權限。
5.2.2.5 不應該使用你自己的普通權限(推薦)
應用隻需在
AndroidManifest.xml
中使用
uses-permission
聲明,即可使用正常權限。 是以,你不能使用正常權限,來保護元件免受惡意軟體的安裝。
此外,在使用自定義普通權限進行應用間通信的情況下,應用是否可以被授予權限取決于安裝順序。 例如,當你安裝已聲明使用普通權限的應用(使用者方法),并且在另一應用(提供者端)之前,它擁有已定義權限的元件,使用者方應用将無法 通路受權限保護的元件,即使稍後安裝提供方應用也是如此。
作為一種方法,防止由于安裝順序而導緻的應用間通信丢失,你可以考慮在通信中的每個應用中定義權限。 通過這種方式,即使在提供方應用之前安裝了使用者方應用,所有使用者方應用也将能夠通路提供方應用。 但是,它會産生一種情況,即在解除安裝第一個安裝的使用者方應用時,權限未定義。 是以,即使有其他使用者方應用,他們也無法通路提供方應用。
如上所述,存在損害應用可用性的風險,是以不應使用你自己的正常權限。
5.2.2.6 你自己的權限名稱的字元串應該是應用包名的擴充(推薦)
當多個應用使用相同名稱定義權限時,将使用先安裝的應用所定義的保護級别。 如果首先安裝的應用定義了正常權限,并且稍後安裝的應用使用相同的名稱定義了簽名權限,則簽名權限的保護将不可用。 即使沒有惡意的意圖,多個應用之間的權限名稱沖突,也可能導緻任何應用的行為成為意外的保護級别。 為防止發生此類事故,建議權限名稱擴充于定義權限的應用的包名(以它開頭),如下所示。
(package name).permission.(identifying string)
例如,為
org.jssec.android.sample
包定義
READ
通路權限時,以下名稱将是首選。
org.jssec.android.sample.permission.READ