2

How My Rogue Android App Could Monitor & Brute-force Your App’s Sensitive Metadata

TL;DR: A rogue Android app could read any other App’s file metadata: filename, size, last modification date. If a filename contained sensitive predictable data, the rogue Android app could locally brute-force this, which was the case for Instagram on Android. Through the leakage of filesize and last modification date, a rogue Android app could monitor real-time usage of others apps. The file system permissions bug has been present in Android since the very beginning. Google rated this vulnerability as a low risk issue and paid out a $500 bug bounty.

Issue

Android App Private Data is currently stored by default in /data/data/<packagename>/. This data is supposed to be visible & accessible only by the App itself, not by any other App. Let’s take the Youtube App as an example. It has its private data stored at location /data/data/com.google.android.youtube/. Let’s look at the directory & file permissions from top to bottom:

As can be noticed, all directories in the hierarchy have the executable (+x) permission set for others. Straight from Wikipedia:

The execute permission grants the ability to execute a file. When set for a directory, this permission grants the ability to access file contents and meta-information if its name is known, but not list files inside the directory, unless read is set also.

Testing this empirically confirms this: other users can cd into these directories, but cannot ls all files inside the directory (no read access) or e.g. create files (no write access):

However, what is remarkable is that existing files inside these directories can be listed and their meta-information gathered, when the filename is known beforehand. In the case of the Youtube app, there is a default file named “youtube.xml” in the shared_prefs folder. This file can be listed by any other app, but not read due to file permissions on the file itself:

As can be seen, any rogue app can thus:

  1. Verify the existence of private files of other apps via attempting to “ls” them on their expected location
  2. Poll the size and last modified data of existing files of other apps

This imposes a security issue. It can be exploited in at least two different ways:

  1. A rogue app can monitor usage of any other app, by monitoring carefully chosen files. E.g. if a rogue app wants to keep track when the Android mobile device user utilizes Youtube, the file size & last modified date of private file “youtube.xml” in Youtube’s shared_prefs directory can be polled periodically. This file is constantly being modified while the Youtube app is in use, and thus can be used to perform stealthy usage profiling.
  2. In case that a legitimate app uses sensitive but predictable data as part of a filename, this can be brute-forced by rogue apps. One example I’ve seen coming by a couple of times is a unique user identifier. E.g. Instagram and Facebook have the below files stored at the following locations:
    • Instagram: /data/data/com.instagram.android/shared_prefs/<USERID>.xml
    • Facebook: /data/data/com.facebook.katana/shared_prefs/XStorage-LATEST-<USERID>.xml

In case of Instagram, the unique USERID currently lies in range 0-2500000000, which is feasible for a local brute-force attack. The following java code for an Android Service can be used by a rogue app to brute force the identifier in the background, in order to reveal the identity of the Android mobile phone’s user via this account:

Note that once the service has been started, the original rogue Android app can be closed – the service will keep on brute-forcing in the background. The attack was performed on a Nexus 4 device and took less than 5 days to cycle through all 2.500.000.000 possible files, hitting the correct one on the go:

ADB Logcat Output

This could be used by an attacker to discover the real identity of the user of the device he/she has infected. This JSONP waterhole attack from 2015 had a similar purpose. Note that Instagram also contains a Content Provider to query the USERID of the registered account (com.instagram.contentprovider.CurrentUserProvider), but is prohibited to query for other apps by default as tested through Drozer:

Drozer Instagram Exported Content Provider - Access Denied

It is thus clearly not the intention of Instagram to reveal this information to other untrusted Applications. I initially found this Android bug while examining the Instagram app during my bug hunting endeavors there.

Remediation

The issue can be remediated by removing the +x permissions for others on app directories in /data/data. This will prevent cd’ing & listing of known files inside these directories, as this property cascades properly:

Timeline

  • 30/11/2015: Submitted bug report to Google Android Bug Bounty
  • 30/11/2015: Reply from Google stating that they will look into it
  • 03/12/2015: Reply from Google stating they are treating this as a High Severity issue
  • 08/01/2016: Update from Google stating that they lowered this to a Low Severity issue
  • 23/01/2016: Update from Google stating that they see this as a hardening request, rather than a security issue. “There is a fix available and it will be part of the next major Android release.”
  • 14/04/2016: $500 bounty granted
  • 08/09/2016: Confirmation of fix in Android 7.0 by Google & permission to publish this blogpost granted

Belgian. IT Security. Bug Bounty Hunter.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *