安卓應用安全指南4.1.2建立/使用活動規則書

apachecn_飛龍發表於2018-03-16

4.1.2 建立/使用活動 規則書

原書:Android Application Secure Design/Secure Coding Guidebook

譯者:飛龍

協議:CC BY-NC-SA 4.0

建立或向活動傳送意圖時,請務必遵循以下規則。

4.1.2.1 僅在應用內部使用的活動必須設定為私有(必需)

僅在單個應用中使用的活動,不需要能夠從其他應用接收任何意圖。 開發人員經常假設,應該是私有的活動不會受到攻擊,但有必要將這些活動顯式設定為私有,以阻止惡意內容被收到。

AndroidManifest.xml

<!-- Private activity -->
<!-- *** POINT 3 *** Explicitly set the exported attribute to false. -->
<activity
    android:name=".PrivateActivity"
    android:label="@string/app_name"
    android:exported="false" />

意圖過濾器不應該設定在僅用於單個應用的活動中。 由於意圖過濾器的特性,以及工作原理,即使您打算向內部的私有活動傳送意圖,但如果通過意圖過濾器傳送,則可能會無意中啟動另一個活動。 更多詳細資訊,請參閱高階主題“4.1.3.1 結合匯出屬性和意圖過濾器設定(用於活動)”。

AndroidManifest.xml(不推薦)

<!-- Private activity -->
<!-- *** POINT 3 *** Explicitly set the exported attribute to false. -->
<activity
    android:name=".PictureActivity"
    android:label="@string/picture_name"
    android:exported="false" >
    <intent-filter>
        <action android:name="org.jssec.android.activity.OPEN />
    </intent-filter>
</activity>

4.1.2.2 不要指定taskAffinity(必需)

在 Android OS 中,活動由任務管理。 任務名稱由根活動所具有的 Affinity 決定。 另一方面,對於根活動以外的活動,活動所屬的任務不僅僅取決於 Affinity,還取決於活動的啟動模式。 更多詳細資訊,請參閱“4.1.3.4 根活動”。

在預設設定中,每個活動使用其包名稱作為其 Affinity。 因此,任務根據應用分配,因此單個應用中的所有活動都屬於同一個任務。 要更改任務分配,您可以在AndroidManifest.xml檔案中顯式宣告 Affinity,或者您可以在傳送給活動的意圖中,設定一個標誌。 但是,如果更改任務分配,則存在風險,即其他應用可能讀取一些意圖,它傳送給屬於其他任務的活動。

請務必不要在AndroidManifest.xml檔案中指定android:taskAffinity,並使用預設設定,將 affinity 作為包名,以防止其他應用讀取傳送或接收的意圖中的敏感資訊。

以下是用於建立和使用私有活動的AndroidManifest.xml示例檔案。

AndroidManifest.xml

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <!-- Private activity -->
    <!-- *** POINT 1 *** Do not specify taskAffinity -->
    <activity
        android:name=".PrivateActivity"
        android:label="@string/app_name"
        android:exported="false" />
</application>

任務和 Affinity 的更多資訊,請參閱“Google Android 程式設計指南” [2],Google 開發者 API 指南“任務和返回棧” [3],“4.1.3.3 讀取傳送到活動的意圖”和“4.1.3.4 根活動”

[2] Author Egawa, Fujii, Asano, Fujita, Yamada, Yamaoka, Sano, Takebata, “Google Android Programming
Guide”, ASCII Media Works, July 2009

[3] http://developer.android.com/guide/components/tasks-and-back-stack.html

4.1.2.3 不要指定launchMode(必需)

活動的啟動模式,用於控制啟動活動時的設定,它用於建立新任務和活動例項。 預設情況下,它被設定為"standard"。 在"standard"設定中,新例項總是在啟動活動時建立,任務遵循屬於呼叫活動的任務,並且不可能建立新任務。 建立新任務時,其他應用可能會讀取呼叫意圖的內容,因此當敏感資訊包含在意圖中時,需要使用"standard"活動啟動模式設定。 活動的啟動模式可以在AndroidManifest.xml檔案的android:launchMode屬性中顯式設定,但由於上面解釋的原因,這不應該在活動的宣告中設定,並且該值應該保留為預設的"standard"

AndroidManifest.xml

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <!-- Private activity -->
    <!-- *** POINT 2 *** Do not specify launchMode -->
    <activity
        android:name=".PrivateActivity"
        android:label="@string/app_name"
        android:exported="false" />
</application>

請參閱“4.1.3.3 讀取傳送到活動的意圖”和“4.1.3.4 根活動”。

4.1.2.4 不要為啟動活動的意圖設定FLAG_ACTIVITY_NEW_TASK標誌(必需)

執行startActivity()startActivityForResult()時,可以更改Activity的啟動模式,並且在某些情況下可能會生成新任務。 因此有必要在執行期間不更改Activity的啟動模式。

要更改Activity啟動模式,使用setFlags()addFlags()設定Intent標誌,並將該Intent用作startActivity()startActivityForResult()的引數。 FLAG_ACTIVITY_NEW_TASK是用於建立新任務的標誌。 當設定FLAG_ACTIVITY_NEW_TASK時,如果被呼叫的Activity不存在於後臺或前臺,則會建立一個新任務。 FLAG_ACTIVITY_MULTIPLE_TASK標誌可以與FLAG_ACTIVITY_NEW_TASK同時設定。 在這種情況下,總會建立一個新的任務。 新任務可以通過任一設定建立,因此不應使用處理敏感資訊的意圖來設定這些東西。

// *** POINT 6 *** Do not set the FLAG_ACTIVITY_NEW_TASK flag for the intent to start an activity.
Intent intent = new Intent(this, PrivateActivity.class);
intent.putExtra("PARAM", "Sensitive Info");
startActivityForResult(intent, REQUEST_CODE);

另外,即使通過明確設定FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS標誌建立了新任務,您也可能認為有一種方法可以防止讀取Intent的內容。 但是,即使使用此方法,內容也可以由第三方讀取,因此您應該避免使用FLAG_ACTIVITY_NEW_TASK

請參閱“4.1.3.1 結合匯出屬性和意圖過濾設定(針對活動)”,“4.1.3.3 讀取傳送到活動的意圖”和“4.1.3.4 根活動”。

4.1.2.5 小心和安全地處理收到的意圖

風險因Activity的型別而異,但在處理收到的Intent資料時,您應該做的第一件事是輸入驗證。

由於公共活動可以從不受信任的來源接收意圖,它們可能會受到惡意軟體的攻擊。 另一方面,私有活動永遠不會直接從其他應用收到任何意圖,但目標應用中的公共活動可能會將惡意Intent轉發給私有活動,因此您不應該認為私有活動不會收到任何惡意輸入。 由於夥伴活動和內部活動也有惡意意圖轉發給他們的風險,因此有必要對這些意圖進行輸入驗證。

請參閱“3.2 仔細和安全地處理輸入資料”

4.1.2.6 在驗證簽名許可權由內部應用定義之後,使用內部定義的簽名許可權(必需)

確保在建立活動時,通過定義內部簽名許可權來保護您的內部活動。 由於在AndroidManifest.xml檔案中定義許可權或宣告許可權請求不能提供足夠的安全性,請務必參考“5.2.1.2 如何使用內部定義的簽名許可權,在內部應用之間進行通訊”。

4.1.2.7 返回結果時,請注意目標應用產生的可能的資訊洩露(必需)

當您使用setResult()返回資料時,目標應用的可靠性將取決於Activity型別。 當公共活動用於返回資料時,目標可能會成為惡意軟體,在這種情況下,可能會以惡意方式使用該資訊。 對於私有和內部活動,不需要過多擔心返回的資料被惡意使用,因為它們被返回到您控制的應用。 夥伴活動中間有些東西。

如上所述,當從活動中返回資料時,您需要注意來自目標應用的資訊洩漏。

public void onReturnResultClick(View view) {
    // *** POINT 6 *** Information that is granted to be disclosed to a partner application can be returned.
    Intent intent = new Intent();
    intent.putExtra("RESULT", "Sensitive Info");
    setResult(RESULT_OK, intent);
    finish();
}

4.1.2.8 如果目標活動是預先確定的,則使用顯式意圖(必需)

當通過隱式意圖使用Activity時,Intent傳送到的Activity由 Android OS 確定。 如果意圖被錯誤地傳送到惡意軟體,則可能發生資訊洩漏。 另一方面,當通過顯式意圖使用Activity時,只有預期的Activity會收到Intent,所以這樣更安全。 除非使用者需要確定意圖應該傳送到哪個應用活動,否則應該使用顯式意圖並提前指定目標。

Intent intent = new Intent(this, PictureActivity.class);
intent.putExtra("BARCODE", barcode);
startActivity(intent);
Intent intent = new Intent();
intent.setClassName(
    "org.jssec.android.activity.publicactivity",
    "org.jssec.android.activity.publicactivity.PublicActivity");
startActivity(intent);

但是,即使通過顯式意圖使用其他應用的公共活動,目標活動也可能是惡意軟體。 這是因為,即使通過軟體包名稱限制目標,惡意應用仍可能偽造與真實應用相同的軟體包名稱。 為了消除這種風險,有必要考慮使用夥伴或內部活動。

請參閱“4.1.3.1 組合匯出屬性和意圖過濾器設定(對於活動)”

4.1.2.9 小心並安全地處理來自被請求活動的返回資料(必需)

根據您訪問的活動型別,風險略有不同,但在處理作為返回值的收到的Intent資料,您始終需要對接收到的資料執行輸入驗證。 公共活動必須接受來自不受信任來源的返回意圖,因此在訪問公共活動時,返回的意圖實際上可能是由惡意軟體傳送的。 人們往往錯誤地認為,私有活動返回的所有內容都是安全的,因為它們來源於同一個應用。 但是,由於從不可信來源收到的意圖可能會間接轉發,因此您不應盲目信任該意圖的內容。 夥伴和內部活動在私有和公共活動中間有一定風險。 一定也要對這些活動輸入驗證。 更多資訊,請參閱“3.2 仔細和安全地處理輸入資料”。

4.1.2.10 如果與其他公司的應用連結,請驗證目標活動(必需)

與其他公司的應用連結時,確保確定了白名單。 您可以通過在應用內儲存公司的證照雜湊副本,並使用目標應用的證照雜湊來檢查它。 這將防止惡意應用欺騙意圖。 具體實現方法請參考示例程式碼“4.1.1.3 建立/使用夥伴活動”部分。 技術細節請參閱“4.1.3.2 驗證請求應用”。

4.2.11 提供二手素材時,素材應受到同等保護(必需)

當受到許可權保護的資訊或功能素材被另一個應用提供時,您需要確保它具有訪問素材所需的相同許可權。 在 Android OS 許可權安全模型中,只有已獲得適當許可權的應用才可以直接訪問受保護的素材。 但是,存在一個漏洞,因為具有素材許可權的應用可以充當代理,並允許非特權應用程式訪問它。 基本上這與重新授權相同,因此它被稱為“重新授權”問題。 請參閱“5.2.3.4 重新授權問題”。

4.2.12 敏感資訊的傳送應該儘可能限制(推薦)

您不應將敏感資訊傳送給不受信任的各方。 即使您正在連線特定的應用程式,仍有可能無意中將Intent傳送給其他應用程式,或者惡意第三方可能會竊取您的意圖。 請參閱“4.1.3.5 使用活動時的日誌輸出”。

將敏感資訊傳送到活動時,您需要考慮資訊洩露的風險。 您必須假設,傳送到公共活動的Intent中的所有資料都可以由惡意第三方獲取。 此外,根據實現,向夥伴或內部活動傳送意圖時,也存在各種資訊洩漏的風險。 即使將資料傳送到私有活動,也存在風險,意圖中的資料可能通過LogCat洩漏。 意圖附加部分中的資訊不會輸出到LogCat`,因此最好在那裡儲存敏感資訊。

但是,不首先傳送敏感資料,是防止資訊洩露的唯一完美解決方案,因此您應該儘可能限制傳送的敏感資訊的數量。 當有必要傳送敏感資訊時,最好的做法是隻傳送給受信任的活動,並確保資訊不能通過LogCat洩露。

另外,敏感資訊不應該傳送到根活動。 根活動是建立任務時首先呼叫的活動。 例如,從啟動器啟動的活動始終是根活動。

根活動的更多詳細資訊,請參閱“4.1.3.3 傳送到活動的意圖”和“4.1.3.4 根活動”。


相關文章