Android Network Communication
Overview
Almost every Android app acts as a client to one or more remote services. As this network communication usually takes place over untrusted networks such as public Wi-Fi, classical network based-attacks become a potential issue.
Most modern mobile apps use variants of HTTP-based web services, as these protocols are well-documented and supported.
Android Network Security Configuration
Starting on Android 7.0 (API level 24), Android apps can customize their network security settings using the so-called Network Security Configuration feature which offers the following key capabilities:
- Cleartext traffic: Protect apps from accidental usage of cleartext traffic (or enables it).
- Custom trust anchors: Customize which Certificate Authorities (CAs) are trusted for an app’s secure connections. For example, trusting particular self-signed certificates or restricting the set of public CAs that the app trusts.
- Certificate pinning: Restrict an app’s secure connection to particular certificates.
- Debug-only overrides: Safely debug secure connections in an app without added risk to the installed base.
If an app defines a custom Network Security Configuration, you can obtain its location by searching for android:networkSecurityConfig
in the AndroidManifest.xml file.
<application android:networkSecurityConfig="@xml/network_security_config"
In this case the file is located at @xml
(equivalent to /res/xml) and has the name “network_security_config” (which might vary). You should be able to find it as “res/xml/network_security_config.xml”. If a configuration exists, the following event should be visible in the system logs:
D/NetworkSecurityConfig: Using Network Security Config from resource network_security_config
The Network Security Configuration is XML-based and can be used to configure app-wide and domain-specific settings:
base-config
applies to all connections that the app attempts to make.domain-config
overridesbase-config
for specific domains (it can contain multipledomain
entries).
For example, the following configuration uses the base-config
to prevent cleartext traffic for all domains. But it overrides that rule using a domain-config
, explicitly allowing cleartext traffic for localhost
.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain>localhost</domain>
</domain-config>
</network-security-config>
Learn more:
- “A Security Analyst’s Guide to Network Security Configuration in Android P”
- Android Developers - Network Security Configuration
- Android Codelab - Network Security Configuration
Default Configurations
The default configuration for apps targeting Android 9 (API level 28) and higher is as follows:
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
The default configuration for apps targeting Android 7.0 (API level 24) to Android 8.1 (API level 27) is as follows:
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
The default configuration for apps targeting Android 6.0 (API level 23) and lower is as follows:
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
Certificate Pinning
The Network Security Configuration can also be used to pin declarative certificates to specific domains. This is done by providing a <pin-set>
in the Network Security Configuration, which is a set of digests (hashes) of the public key (SubjectPublicKeyInfo
) of the corresponding X.509 certificate.
When attempting to establish a connection to a remote endpoint, the system will:
- Get and validate the incoming certificate.
- Extract the public key.
- Calculate a digest over the extracted public key.
- Compare the digest with the set of local pins.
If at least one of the pinned digests matches, the certificate chain will be considered valid and the connection will proceed.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
Use certificate pinning for OWASP website access including sub domains
<domain includeSubdomains="true">owasp.org</domain>
<pin-set expiration="2018/8/10">
<!-- Hash of the public key (SubjectPublicKeyInfo of the X.509 certificate) of
the Intermediate CA of the OWASP website server certificate -->
<pin digest="SHA-256">YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=</pin>
<!-- Hash of the public key (SubjectPublicKeyInfo of the X.509 certificate) of
the Root CA of the OWASP website server certificate -->
<pin digest="SHA-256">Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhIMN+eWys=</pin>
</pin-set>
</domain-config>
</network-security-config>
Security Provider
Android relies on a security provider to provide SSL/TLS-based connections. The problem with this kind of security provider (one example is OpenSSL), which comes with the device, is that it often has bugs and/or vulnerabilities.
To avoid known vulnerabilities, developers need to make sure that the application will install a proper security provider. Since July 11, 2016, Google has been rejecting Play Store application submissions (both new applications and updates) that use vulnerable versions of OpenSSL.