Android provides several options to save persistent application data, one of which is External Storage (/sdcard, /mnt/sdcard). "External storage" examples include a micro- or standard-sized SD card internal to the device, Android device storage mounted to a PC, and the Android/obb directory.

Files saved to the external storage prior to Android 4.1 are world-readable. Prior to Android 1, files saved to external storage are world-writable. From Android 1 to Android 4.3, only the WRITE_EXTERNAL_STORAGE permission is required for an app to write to any external storage file stored by any app. Starting with Android 4.4, groups and modes of files are created based on a directory structure, which allows an app permission to manage/read/write files within a directory structure based on its package name. Starting with Android 4.4, users (including apps as users) are isolated from primary external storage spaces of other apps controlled by the Android device.

Consequent to the lack of restrictions described above, files written to external storage can be modified or read by other apps installed on the device (for the Android versions which allow read/write) and by anyone with access to the files if stored on an off-device external storage device such as a PC (or if the in-device external storage media is removed and mounted elsewhere).

The Android API Guides [Android Guides 2013Storage Options states:

Caution: External storage can become unavailable if the user mounts the external storage on a computer or removes the media, and there’s no security enforced upon files you save to the external storage. All applications can read and write files placed on the external storage and the use can remove them.

Developers should not store sensitive data to external storage devices unless encrypted first, because files stored externally have no guarantee of availability, integrity, and confidentiality.

Noncompliant Code Example

The following code creates a file on the external storage and saves sensitive information to the file:

private String filename = "myfile"

private String string = "sensitive data such as credit card number"
FileOutputStream fos = null;

try {
  File file = new File(getExternalFilesDir(TARGET_TYPE), filename);
  fos = new FileOutputStream(file, false);
  fos.write(string.getBytes());
} catch (FileNotFoundException e) {
  // handle FileNotFoundException
} catch (IOException e) {
  // handle IOException
} finally {
  if (fos != null) {
    try {
  	fos.close();
    } catch (IOException e) {
      // handle error
    }
  }
}

Proof of Concept

Typically, an application stores files in the directory as follows:

/sdcard/Android/data/com.company.app/files/save/appdata/save_appdata

Compliant Solution #1 (Save a File on Internal Storage)

The following code uses the openFileOutput() method to create "myfile" in an application data directory with permission set to MODE_PRIVATE so that other apps cannot access the file:

 

private String filename = "myfile"
private String string = "sensitive data such as credit card number"
FileOutputStream fos = null;

try {
   fos = openFileOutput(filename, Context.MODE_PRIVATE);
   fos.write(string.getBytes());
   fos.close();
} catch (FileNotFoundException e) {
  // handle FileNotFoundException
} catch (IOException e) {
  // handle IOException
} finally {
  if (fos != null) {
    try {
      fos.close();
    } catch (IOException e) {
      // handle error
    }
  }
}

Compliant Solution #2

Securely encrypt the data first, prior to storing it on external storage such as an SD card. A note of caution: many default and non-default behaviors in Android and other cryptographic libraries have been found to use non-secure encryption methods. See DRD17-J,  DRD18-J, and [Egele 2013] for more information.

Risk Assessment

Storing sensitive information on external storage can leak sensitive information to malicious apps.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DRD00-J

medium

probable

medium

P12

L1

Automated Detection

It is possible to automatically detect whether an application writes to external storage. It is not feasible to automatically determine whether such output could be stored internally. At least one automated analysis exists which checks if an Android app follows particular rules for secure encryption [Egele 2013], but those rules are not comprehensive and thus passing the automated checker does not guarantee sound encryption.

Related Vulnerabilities

  • JVN#92038939 mixi for Android information management vulnerability
  • JVN#05102851 Yome Collection for Android issue in management of IMEI

Related Guidelines

Android Secure Coding Guidebook by JSSEC

4.6 Secure File Handling
4.6.1.4 Handling external storage files
4.6.2.1 When creating new files, make them private
4.6.2.2 Don’t create files accessible from other apps with read/write privilege
4.6.2.3 Minimize the use of files stored in external storage such as SD card
4.6.2.4 Consider the lifetime of files when designing apps

[The CERT Oracle Secure Coding Standard for Java]DRD17-J. Do not use the Android cryptographic security provider encryption default for AES
[The CERT Oracle Secure Coding Standard for Java]DRD18-J. Do not use the default behavior in a cryptographic library if it does not use recommended practices

Bibliography

[Android API 2013]Class Environment
[JSSEC 2014]4.6 Secure File Handling
[Source.android.com]External Storage Technical Information
[Egele 2013]An Empirical Study of Cryptographic Misuse in Android Applications

 

      

2 Comments

  1. I guess that it is safe to store sensitive data on external storage if it is (strongly) encrypted.  Should this be added as an exception?

    1. Unknown User (lflynn)

      Good point. I added text about strong encryption, plus differentiated some inter-app vulnerabilities according to Android versions.