Accessing the user’s current location and location history without their permission on (older versions of) Android

Caveat before you read on. This article was initially written a few years ago but never published. Google has since then patched this particular vulnerability on devices running Android 10 and later but a lot of users still use older versions of Android to this day so I thought it was still relevant to post

This might not be obvious to a lot of people, but there is a way to access the user’s current location and location history on older versions of Android without explicitly asking for their permission.

Android introduced a much desired runtime permissions system a few years ago, much to the delight of users and developers alike.

The idea is that, if your app is targeting a specific version of Android and later, you cannot access certain information on the device unless you explicitly ask for the user’s permission while they are using your app (some apps held out targeting later versions of Android because of this. Thankfully, Google has decided some time ago to put an end to this.)

Location is one of those pieces of information. Amongst all the data you can collect about a user, location is king, since it allows companies to very narrowly target their users with ads, content, or even use that information for nefarious purposes.

Google knows this and has put extra effort into plugging any holes in the design of Android that might leak that information to apps without the user’s consent. As an example, if your app needs access to the WiFi details, you must also ask the user to grant you access to your coarse or fine location, since accessing your WiFi’s name allows for a reverse lookup of your general location given a big enough sample of SSIDs.

Unfortunately, there is a very easy way to retrieve both the current user’s location and their location history (to an extent) without explicitly asking the user for permission (on devices with Android 9 and older).

How you ask? Photo EXIF data.

All you have to do is to ask the user to take a photo using their system camera without asking for a camera permission either, and then read the EXIF data on the produced photo. This can be done with a few lines of code (the full source can be found on Github):

// This requires NO permissions (camera, storage etc)
fun askForPhoto(activity: Activity, imageRequest: Int) {
  val dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
  val picture = File(dir, UUID.randomUUID().toString())
  // keep this. Will be used later in the onActivityResult method
  photoUri = FileProvider.getUriForFile(this, "com.savvasdalkitsis.fileprovider", picture)
  val photoIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
  photoIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
  startActivityForResult(photoIntent, imageRequest)
}
fun getLocation(photoUri: Uri): Pair<Double, Double> {
  contentResolver.openInputStream(photoUri).use { stream ->
    val latLon = ExifInterface(stream).latLong
    return Pair(latLon[0], latLon[1])
  }
}

You can even retrieve their location history if you ask to access their camera roll (with the runtime permission READ_EXTERNAL_STORAGE) and now you have access to a series of geolocations with date and time attached to them (the location extracted from your camera roll will NOT be the same as the Google Location History, if you have it enabled, as these two data sets are completely different).

Not convinced? Here is a sample app I wrote that does just that. It pretends to be a selfie app (any excuse to make the user take a picture for you or give you access to their camera roll will work of course) and then presents you with your location inside the app. All done without asking for the location permission at any point:

And here is the app in action:

A couple of points. For this to work, your camera app must have the ‘Save Location’ setting enabled. Some camera apps have this setting enabled by default but your camera app might not. In that case, your location cannot be extracted. The default Google camera asks the user to enable this option on first use. Many users (myself included) will allow this and be vulnerable. I also tried the default camera on Samsung Galaxy phones with similar results.

(please note that users who have granted location access to their camera app can revoke this at any time via the location settings on the device: Settings → Security & Location → Location → App permissions. Also, each camera app will have a similar option inside its own settings. For the Google Camera mentioned above this will be under Camera → More → Settings → Save Location)

You can play around with this yourself and see if your camera app is vulnerable by building the app from Github.

Please note that the sample app DOES NOT upload your location to any server. It does use the internet to download the embedded map data.

Also note that a similar exploit existed on iOS, as any app with access to the user’s Photos could get a location history using the method described above. This was released by Felix Krause in a blog post on Oct 2017 which can be found here: https://krausefx.com/blog/ios-privacy-detectlocation-an-easy-way-to-access-the-users-ios-location-data-without-actually-having-access

In conclusion, I am not aware of any particular apps using this trick but, in my opinion, it is highly likely that some do. What I would suggest, is to always review the permissions an app requires, and make a judgement call on whether you trust the app publisher enough before giving them access to your photos or your camera.

Leave a comment