Protecting users with TLS by default in Android P
[Cross-posted from the Android Developers Blog]
Android is committed to keeping users, their devices, and their data safe. One of the ways that we keep data safe is by protecting all data that enters or leaves an Android device with Transport Layer Security (TLS) in transit. As we announced in our Android P developer preview, we’re further improving these protections by preventing apps that target Android P from allowing unencrypted connections by default.
This follows a variety of changes we’ve made over the years to better protect Android users. To prevent accidental unencrypted connections, we introduced the android:usesCleartextTraffic manifest attribute in Android Marshmallow. In Android Nougat, we extended that attribute by creating the Network Security Config feature, which allows apps to indicate that they do not intend to send network traffic without encryption. In Android Nougat and Oreo, we still allowed cleartext connections.
How do I update my app?
If your app uses TLS for all connections then you have nothing to do. If not, update your app to use TLS to encrypt all connections. If you still need to make cleartext connections, keep reading for some best practices.
Why should I use TLS?
Android considers all networks potentially hostile and so encrypting traffic should be used at all times, for all connections. Mobile devices are especially at risk because they regularly connect to many different networks, such as the Wi-Fi at a coffee shop.
All traffic should be encrypted, regardless of content, as any unencrypted connections can be used to inject content, increase attack surface for potentially vulnerable client code, or track the user. For more information, see our past blog post and Developer Summit talk.
Isn’t TLS slow?
No, it’s not.
How do I use TLS in my app?
Once your server supports TLS, simply change the URLs in your app and server responses from http:// to https://. Your HTTP stack handles the TLS handshake without any more work.
If you are making sockets yourself, use an SSLSocketFactory instead of a SocketFactory. Take extra care to use the socket correctly as SSLSocket doesn’t perform hostname verification. Your app needs to do its own hostname verification, preferably by calling getDefaultHostnameVerifier() with the expected hostname. Further, beware that HostnameVerifier.verify() doesn’t throw an exception on error but instead returns a boolean result that you must explicitly check.
I need to use cleartext traffic to
While you should use TLS for all connections, it’s possibly that you need to use cleartext traffic for legacy reasons, such as connecting to some servers. To do this, change your app’s network security config to allow those connections.
We’ve included a couple example configurations. See the network security config documentation for a bit more help.
Allow cleartext connections to a specific domain
If you need to allow connections to a specific domain or set of domains, you can use the following config as a guide:
Allow connections to arbitrary insecure domains
If your app supports opening arbitrary content from URLs over insecure connections, you should disable cleartext connections to your own services while supporting cleartext connections to arbitrary hosts. Keep in mind that you should be cautious about the data received over insecure connections as it could have been tampered with in transit.
<base-config cleartextTrafficPermitted="true" />
How do I update my library?
If your library directly creates secure/insecure connections, make sure that it honors the app’s cleartext settings by checking isCleartextTrafficPermitted before opening any cleartext connection.