Mobile Software Development Security Requirements for Google Partners
Summary
Requirements
- Follow best practices guidelines published by mobile platform developers.
- Do not publish apps on behalf of Google. (Only Google should publish apps on behalf of Google.)
- Use built-in facilities for account management.
- Never ask for user passwords directly.
- Use OAuth2 for passing credentials.
- Securely communicate with backend services.
- 100% of network traffic should be encrypted with TLS.
- Certificates must be verified.
- Authenticate backend traffic with OAuth2 tokens.
- Use Cloud Endpoints if possible.
- Prevent Eavesdropping on Inter-Process Communication.
- Store data with limited privileges.
- 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.
- Activities and Services
- 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. - 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. - ContentProvider
- Distinct read and write permission values must be specified (i.e. the
declaration should use
android:readPermission
andandroid:writePermission
, notandroid:permission
). The default behavior of a ContentProvider is to allow access to any application if these values are not specified. - 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.
- 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.
- BroadcastReceiver
- 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. - You should declare an
android:permission
which other applications need to request in order to send broadcasts to your application. - 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
- Best Practices for Security & Privacy
- Android Security Tips
- Security and Privacy in Android Apps
- Application Security for the Android Platform (O'Reilly book)
- OWASP Mobile Security Project
- iOS Application (In)Security (by MDSec Consulting)
- Hacking and Securing iOS Applications (O'Reilly book)
- Japan Smartphone Security Association Android Guidelines