Android M and the war on cleartext traffic

Developers can restrict cleartext traffic on Android M via the new 'usesCleartextTraffic' manifest flag.

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.

#####usesCleartextTraffic

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 ApplicationInfo setting: ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC.

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);

#####NetworkSecurityPolicy 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 (usesCleartextTraffic).

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:

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.

#####StrictMode goodies 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.

John Kozyrakis

mobile security, static & dynamic analysis, automation, payments

London, UK