You might already know that iPhone and Android, are the two most commonly used smartphone operating systems in the world. With their several benefits apart and common functionalities, comes great deal of security concerns. As internet is itself evolving day by day, and where there are advancements, there are new loop holes which can be exploited, smartphones have their own area of security issues to address upon. In this series of Android Security, we will look at what are the areas that need attention to take certain steps and what are the better approaches to tackle these issues.
The Android Ecosystem
The open source nature of Android allows companies and developers to distribute the different variants, versions and flavours of the operating system. This makes it hard to maintain standards across developers and OEMs to follow same rules. This creates a lot of space for troublemakers to exploit the system in various ways. Where, Android has its popularity among consumers and developers alike, it has its downsides too.
Listing down common loop holes:
Here is a list of most common loopholes an application can have:
- Root Access
- File System
- Backup Theft
- SSL Pinning
In this section we will discuss what vulnerabilities root access and persistent data can cause in your application.
Root Access, is when a device user has access to unlimited control over device. Its file system, OS (Roms), themes, systems apps etc. Normally, devices are locked by OEMs and Carriers depending on the features they want to cater to the consumers. This may cause device to perform below par when its on-board specifications allows it to do more. Custom Roms for more features and improved battery life is one of the most common reason to root. But it gives a serious headache to app developers if the app is using features like database or file storage.
Generally, app’s internal data directory cannot be accessed on devices (unless its debug version, which can be accessed from Android Studio/DDMS tools for testing purposes). This is the directory where the app’s critical information like database and preferences files are saved. Once rooted, these can be easily accessed via super user commands. This raises a concern about which kind of data is stored in the file system, and what can happen to the user, product or developers as a whole if this data is compromised. Issues related to how and what data should be saved is discussed in the next section.
Here, the concern is, what should you do if your app can be vulnerable if the user’s device is rooted. Since rooted device has “God” like access over everything that is in the device. It is impossible to dictate the control over your data, and the end user or even third party apps can do whatever they want to do, wherever they want to do in the system.
What you should do?
A simple approach would be to not allow the app services to work on the rooted device. This may sound annoying at first and it is explicitly denying the app usage, but it is for greater good. There is a library in Android called rootbeer which you can use to detect root. Although, this check cannot guarantee 100% that the device is rooted or not, it can give you extra layer of security.
When it comes to saving data for apps, shared preferences is the first choice of every developer. Its simplicity allows to use it without any extra effort since its storage mechanism is saving key value pairs. Under the hood, shared preferences file is just a text file in xml format, saved in applications data directory. This is easily accessible in debug mode, by navigating to the data/data/package using Device Explorer. Or if the build is production (release), this file can easily be accessed in rooted phone. Here is the link to official guide on using device explorer.
Starting from Android Studio 3.0, you can navigate to app’s directory without starting DDMS Tools. Using Device Explorer window, like shown below:
Simply navigate to the folder of your app by finding it with name of your package, and goto shared_prefs folder, double click it, it should open your preferences right away in plain text:
Now, this is quite handy way to see what is stored in shared preferences and specially, how it is stored. Most of the time the data is saved in plain text. By plain text we mean, the values of the data or variable are written as is in the preferences. This is really dangerous approach if you are saving some sensitive data.
At first, shared preferences should never be used to save sensitive information like authentication tokens, emails, hashes, database keys, API keys etc. If there is a must need for some business reason, it should be encrypted. There are libraries available to make encryption process easier, like this one or other. Otherwise, it is preferred you write your own implementation of encrypting data using Android Keystore.
- Do not save any sensitive information in any case in the application’s shared preferences.
- If needed, always save encrypted data in shared preferences.
Using local database also need some attention when it comes to security. This topic is focused on SQLite Database as it is the most commonly used database among the Android developer’s community. But if you are using other platforms like Realm, the bottom line is the same, database uses a file to save its content. The protection level of this file (or files) depends on the OS, database type, platform etc.
Now, if you do not already know, any database can be accessed from application directory if the device is rooted, or from Android Studio if the app is in debug mode. Simply navigate to data/data/package/databases directory from device explorer. In case the developer provided custom directory, you need to where that directory exists. And the most crucial component of your application is at stake now.
In Android Studio 3.+, you can find Device Explorer which looks like this:
You can navigate to data -> data-> package name -> databases, to find your database file.
You may be wondering if the attacker can read the data contents of your .db extension database file or not, he does not have to just download DB Browser for SQLite, and open the .db file with it. You can explore, query and even edit data using this tool.
If this was the banking app or any financial app, of which services are heavily relies on data, attacker can exploit these services once he has the hold of this critical information. To, prevent this, one way is to make the app cloud-first. Meaning minimum caching to cater the user with intended services.
SQLCipher is a library that is built upon SQLite Database to provide encryption feature on SQLite Database. It is simple to use, almost similar to SQLite. One main difference is we have to provide an encryption key while initiating database. This key will be used to encrypt decrypt data. Once a database is initialized with a key, it should always be accessed through it or otherwise it will result in error. This key can be changed with “PRAGMA” commands, but it needs old key to reset to new key.
This makes it almost impossible to spy on data, when extracted from the phone and accessed with the help of DB Browser tool. This solves the access problem but give rise to a new one: Where and How the key is generated and stored?
Most common answer would be the Shared Preferences, obviously. But revisiting the last topic, it raises concerns on its storage mechanism.
- What if you save this pass key, required by SQLCipher in code? It will be revealed on decompiling apk.
- What if you save this in preferences? It will be also reveal if it is not encrypted.
You will have to secure database using SQLCipher, which needs a pass key, and also devise a way to secure this pass key also, like encrypting it before saving it in the preferences. A good practice would be to generate a unique pass key at runtime using Android Keystore API, and save it in preferences in encrypted form. By doing this you are adding more secure layers and preventing a possible data leak to the attacker.
Something to take from above discussion:
- Use secure database or cloud-first data storage mechanism.
- While securing data with encryption key, pay attention to saving mechanism, like securing encryption key also.
- Take all related attack vectors when implementing a solution, so as to minimize resulting vulnerabilities.
In the next section, we will discuss another set of security area which includes application logs, screenshots and data theft. Feel free to point out corrections and things that might have been missed. Remember to leave some feedback about what you think can really raise a security issue while developing apps for Android!
Talha is a CS graduate from University of Karachi, currently working at VentureDive as Software Engineer. He appreciates the use of best practices to reap full benefits of the given platform. He likes to question the conventional methodologies and practices and prefers to look at the bigger picture.