From 87613775159568cbe872770c3bbe78e496e101db Mon Sep 17 00:00:00 2001
From: Joe Fernandez The Android Network Security Config lets apps customize their network security settings
-in a safe, declarative configuration file without modifying application code.
-These settings can be configured for specific domains and app-wide. An application may want to trust a custom set of CAs instead of the platform
-default. The most common reasons of this are:
-In this document
-
-Features
-
-
-
-Examples
-Trusting Custom CAs
-
-
-
By default secure (e.g. TLS, HTTPS) connections from all applications trust the pre-installed system CAs, and -applications targeting API level 23 (Android M) and below also trust the user-added CA store by default. -An application can customize its own connections using {@code base-config} (for app-wide customization) or -{@code domain-config} (for per-domain customization).
- -Assume you want to connect to your host which uses a self-signed SSL certificate or to -a host whose SSL certificate is issued by a non-public CA which you trust, e.g., your company's internal -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> - <trust-anchors> - <certificates src="@raw/my_ca"/> - </trust-anchors> - </domain-config> -</network-security-config> -- -
Add the self-signed or non-public CA certificate, in PEM or DER format, to {@code res/raw/my_ca}.
-
-In AndroidManifest.xml reference the above config
-
-<?xml version="1.0" encoding="utf-8"?> -... -<application ...> - <meta-data android:name="android.security.net.config" - android:resource="@xml/network_security_config" /> - ... -- -
An application that does not want to trust all CAs trusted by system can instead specify its own -reduced set of CAs to trust. This protects the application from fradulent certificates issued by any -of the other CAs.
- -The config to limit the set of trusted CAs is similar to trusting a custom CA -for a specific domain except that multiple CAs are provided in the resource.
- -
-res/xml/network_security_config.xml:
-
-<?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> -- -
Add the trusted CAs, in PEM or DER format, to {@code res/raw/trusted_roots}.
-Note that if using PEM format the file must contain only PEM data and no extra text.
-You can also provide multiple <certificates> elements instead
-of one.
-In AndroidManifest.xml reference the above config
-
-<?xml version="1.0" encoding="utf-8"?> -... -<application ...> - <meta-data android:name="android.security.net.config" - android:resource="@xml/network_security_config" /> - ... -- - -
An application may want to trust additional CAs not trusted by the system, this could be due to -the system not yet including the CA or a CA that does not meet the requirements for inclusion into -the Android system. An application can do this by specifying multiple certificate sources for a configuration. -
-
-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> -- -
-In AndroidManifest.xml reference the above config
-
-<?xml version="1.0" encoding="utf-8"?> -... -<application ...> - <meta-data android:name="android.security.net.config" - android:resource="@xml/network_security_config" /> - ... -- - -
When debugging an application that connects over HTTPS you may want to connect to a local development -server, which does not have the SSL certificate for your production server. In order to support this -without any modification to your application's code you can specify debug-only CAs that are -only trusted when android:debuggable -is {@code true} by using {@code debug-overrides}. Normally IDEs and build tools set this flag automatically for non-release builds.
-This is safer than the usual conditional code because, as a security precaution, application stores -do not accept applications which are marked debuggable.
- -
-res/xml/network_security_config.xml:
-
-<?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> -- -
-In AndroidManifest.xml reference the above config
-
-<?xml version="1.0" encoding="utf-8"?> -... -<application ...> - <meta-data android:name="android.security.net.config" - android:resource="@xml/network_security_config" /> - ... -- - -
Applications which intend to connect to destinations using only secure connections can opt-out -of supporting cleartext (i.e. plain HTTP instead of HTTPS) to those destinations. This helps prevent -accidental regressions in applications due to changes in URLs provided by external sources such as -backend servers.
-See {a href="{@docRoot}reference/android/security/NetworkSecurityPolicy.html#isCleartextTrafficPermitted()} for more details.
- -For example, an application may want to ensure that all connections to {@code secure.example.com} are always -done over HTTPS to protect sensitive traffic from hostile networks.
- -
-res/xml/network_security_config.xml:
-
-<?xml version="1.0" encoding="utf-8"?> -<network-security-config> - <domain-config usesCleartextTraffic="false"> - <domain includeSubdomains="true">secure.example.com</domain> - </domain-config> -</network-security-config> -- -
-In AndroidManifest.xml reference the above config
-
-<?xml version="1.0" encoding="utf-8"?> -... -<application ...> - <meta-data android:name="android.security.net.config" - android:resource="@xml/network_security_config" /> - ... -- - -
Normally an application trusts all preinstalled CAs. If any of these CAs were to issue a fradulent certificate -the application would be at risk from a MiTM attack. Some applications choose to limit the set of -certificates they accept by either limiting the set of CAs they trust or by certificate pinning.
- -Certificate pinning is done by providing a set of certificates by hash of the public key (SubjectPublicKeyInfo -of the X.509 certificate). A certificate chain is then only valid if the certificate chain contains at least -one of the pinned public keys.
- -Note that when using certificate pinning you should always include a backup key so that if you -are forced to switch to new keys, or change CAs (when pinning to a CA certificate or an intermediate of that CA), -your application's connectivity is unaffected. Otherwise you will have to push out an update to the -application to restore connectivity.
- -Additionally it is possible to set an expiration time for pins after which pinning will not be -performed. This helps prevent connectivity issues in applications which have not been updated. -However, setting an expiration time on pins may enable pinning bypass. -
- -
-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> - </domain-config> -</network-security-config> -- -
-In AndroidManifest.xml reference the above config
-
-<?xml version="1.0" encoding="utf-8"?> -... -<application ...> - <meta-data android:name="android.security.net.config" - android:resource="@xml/network_security_config" /> - ... -- - -
Values not set in a specific config will be inherited. -This allows more complex configurations while keeping the configuration file readable.
- -If a value is not set in a specific entry then value from the next more general entry will be used. -Values not set in a {@code domain-config} will be taken from the parent {@code domain-config}, if nested, or -from the {@code base-config} if not. Values not set in the {@code base-config} will use -the platform default values. - -
For example consider, where all connections to subdomains of {@code example.com} -must use a custom set of CAs. Additonally cleartext traffic to these domains is permitted -except when connecting to {@code secure.example.com}. By nesting the configuration -for {@code secure.example.com} inside the configuration for {@code example.com} the -{@code trust-anchors} does not need to be duplicated.
- -
-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> -- -
-In AndroidManifest.xml reference the above config
-
-<?xml version="1.0" encoding="utf-8"?> -... -<application ...> - <meta-data android:name="android.security.net.config" - android:resource="@xml/network_security_config" /> - ... -- - -
The configuration file is XML. Here is what it can contain:
- --<?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> -- -
<base-config>
-<domain-config>
-<debug-overrides>
-<base-config usesCleartextTraffic=["true" | "false"]> - ... -</base-config>
<trust-anchors>domain-config.
-
-Any values that are not set will use the platform default values. -The default configuration for applications targeting above API level 24 and above: -
-<base-config usesCleartextTraffic="true"> - <trust-anchors> - <certificates src="system" /> - </trust-anchors> -</base-config> --The default configuration for applications targeting API level 23 and below is: -
-<base-config usesCleartextTraffic="true"> - <trust-anchors> - <certificates src="system" /> - <certificates src="user" /> - </trust-anchors> -</base-config> -- -
<domain-config usesCleartextTraffic=["true" | "false"]> - ... -</domain-config>
<domain>
-<trust-anchors>
-<pin-set>
-<domain-config>Note that if multiple {@code domain-config} elements cover a destination the config with the most specific (longest) -matching domain rule will be used.
<domain includeSubdomains=["true" | "false"]>example.com</domain>
<debug-overrides> - ... -</debug-overrides>
<trust-anchors><trust-anchors> -... -</trust-anchors> -
<certificates><certificates src=["system" | "user" | "raw resource"] - overridePins=["true" | "false"] /> -
-Default is {@code "false"} unless specified in a {@code debug-overrides} element, in which case the default is {@code "true"}. -
-<pin-set expiration="date"> -... -</pin-set> -
<pin><pin> for the format of pins.Expiration helps prevent connectivity issues in applications which do not get updates to their -pin set, for example because the user disabled application updates.
-<pin digest=["SHA-256"]>base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)</pin>