From f1bfa2537cfc0f732114e2755e645ca22ea50e85 Mon Sep 17 00:00:00 2001
From: Joe Fernandez
+ The Android N Developer Preview includes a Network Security Configuration
+ feature that lets apps customize their network security settings in a safe,
+ declarative configuration file without modifying app code. These settings can
+ be configured for specific domains and for a specific app. The key
+ capabilities of this feature are as follows:
+
+ The Network Security Configuration feature uses an XML file where you specify
+ the settings for your app. You must include an entry in the manifest of your
+ app to point to this file. The following code excerpt from a manifest
+ demonstrates how to create this entry:
+
+ An app may want to trust a custom set of CAs instead of the platform
+ default. The most common reasons of this are:
+
+ By default secure (e.g. TLS, HTTPS) connections from all apps trust
+ the pre-installed system CAs, and apps targeting API level 23
+ (Android M) and below also trust the user-added CA store by default. An
+ app 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, such as your company's internal CA.
+
+ In this document
+
+
+
+
+
+Adding a Security Configuration File
+
+
+<?xml version="1.0" encoding="utf-8"?>
+...
+<app ...>
+ <meta-data android:name="android.security.net.config"
+ android:resource="@xml/network_security_config" />
+ ...
+</app>
+
+
+Customizing Trusted CAs
+
+
+
+
+Configuring a Custom 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}. +
+ + ++ An app 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 + app 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.
+
+ An app 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 + app 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> ++ + + +
+ When debugging an app 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 app'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, app stores do not accept apps 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> ++ + + +
+ Applications intending to connect to destinations using only secure + connections can opt-out of supporting cleartext (using unencrypted HTTP + protocol instead of HTTPS) to those destinations. This option helps prevent + accidental regressions in apps due to changes in URLs provided by external + sources such as backend servers. +
+ ++ See the reference documentation for \ + {@code android.security.NetworkSecurityPolicy} class + {@code isCleartextTrafficPermitted()} method for more details. +
+ ++ For example, an app 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> ++ + + +
+ Normally an app trusts all preinstalled CAs. If any of these CAs were + to issue a fradulent certificate the app would be at risk from a MiTM + attack. Some apps 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 + app's connectivity is unaffected. Otherwise you must to push out + an update to the app to restore connectivity. +
+ ++ Additionally it is possible to set an expiration time for pins after which + pinning is not performed. This helps prevent connectivity issues in + apps 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> ++ + + +
+ Values not set in a specific config are inherited. This behavior 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 is used. Values not set in a {@code domain-config} is + 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} uses 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> ++ + + +
+ The Network Security Configuration feature uses an XML file format. + The overall structure of the file is shown in the following code sample: +
+ ++<?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> ++ +
+ The following sections describe the syntax and other details of the file + format. +
+ +<base-config><domain-config><debug-overrides>
+ +<base-config usesCleartextTraffic=["true" | "false"]> + ... +</base-config> ++
<trust-anchors>
+ domain-config.
+
++ Any values that are not set use the platform default values. The default + configuration for apps targeting above API level 24 and above: +
+ ++<base-config usesCleartextTraffic="true"> + <trust-anchors> + <certificates src="system" /> + </trust-anchors> +</base-config> ++The default configuration for apps 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 is 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"] /> +
+ Specifies if the CAs from this source bypass certificate pinning. If {@code + "true"} then certificate chains which chain through one of the CAs from this + source then pinning is not be performed. This can be useful for debug CAs + or to support letting the user MiTM your app's secure traffic. +
+ ++ 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 apps which do + not get updates to their pin set, for example because the user + disabled app updates. +
++<pin digest=["SHA-256"]>base64 encoded digest of X.509 + SubjectPublicKeyInfo (SPKI)</pin> ++