Mobile Software Development Security Requirements for Google Partners

Summary

Requirements

  1. Follow best practices guidelines published by mobile platform developers.
  2. Do not publish apps on behalf of Google. (Only Google should publish apps on behalf of Google.)
  3. Use built-in facilities for account management.
    1. Never ask for user passwords directly.
    2. Use OAuth2 for passing credentials.
  4. Securely communicate with backend services.
    1. 100% of network traffic should be encrypted with TLS.
    2. Certificates must be verified.
    3. Authenticate backend traffic with OAuth2 tokens.
    4. Use Cloud Endpoints if possible.
  5. Prevent Eavesdropping on Inter-Process Communication.
  6. Store data with limited privileges.
  7. Use compiler and SDK hardening options.

As with other software development outsourcing, there may be additional requirements around availability and ownership of the source code, as well as review of any third party access to data that the application stores, retrieves, or processes.

This document aims to describe the minimum security requirements for mobile applications built for Google by vendors. Since different applications have different requirements regarding the protection of confidentiality, integrity, and availability, the requirements described in this document should be seen in the context of the application they are applied to, and are to be used along with project-specific requirements. In some cases, stricter requirements may be necessary. In certain other cases, it may be desirable to waive some of the requirements in this document. Similarly, an existing application might not fulfill all requirements, and it may not be possible, or deemed necessary to backport them. In such a case, this decision should be documented along with the waived requirements.

Any exceptions to these policies must be approved by the Google security team in advance, and should be documented in a README.security file in the root of the source code repository.

Outside the scope of this document are security requirements around sharing data with vendors, as well as requirements for server-side web applications and APIs that may be developed to support or augment the mobile application. (The Web Application Requirements apply to these backend components.) You are encouraged to use Google Cloud Endpoints for your backend, as this includes the necessary authentication layer.

General Information

Currently, the two mobile platforms this document aims to cover are Android and Apple iOS. Both Google and Apple provide security relevant documentation on their respective developer sites. It is expected that third party vendors consult this documentation when making security sensitive decisions.

Deployment

The final application must be signed and pushed by a Google-owned and -controlled key, so a Google engineer must handle the signing of each application. The application must not be published by any account other than an official google.com account for publishing applications. The application should not be released by the vendor developing the application.

Authentication/Authorization

In many cases, applications and the data in the application should not be available to everybody. In order to identify authorized users, many applications ask the user to log in. The requirements in this section apply to all mobile applications (internal and external) that require users to authenticate.

Applications should rely on industry standard protocols such as OAuth2 for authenticating access to Google APIs or services. Additionally, the scopes included in requests for authentication tokens should be the minimum necessary for the application to function. The scopes requested by the application should be documented along with a brief description of why they are necessary as part of the application deliverable. For applications developed specifically for Google, this, and any other exceptions granted, should be documented in a README.security file in the root of the source code repository.

Android

Applications should rely on system facilities such as the AccountManager to obtain authentication tokens. Applications should never request credentials from the user directly. Applications should also never rely on the use of an Activity such as a WebView to present authentication or authorization dialogs.

Applications should never store authentication tokens, but instead use the AccountManager facilities to refresh authentication tokens as necessary.

iOS

Unfortunately, iOS does not provide a facility similar to Android’s AccountManager for Google accounts. If an iOS application requires authentication, it should use the Google developed and publicly available GTMAppAuth library to handle user authentication flows. A Googler will need to create the client ID and secret on https://console.developers.google.com/and provide the values to the vendor for use within the application.

Communicating with Cloud Services

For an attacker it is often extremely easy to listen in on the packets as they are transmitted between a user and the web application (for example when the user is on a public WiFi network). In order to avoid that sensitive data is read by an attacker while it is in transit, any application that contains anything but public data must be available solely over HTTPS.

However, even with encryption, there are certain ciphers and key lengths that are not deemed secure nowadays. For this reason, the web server must be configured to support TLS version 1.0 or newer, and must only accept secure ciphers with strong grade key lengths (>=112 bits).

To avoid someone impersonating your web server, it must identify itself with a valid certificate, that is signed by a trusted certification authority. The CA’s public key must be installed by default in the certificate store of the mobile platforms targeted.

A common mistake that plagues mobile applications involves failing to validate the remote server’s certificate, which can lead to man-in-the-middle attacks. Any code responsible for generating HTTPS requests in the application must ensure that server certificates are validated.

Use of low level libraries such as OpenSSL will require explicit checks to ensure that the connection can be trusted. Some guidance is available from iSEC Partners in their paper, “Everything You’ve Always Wanted to Know About Certificate Validation With OpenSSL.”

Any communication with external services must be documented as part of the application deliverables or documentation, and those services must conform to any applicable security requirements. All communications must be via TLS, and any exceptions must have a documented reason.

Authenticating to Backends

If your application connects to backends that provide APIs containing confidential data, PII, or any other information that is not public, access must be authenticated. Pass an OAuth2 token from the client to the backend, and validate the token upon receiving at the backend. Ensure that bearer tokens are validated in a manner that does not allow brute force attacks.

If the URLs your application requests can be controlled or influenced by third parties, be sure to perform suitable validation and ensure the URL is present in a list of acceptable endpoints and/or schemes. Many information disclosure or SSRF bugs are related to practices such as fetching an attacker provided-URL of the form "file://...”, etc. Generally, only the prefixes "http://" and "https://" should be accepted.

Android

In Android, both HttpURLConnection (preferred) and DefaultHttpClient (legacy) perform sufficient validation by default. If the default javax.net.ssl packages are used instead, the application will need to specifically validate the CN or SAN fields in the certificate. Expiry date and whether the certificate was issued by a trusted certificate authority are verified automatically.

iOS

Core iOS libraries such as CFNetwork and NSURLRequest will perform certificate validation by default, as will popular third party libraries that wrap these (e.g. AFNetworking). Be sure to configure any sockets to use strong protocols such as TLSv1 (SSLv3 and below has known weaknesses). If you subclass these for your application, you must ensure that your implementation either performs or delegates validation.

Interprocess Communication

Android

IPC is often performed by sending Intents between Android components such as an Activity, Service, ContentProvider, and BroadcastReceiver. Specific guidance for each type of Android component is below. Although the guidance is biased toward definitions in AndroidManifest.xml, the same security properties can (and should) always be configured programmatically as well. Avoid using Unix-style RPC mechanisms like sockets, files, and pipes, as they are easy to misuse and lack security controls by default.

Several of the recommendations below suggest creating custom permissions. Where possible, these custom permissions should be defined using a “signature” protection level. Note that this may require additional coordination pertaining to what certificates are used to sign the application, and this should be discussed with the Google engineer supporting your deployment.

  1. Activities and Services
    1. Only specify <intent-filter> tags for activities and services which are meant to be invoked by third party applications. If the Activity or Service should not be invoked by external applications, but you do specify an intent-filter, be sure to set the "android:exported" attribute to false. This attribute can be applied to both <activity> and <service> elements.
    2. If the activity or service needs to be exposed to other applications and performs some sensitive action, the manifest should protect these by declaring and requiring a custom permission. Note that this is somewhat coarse-grained - any app with the specified permission can invoke the service or activity. For finer grained checking (i.e. per-method permissions), use checkCallingPermission() or a related method.
  2. ContentProvider
    1. Distinct read and write permission values must be specified (i.e. the declaration should use android:readPermission and android:writePermission, not android:permission). The default behavior of a ContentProvider is to allow access to any application if these values are not specified.
    2. If the ContentProvider does not need to be exposed to other applications, be sure to set the “android:exported” attribute to false. False is the default behavior for applications targeting SDK version 17 or higher, but the default for prior versions of Android is true.
    3. Care should be taken while designing the URI scheme to enable fine-grained access control if other applications need temporary access to some of the content.
  3. BroadcastReceiver
    1. Only specify <intent-filter> tags if the BroadcastReceiver is meant to be invoked by third party applications. If the BroadcastReceiver should not be invoked by external applications, but you do specify an intent-filter, be sure to set the android:exported attribute to false.
    2. You should declare an android:permission which other applications need to request in order to send broadcasts to your application.
    3. Similarly, if your application emits broadcast intents, you should specify a receiver permission on every broadcast to ensure that other applications can not eavesdrop on this content.

iOS

iOS does not support many traditional IPC mechanisms. As a workaround, many applications implement a limited form of IPC by registering custom protocol handlers (“Communicating with Other Apps”) in the Info.plist file. These custom protocol handlers should not be used to pass any sensitive data - another application may “squat” on the protocol handler, and collect sensitive information passed via this channel. Additionally, there is no mechanism to strongly authenticate any client connection.

The functionality of any custom protocol handlers included in an iOS application should be documented as part of the application deliverables.

Storing Data

In general, storing sensitive data on mobile devices is discouraged. However, in some cases, it may be necessary to store such data on the device. Different mechanisms are available on Android and iOS to protect on-device data are discussed below.

Any sensitive data which is to be stored on the device should be documented as part of the application deliverables. This documentation should include details around where the data is stored and how it is protected. Applications should additionally take steps to avoid logging sensitive information to system logging facilities.

Related to sensitive user data, please note that sensitive information such as cryptographic keys or API secrets, etc. should never be hard coded into an application, as they can be discovered via reverse engineering / decompilation of the application.

Android

Android offers a variety of storage options. In general, only the use of shared external storage should be avoided, as files stored there are readable by other applications. The other storage mechanisms are protected by Android's security model, and the application should select the appropriate storage mechanism (cache, database, etc.) as needed. Note that for internal storage, applications should make use of openFileOutput() with the MODE_PRIVATE argument. SharedPreferences should be used for storing small amounts of data (such as settings, API keys, etc.)

iOS

iOS provides the Keychain and data protection APIs to assist in securing sensitive data that is stored on the device. For Keychain items, prefer attributes such as kSecAttrAccessibleWhenUnlocked. When using the Data Protection APIs to protect files, prefer protection classes such as NSDataWritingFileProtectionCompleteUnlessOpen or NSFileProtectionCompleteUnlessOpen and be cognizant of when your application keeps files open.

Secure Development

There are a host of secure coding patterns that should be followed in order to avoid issues such as SQL injection, format string flaws, race conditions, integer overflow or underflow, buffer overflows, etc. While discussing how to avoid all these issues is outside the scope of this document, guides written by both Apple and Google give a reasonable overview of many common flaws and suggestions for how to avoid them - applicable to both native and interpreted code. Vendors are expected to follow the guidance provided by these documents.

On Android, refrain from using NDK and implement all functionality in Java for the Dalvik VM. Do not load classes dynamically, favoring builds with all classes loaded by the built-in loaders.

WebView should be avoided for any Android application with API version less than 19. Older versions of WebView are vulnerable to many issues, including code execution via the JavaScript engine. Either target newer platforms, or use an Intent to display content in the built-in browser.

Applications relying on native code should additionally opt-in to any available compiler protections. iOS/LLVM also support protection methods such as stack canaries and automatic reference counting which help mitigate memory corruption vulnerabilities.

Further Reading