Storing Data Securely with Android
Android has quite a number of security features that are built into the operating system that significantly reduce the frequency and impact of security issues. The system is designed so that when you build your apps with default system and file permissions, you can avoid having to make difficult decisions about security.
Some of the core security features that can help you build secure apps include:
- The Android Application Sandbox that isolates all of your app data and code execution
- An application framework that has robust implementations of common security functionality, including cryptography, permissions, as well as secure IPC
- Technologies including ASLR; NX; ProPolice; safe_iop; OpenBSD dlmalloc; OpenBSD calloc; and Linux mmap_min_addr that can be used to mitigate risks that are associated with common errors in memory management
- An encrypted files system that is used to protect data on lost or stolen devices
- User-granted permissions that restrict access to system features and user data
- Application-defined permissions that control application data on a per-app basis
It’s important for you to be familiar with the Android security best practices. By making these practices your general coding habits, you will reduce the chance of inadvertently introducing many security issues that could adversely affect your users.
The most common security concern for an Android application is whether the data that you save on the device is readily accessible to other apps. There are three fundamental ways you can save data on the device:
Using internal storage
Files that you create on internal storage are, by default, accessible only to your app. This protection is automatically implemented by Android and should be sufficient for most applications.
You should generally not use the MODE_WORLD_WRITEABLE or the MODE_WORLD_READABLE mode for IPC files. This is because they do not provide you with the ability to limit data access to all applications, nor do they provide any control for you on data format. If you would like to share your data with other app processes, you can instead consider using a content provider. Content provider offers read and write permissions to other apps and then can make dynamic permission grants on a case-by-case basis.
For you to provide additional protection for sensitive data, you can choose to encrypt local files using a key that’s not directly accessible to the application. For instance, a key can be placed in a KeyStore and then protected with a user password not stored on the device. However, this does not protect data from a root compromise that might monitor the user inputting the password. It can, though, provide protection for a lost device without file system encryption.
Using external storage
Files that are created on an external storage device, such as SD Cards, are globally readable and writable. Because you can remove external storage and it can also be modified by any application, you should not try storing sensitive information using external storage.
Concerning data from any untrusted source, always perform input validation when handling data from an external storage device. It is strongly recommended that you not store executables or any class files on external storage before dynamic loading. If your app retrieves executable files from external storage, make sure the files are signed and cryptographically verified before to dynamic loading.
Using content providers
Content providers usually offer a structured storage mechanism limited to your own application, or exported so they can be accessed by other applications. If you don’t intend to provide other applications with access to your ContentProvider, be sure to mark them as android:exported=false in the actual application manifest. Otherwise, you need to set the android:exported attribute “true” so it will allow other apps to access the stored data.
When creating a ContentProvider that you intend to export for use by other applications, you can specify a single permission for reading and writing, or set distinct permissions for reading and writing within the manifest. It is recommended that you limit your permissions to those that are required to accomplish the task at hand. Keep in mind, though, that it’s usually easier to add permissions later to be able to expose new functionality than it will be to take them away and break existing users.
If you’re using a content provider to share data between only your own apps, it’s preferable for you to use the android:protectionLevel attribute and set it to “signature” protection. Signature permissions don’t require user confirmation, so they provide you with a better user experience plus more controlled access to the content provider data when the apps are all accessing the data and are signed with the same key.
Content providers can also provide some additional granular access by declaring the android:grantUriPermissions attribute and by using the FLAG_GRANT_READ_URI_PERMISSION and the FLAG_GRANT_WRITE_URI_PERMISSION flags in the actual Intent object that activates the component. The scope of these permissions can also be further limited by using the .
When accessing a content provider, be sure to use parameterized query methods such as query() or update(), or delete() in order to avoid potential SQL injection from any untrusted source. Note that if you use parameterized methods, they are not sufficient if the selection argument is built by concatenating the user data before submitting it to the method.
Don’t have a false sense of security about the write permission. You should consider that the write permission allows SQL statements that make it possible for some data to be confirmed using creative WHERE clauses, and by parsing the results. An attacker, for example, might probe for presence of a specific phone number in a call-log by simply modifying a row only if that phone number already exists. If in fact the content provider data has predictable structure, then the write permission may be equivalent to providing both reading and writing.
With the above points covered, you can build your apps with default system and file permissions to reduce security issues. The key is to put these practices in place so you can avoid difficult decisions in the future about security.