「網路安全性設定」功能可讓您在安全的宣告式設定檔中,自訂應用程式的網路安全性設定,且不必修改應用程式程式碼。您可以為特定網域和應用程式調整這些設定。這項功能的主要特性如下:
- 自訂信任錨點:為應用程式安全連線自訂信任的憑證授權單位 (CA)。例如,信任特定的自行簽署憑證,或限制應用程式信任的公開 CA 組合。
- 僅限偵錯的覆寫機制:安全地偵錯應用程式中的安全連線,不會對已安裝應用程式的使用者增添風險。
- 選擇不採用明文流量:避免應用程式意外使用明文 (未加密) 的流量。
- 憑證綁定:限制應用程式的安全連線只能使用特定憑證。
新增網路安全性設定檔案
「網路安全性設定」功能會使用 XML 檔案,您可以在該檔案中指定應用程式設定。您必須在應用程式資訊清單中,加入一個指向該檔案的項目。下列資訊清單節錄內容示範了建立此項目的方法:
<?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:networkSecurityConfig="@xml/network_security_config" ... > ... </application> </manifest>
自訂信任的 CA
您可能會希望應用程式信任自訂的 CA 組合,而非平台預設值。這種情況最常見的原因包括:
- 連線至含有自訂 CA 的主機,例如自行簽署或在公司內部核發的 CA。
- 將 CA 限制在您信任的 CA 組合,而非所有預先安裝的 CA。
- 信任系統中未包含的其他 CA。
根據預設,所有應用程式的安全連線 (使用傳輸層安全標準 (TLS) 和 HTTPS 等通訊協定) 會信任預先安裝的系統 CA,指定 Android 6.0 (API 級別 23) 以下版本的應用程式也會信任使用者新增的 CA 儲存庫。您可以使用 base-config
(針對應用程式範圍自訂) 或 domain-config
(針對個別網域自訂),自訂應用程式的連線。
設定自訂 CA
建議您在連線至主機時,該主機使用自行簽署的 SSL 憑證,或是由您信任的非公開 CA (例如貴公司的內部 CA) 核發的 SSL 憑證。以下程式碼片段示範如何在 res/xml/network_security_config.xml
中為自訂 CA 設定應用程式:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </domain-config> </network-security-config>
請將自行簽署或非公開的 CA 憑證,以 PEM 或 DER 格式新增至 res/raw/my_ca
。
限制信任的 CA 組合
如果您不希望應用程式信任符合系統信任的所有 CA,可以改為指定一組數量較少的信任 CA。這麼做可防止應用程式信任其他 CA 核發的詐欺憑證。
這項設定會限制信任 CA 的組合,因此與針對特定網域信任自訂 CA 類似,不同之處在於前者的多個 CA 是在資源中提供。下列程式碼片段示範如何在 res/xml/network_security_config.xml
中,限制應用程式的信任 CA 組合:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/> </trust-anchors> </domain-config> </network-security-config>
將信任的 CA 以 PEM 或 DER 格式新增至 res/raw/trusted_roots
。請注意,如果採用 PEM 格式,則檔案「只能」包含 PEM 資料,且不得含有其他文字。您也可以提供多個 <certificates>
元素,而非單一元素。
信任其他 CA
您可能會希望應用程式信任系統不信任的其他 CA,例如系統尚未納入的 CA,或是 CA 不符合納入 Android 系統的條件。您可以在 res/xml/network_security_config.xml
中使用程式碼,為設定指定多個憑證來源,如以下節錄內容所示。
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="@raw/extracas"/> <certificates src="system"/> </trust-anchors> </base-config> </network-security-config>
設定用於偵錯的 CA
對透過 HTTPS 連線的應用程式偵錯時,建議您連線至沒有為實際執行伺服器提˙供 SSL 憑證的本機開發伺服器。如想支援這項功能而不修改應用程式的程式碼,您可以使用 debug-overrides
指定僅供偵錯的 CA,「只」在 android:debuggable 為 true
時,才信任該 CA。通常,IDE 和建構工具會為非發布子版本自動設定這個標記。
這比一般的條件式程式碼更為安全,因為基於安全考量,應用程式商店不接受標示為可進行偵錯的應用程式。
以下節錄說明如何在 res/xml/network_security_config.xml
中指定僅供偵錯的 CA:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors> <certificates src="@raw/debug_cas"/> </trust-anchors> </debug-overrides> </network-security-config>
選擇停用明文流量
注意:本節指南僅適用於指定 Android 8.1 (API 級別 27) 以下版本的應用程式。自 Android 9 (API 級別 28) 開始,系統會預設停用明文支援功能。
如果您希望應用程式只使用安全連線連結至目的地,可以選擇對這些目的地停用明文 (使用未加密的 HTTP 通訊協定,而非 HTTPS) 支援功能。這個選項可防止因為外部來源 (如後端伺服器) 提供的網址有變,導致應用程式發生迴歸錯誤。詳情請參閱 NetworkSecurityPolicy.isCleartextTrafficPermitted()
。
例如,您可能希望確保應用程式一律透過 HTTPS 連線至 secure.example.com
,以保護來自惡意網路的敏感流量。
以下節錄說明如何在 res/xml/network_security_config.xml
中停用明文:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </network-security-config>
綁定憑證
一般來說,應用程式會信任所有預先安裝的 CA。如果這類 CA 發送詐欺憑證,應用程式會有遭受路徑上攻擊的風險。有些應用程式為了限制接受的憑證組合,會限制要信任的 CA 組合,或是綁定憑證。
系統會使用公開金鑰 (X.509 憑證的 SubjectPublicKeyInfo
) 雜湊值,提供一組憑證來綁定憑證。只有憑證鏈結含有至少一個綁定的公開金鑰時,該鏈結才有效。
請注意,使用憑證綁定功能時,建議您一律加入備用金鑰,這樣一來,若系統強制要求您改用新金鑰或變更 CA (綁定至 CA 憑證或該 CA 的中繼憑證時),應用程式的連線能力就不會受到影響。否則,您必須向應用程式推送更新才能恢復連線。
此外,您也可以為綁定憑證設定到期時間,期限過後就不再綁定憑證。這有助於防止尚未更新的應用程式發生連線問題。不過,如果為綁定憑證設定到期時間,攻擊者就有可能略過已綁定的憑證。
以下節錄說明如何在 res/xml/network_security_config.xml
中綁定憑證:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin> <!-- backup pin --> <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin> </pin-set> </domain-config> </network-security-config>
設定繼承行為
系統會繼承未在特定設定中指定的值。這項行為可允許更複雜的設定,同時保持設定檔易於讀取。
例如,未在 domain-config
中設定的值會從父項 domain-config
(如果是巢狀結構) 擷取;如果不是巢狀結構,則從 base-config
擷取。未在 base-config
中設定的值會使用平台預設值。
舉例來說,假設所有連至 example.com
的子網域連線都必須使用自訂 CA 組合。此外,系統允許傳送至這些網域的明文流量,但連線至 secure.example.com
「除外」。如果在 example.com
的設定中為 secure.example.com
的設定建立巢狀結構,就不必複製 trust-anchors
。
以下節錄顯示此巢狀結構在 res/xml/network_security_config.xml
中呈現的內容:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </domain-config> </network-security-config>
設定檔格式
「網路安全性設定」功能採用 XML 檔案格式。檔案的整體結構如以下程式碼範例所示:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </base-config> <domain-config> <domain>android.com</domain> ... <trust-anchors> <certificates src="..."/> ... </trust-anchors> <pin-set> <pin digest="...">...</pin> ... </pin-set> </domain-config> ... <debug-overrides> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </debug-overrides> </network-security-config>
以下各節說明檔案格式的語法和其他詳細資料。
<network-security-config>
- 可包含:
-
0 或 1 個
<base-config>
任意數量的<domain-config>
0 或 1 個<debug-overrides>
<base-config>
- 語法:
<base-config cleartextTrafficPermitted=["true" | "false"]> ... </base-config>
- 可包含:
-
<trust-anchors>
- 說明:
-
如果連線的目的地不在
domain-config
涵蓋範圍內,則連線會採用預設設定。未設定的值都會採用平台預設值。
若應用程式指定 Android 9 (API 級別 28) 以上版本,其預設設定如下:
<base-config cleartextTrafficPermitted="false"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
若應用程式指定 Android 7.0 (API 級別 24) 至 Android 8.1 (API 級別 27) 版本,其預設設定如下:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
若應用程式指定 Android 6.0 (API 級別 23) 以下版本,其預設設定如下:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </base-config>
<domain-config>
- 語法:
-
<domain-config cleartextTrafficPermitted=["true" | "false"]> ... </domain-config>
- 可包含:
-
1 或多個
<domain>
0 或 1 個<trust-anchors>
0 或 1 個<pin-set>
任意數量的巢狀<domain-config>
- 說明:
- 根據
domain
元素的定義,用於連線至特定目的地的設定。請注意,如果多個
domain-config
元素涵蓋某個目的地,則會使用相符網域規則最明確 (最長) 的設定。
<domain>
- 語法:
-
<domain includeSubdomains=["true" | "false"]>example.com</domain>
- 屬性:
-
-
includeSubdomains
- 如果設為
"true"
,這項網域規則須與網域和所有子網域 (包括子網域的子網域) 相符。否則,只有完全相符的網域會套用此規則。
-
<debug-overrides>
- 語法:
-
<debug-overrides> ... </debug-overrides>
- 可包含:
-
0 或 1 個
<trust-anchors>
- 說明:
-
當 android:debuggable 為
"true"
時要套用的覆寫設定,IDE 和建構工具產生的非發布子版本通常屬於這種情況。在debug-overrides
中指定的信任錨點會新增至所有其他設定,當伺服器的憑證鏈結使用其中一個僅供偵錯的信任錨點時,系統不會執行憑證綁定作業。如果 android:debuggable 是"false"
,則系統會完全忽略此部分。
<trust-anchors>
- 語法:
-
<trust-anchors> ... </trust-anchors>
- 可包含:
-
任意數量的
<certificates>
- 說明:
- 安全連線的信任錨點集合。
<certificates>
- 語法:
<certificates src=["system" | "user" | "raw resource"] overridePins=["true" | "false"] />
- 說明:
trust-anchors
元素的 X.509 憑證集合。- 屬性:
-
src
-
CA 憑證的來源。可以是下列其中一種:
- 原始資源 ID,指向包含 X.509 憑證的檔案。憑證必須以 DER 或 PEM 格式編碼。如果是 PEM 憑證,則檔案「不得」包含其他非 PEM 格式的資料。
"system"
,此為預先安裝系統的 CA 憑證來源"user"
,此為使用者新增的 CA 憑證來源
overridePins
-
指出此來源的 CA 是否要略過憑證綁定功能。如果設為
"true"
,則系統不會在由此來源的其中一個 CA 簽署的憑證鏈結上,執行綁定作業。不管是要偵錯 CA,或是測試應用程式安全流量是否遭到中間人攻擊,這項做法都很實用。預設值為
"false"
,但如果是在debug-overrides
元素中指定,則預設值為"true"
。
<pin-set>
- 語法:
-
<pin-set expiration="date"> ... </pin-set>
- 可包含:
-
任意數量的
<pin>
- 說明:
-
一組公開金鑰綁定憑證。如要讓系統信任安全連線,該信任鏈結中的其中一個公開金鑰必須位於綁定憑證組合中。請參閱
<pin>
,瞭解綁定憑證的格式。 - 屬性:
-
-
expiration
-
綁定憑證的到期日,格式為
yyyy-MM-dd
,在該日期過後憑證將失效,系統也會停止綁定該憑證。如未設定這項屬性,綁定憑證就不會過期。設定到期日可防止應用程式因未收到綁定憑證的更新內容 (例如使用者停止更新應用程式),導致發生連線問題。
-
<pin>
- 語法:
-
<pin digest=["SHA-256"]>base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)</pin>
- 屬性:
-
-
digest
-
用於產生綁定憑證的摘要演算法。目前僅支援
"SHA-256"
。
-
其他資源
如要進一步瞭解網路安全性設定,請參閱以下資源。