Purpl3F0x Secur1ty

Pentesting, reverse engineering, and phishing & malware analysis.

12 January 2023

DIVA - An intentionally vulnerable Android app - Part 1: Insecure Storage

by purpl3f0x


Intro


After spending a year working on Android malware analysis, I am now making the transition to Android security assessments. I’ve been studying up on the subject for the last few weeks, and I have been practicing on deliberately vulnerable apps. I am going to share my experience working with DIVA, the Damn Insecure and Vulnerable App. Each of the challenges are fairly short, so I’ll be breaking them up by category instead of doing individual posts.

Today, I’ll be covering the challenges that fall under the umbrella of Insecure Storage. There are four challenges in this category, each slightly increasing in difficulty, but each also teaching the different places that should be checked when assessing an Android app.


Insecure Storage 1


The challenge asks you to enter a username and a password, and it will store it somewhere in an insecure manner. The goal is to see if you can find where the credentials were stored, and prove that they were stored in a way that goes against best security practices.

Figure 1 - Enter some fake creds.


To get our first clue on where to look, we can check out the decompiled code in Jadx GUI:

Figure 2 - Finding hints in code.


It appears that the credentials are being put into the Shared Preferences on the device, and it doesn’t appear to hash or encrypt the credentials based on what is in code here.

Using ADB, we can connect to the phone and have a look in the files:

Figure 3 - Finding shared_prefs.


Inside this directory is an XML file. We can use cat to view the contents of the file and see that the credentials were stored in plain text:

Figure 4 - Exposed secrets.


This solves challenge #1.


Insecure Storage 2


Challenge #2 asks us to input credentials again, but this time they will be stored a different way. Once again, we look at code to get our hint:

Figure 5 - Credentials saved to a SQLite database.


Android apps can make use of SQLite for storing and querying data, and it appears that in this case, the credentials we supplied are being stored in a database by the name of ids2. Once again, there is no evidence in code that any hashing or encryption is happening.

Making use of the same ADB shell, we can see where the database is stored:

Figure 6 - Finding the database.


To make it easier to work with the file, we can copy this file to the sdcard, and then use ADB to pull the file to the local machine:

Figure 7 - Exfiltrating the database.


At this point, the method you use to view the contents of the database is up to you. There are tools for reading SQLite databases, you could use Python to read and extract the contents of the database, or use an online viewer:

Figure 8 - Discovering the secrets.


An amusing side-note; this exercise initially didn’t work for me. I wasn’t sure what was happening, until I realized that the password I supplied, ThisIsn'tSecure, had a single-quote in it, and it was likely causing issues with the SQL statement in the app’s code. In other words, I unintentionally found a SQLi vulnerability!


Insecure Storage 3


As with the last two challenges, we have to give the app some fake credentials that the app will store somewhere. We’ll go back to Jadx to see what is happening this time:

Figure 9 - Secrets written to the app's data directory.


It looks like the credentials are not being hashed or encrypted, and are being written to a file that starts with uinfo. The code suggests that it is being put into the data directory used by the app. This is the same directory that we have already been poking around in:

Figure 10 - The secrets are revealed again.


The theory seems to be accurate, and the credentials were found very easily.


Insecure Storage 4


This is the final challenge for the Insecure Storage category, and it was slightly trickier than the others, because the hints from the code were not as straight-forward as I initially thought. Looking in Jadx, it would appear that the credentials are being stored on the SD card:

Figure 11 - File written to external storage.


Yet again, there is no attempt to obfuscate the credentials or the file. The app fetches the path to external storage and puts the file there, and yet it doesn’t seem as though the file is in the expected location:

Figure 12 - Where is it?


At this point, I was not sure of where to look, so I decided to make use of Medusa to help catch the app in the act of writing the file:

Figure 13 - Preparing Medusa.


With Medusa hooked into the app, I wrote in some fake credentials again, and this time I was able to determine where the file was being written to:

Figure 14 - Finding the true path


Figure 15 - Discovering the credentials.



Conclusion


This concludes the Insecure Storage challenge set in DIVA. Developers have many options when storing credentials locally, but effort needs to be made to do so securely. Credentials should not be stored in locations that are easy to discover, but if there is no way around that, credentials should be hashed using suitable algorithms in order to avoid unintentional disclosure of sensitive data. This is a key area that pentesters should be going over with a fine-tooth comb when conducting security assessments or when participating in bug bounty.


Appendix

Device used:

Tools used:

tags: Pentesting - Reverse Engineering - Android