A week ago, during WWDC, Apple announced App Transport Security (ATS) for iOS 9. This feature will allow app developers to specify which domains their app needs to communicate with over HTTPS. In principle, for those domains, cleartext traffic will be automatically blocked by the system.
What about Android?
Google has not yet announced it officially, but the next Android version (codenamed Android M) has a “similar” feature. The code that includes this has actually been around for a while before Apple’s WWDC conference, but no-one seems to have picked it up.
Starting with Android M, apps are able to make use of a new manifest flag:
<application android:usesCleartextTraffic=["true" | "false"]>
If not declared, the default value is TRUE. All apps behave as before: there are no default restrictions in using HTTP.
This manifest flag is used to set a new
Then, when the app starts, the following code is run on the
ActivityThread class, setting a
NetworkSecurityPolicy for the application.
NetworkSecurityPolicy.getInstance().setCleartextTrafficPermitted((data.appInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0);
android.security.NetworkSecurityPolicy is a new class used to set the “network policy” of the application. This policy system seems very similar to Apple’s App Transport Security but it currently holds just this one boolean flag (
However, it does have some extra functionality when used in relation to
StrictMode, which has been extended. There are now policies like NETWORK_POLICY_ACCEPT, NETWORK_POLICY_LOG and NETWORK_POLICY_REJECT.
I can’t describe how this works better than the commit message itself:
Add app-level usesCleartextTraffic manifest attribute. The attribute declares whether the app intends to use cleartext network traffic (e.g., HTTP, WebSockets, XMPP, SMTP, IMAP -- without TLS or STARTTLS). The default value is true. If set to false, the app declares that it does not intend to use cleartext network traffic. In this case the app requests the platform, tooling, and third-party libraries to prevent it from using cleartext traffic. The danger of cleartext network traffic is that its confidentiality, authenticity, and integrity are not guaranteed. This feature is designed to help apps which care about security of data exchanged over the network. These apps can accidentally regress/downgrade to using cleartext network communications. This typically happens when the server the app communicates with all of a sudden tells it to use cleartext communications (e.g, HTTP URL instead of an HTTPS URL) or when one of the components of the app gets updated and regresses to cleartext communications without the developer noticing. In general, the prevention measures are on best effort basis. It's impossible to automatically prevent all instances of cleartext traffic. For example, an app bent on bypassing restrictions could perform low-level network I/O with unusual TCP packet fragmentation, or could use a custom application-level protocol. The expectation is that most apps use libraries for network communications and these libraries over time will start to honour this flag, thus increasing the protections offered by it.
#####Caveats As Google’s documentation & commit messages mention in many places, this is, for now, a best-effort system. This means that a developer may declare that it doesn’t want any cleartext traffic, but only certain system components will honour this.
The following components have been updated so that they honour the network security policy set for the application:
- DownloadManager, while downloading things on behalf of an app
- Apache’s HTTPclient (even though it’s being deprecated)
- OkHttp URLStreamHandler
The documentation mentions that WebViews and HttpURLConnection also honour the flag, but I can’t seem to find evidence yet.
#####Thoughts As expected, this is a very recent addition to the code and is still a bit immature. I believe it is a step in the right direction for Android; to be honest I wasn’t expecting something like this to be implemented. I think it will get more mature in future Android versions. I believe that developers will eventuall be able to implement nice things like domain restrictions, whitelisting, requirements for certain certificates (pinning) per domain etc through the new NetworkSecurityPolicy class. As it stands however, this has the potential to create quite a few issues for developers. If a developer decides to enable it, presumably all cleartext traffic will be blocked. This will include traffic from advertisement libraries until (if) they are updated to HTTPS. Apple’s ATS system is more granular: It can allows developers to declare that comms for specific hosts need to be secure by default. This way, an app can be certain that comms with certain backends are secure but still let possibly insecure ads go through.
There are more goodies, but they are part of
StrictMode, a developer tool which detects in an application during development. The following new framework APIs are interesting:
penaltyDeathOnCleartextNetwork() (cool name, I guess) or the
persist.sys.strictmode.nonssl property in
StrictMode that is supposed to crash an app completely if cleartext traffic is detected.
detectCleartextNetwork() is very interesting - it looks like it can help developers detect if they are sending out data in the clear.
detectCleartextNetwork() Detect any network traffic from the calling app which is not wrapped in SSL/TLS. This can help you detect places that your app is inadvertently sending cleartext data across the network. Using penaltyDeath() or penaltyDeathOnCleartextNetwork() will block further traffic on that socket to prevent accidental data leakage, in addition to crashing your process. Using penaltyDropBox() will log the raw contents of the packet that triggered the violation. This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it may be subject to false positives, such as when STARTTLS protocols or HTTP proxies are used.
######How does it work under the hood? After some quick browsing around the code, it looks like the StrictMode connection inspection feature works through the NetworkManagementService (netd). As stated in the commit message: > Detection is done by looking for a well-known TLS handshake header; it’s not future proof, but it’s a good start. Handles both IPv4 and IPv6
For those interested, the TLS handshake signatures can be found here.