Exploiting Android local storage with Corellium
Storing data is essential to many mobile applications. What data is being stored? How is the data being stored? How is my data being protected? These are all great questions. In this blog post we are going to demonstrate exploiting local Android storage: how to examine, detect and take advantage of sensitive information being stored by an Android application. So, let’s get started.
When it comes to an Android device the following are some common ways of storing data:
Android Application Databases
We will be using the intentionally vulnerable Android application known as the MASTG Hacking Playground, it can be accessed here. Utilizing Corellium virtualized devices along with the MASTG application we will check frequent Android locations used for storing data and how easily that data can be compromised.
Shared Preferences are XML files to store private primitive data in key-value pairs. Data Types include Booleans, floats, ints, longs, and strings. The Shared Preferences object can be declared world-readable (accessible to all apps) or private. Misuse of the plain-text Shared Preferences can often lead to exposure of sensitive data.
Once you have the MASTG Hacking Playground application installed on your Corellium Android device you can launch into it. Within the menus provided you can select the “Shared Preferences” challenge. This challenge creates a shared preferences files within the Android data directory that we can now retrieve to look for sensitive data.
Corellium Files tab can be used to access the root filesystem for your Android device, every Android application has a data directory which can be found using the following path:
If you are not aware of your application package name you can easily identify that within the apps tab within Corellium.
Now that we are in the data directory for android, this is where you will find a ton of information relating to the application you are looking at. We will continue to use this directory path going forward in this blog post but for now we are going to focus on navigating into the shared_prefs folder.
Within this directory you will find a file (key.xml) which stores sensitive information and can be easily downloaded via the Corellium interface. Once you download the file you can open it with any text editor to see the sensitive data.
There are a large number of applications that utilize Android shared preferences to store sensitive data, API keys, application preferences and more. This data should always be reviewed as part of a mobile security assessment.
Every Android-compatible device supports shared external storage, including all Corellium Android virtualized devices. This storage may be removable (SD or Micro SD Card) or internal on the device. All Files stored within Android external storage are world-readable allowing any application to read the data within.
Once you have the MASTG Hacking Playground application installed on your Corellium Android device you can launch into it. Within the MASTG application menus you can select the “ExternalStorage” challenge. This challenge creates a TXT file with a secret password within the Android external storage directory.
For the device I am using the file is located in the following directory, this directory can vary depending on the device model.
The Corellium Files tab will allow you to easily download the file created (password.txt) and open with a local text editor.
It is worth noting when an application is uninstalled from your device only the data directory is removed, anything that was stored within Android external storage will still remain on the device accessible to anyone with device access and any application installed on your device.
Android application databases
The Android platform has a number of databases that can be used for local data storage. Each one has some unique components and methods that need to be understood to fully analyze the data within.
SQLite is an SQL database engine that stores data in .db files. The Android SDK has built-in support for SQLite databases. With the built-in support from Android SQLite becomes one of the most common ways to store data within an application. A lot of times you will see data stored in plain text, which is the first challenge we will go through.
Within the MASTG application menu you can select the “SQLite” challenge, once you have selected the challenge a database with unencrypted data will be created in the following directory:
In this directory you will see a file named “PrivateNotSoSecure”. This file can be downloaded locally from Corellium and opened with a database reader (command line, DB browser, etc).
When you download the newly created “encrypted” file and open it with the same database viewer from above you get prompted for a password.
Improvement from the unencrypted database above? Sort of. While there is an additional level of protection if the key or password is stored locally within the binary, it is a matter of time before it is located and used to decrypt the contents of the database.
In this case if you navigate to the following directory within Corellium you can retrieve the shared object library that stores the key.
The file in question is “libnative-lib.so”, this can be downloaded from Corellium easily so we can proceed with finding the key. Once you have the file we can use “strings” to search the shared object.
There is a bit of content to go through when you run that but when you look through as part of your analysis you will find the following key.
Let’s take that secret string and enter it when opening the encrypted database. Once you do that you will see the decrypted data.
While there is an improvement to the overall security of the data it is still not protected as much as it can be. Any keys used for encrypted should be either stored offline (webserver) or stored within the Android keystore to prevent the key being exposed.
Firebase Real-Time database can be leveraged by application developers to store and sync data with a NoSQL cloud-hosted database. The data is stored as JSON and is synchronized in real-time to every connected client and also remains available even when the application goes offline.
A misconfigured firebase database can be accessed using the following URL. This does require the firebase project name, which is accessible through reverse engineering an Android application, and reviewing the manifest and/or looking through files within the data directory.
Realm databases are becoming more and more popular among developers. The database and its contents can be encrypted with a key stored in the configuration file.
Similar to what we saw with SQLite the databases can be stored unencrypted and easily accessed. If they are encrypted it would require reverse engineering to determine if the key is hardcoded within a local file, shared object, etc.
Conclusion: Exploiting local Android storage to identify security risks
The steps we discussed above are used to examine local storage for Android applications and detect potential security risks. These techniques can be used by mobile pentesters, appsec professionals and development teams. Corellium makes all of this testing seamless with access to the root filesystem for any Android device and console access for deeper file analysis.
Thoughts, stories and ideas from the Corellium team.
Thoughts, stories and ideas from the Corellium team.
Apple signing with Corellium
Using the Safari Web Inspector with Corellium
How we ported Linux to the M1
Armv9 and Corellium: Why we chose Arm vs X86
Large US telco pentests 3x faster
A brief look at the new Corellium
Corellium support for iOS 16
Faster mobile app pentesting with Corellium
Exploiting iOS local storage with Corellium
Intro to iOS mobile reverse engineering
Subscribe to stay connected
Stay up to date with the latest news and announcements.