This post is also available in: 日本語 (Japanese)

Executive Summary

We discovered a widespread vulnerability in Google’s Android OS we are calling “Android Installer Hijacking,” estimated to impact 49.5 percent of all current Android users. In detail:

Android Installer Hijacking allows an attacker to modify or replace a seemingly benign Android app with malware, without user knowledge. This only affects applications downloaded from third-party app stores.

The malicious application can gain full access to a compromised device, including usernames, passwords, and sensitive data.

Palo Alto Networks worked with Google and major manufacturers such as Samsung and Amazon to inform them of the vulnerability and issue patches for their devices.

Introduction

In January 2014, we uncovered a Time-of-Check to Time-of-Use (TOCTTOU) vulnerability in Android OS that permits an attacker to hijack the ordinary Android APK installation process. This hijacking technique can be used to bypass the user view and distribute malware with arbitrary permissions. It can substitute one application with another, for instance if a user tries to install a legitimate version of “Angry Birds” and ends up with a Flashlight app that’s running malware. We are calling the technique that exploits this vulnerability Android Installer Hijacking. We have been cooperating with Google and major manufacturers such as Samsung and Amazon to patch affected Android devices.

Vulnerability Description

In order to understand how this works, let’s first take a look at how Android installs apps. Android supports the ability to install apps from the Google Play store as well as from the local file system. Google Play downloads Android packages (APKs) to a protected space of the file system. Third party app stores and mobile advertisement libraries usually download APK files to unprotected local storage (e.g. /sdcard/) and install the APK files directly. Both methods use a system application called PackageInstaller to complete the installation.

On affected platforms, we discovered that the PackageInstaller has a “Time of Check” to “Time of Use” vulnerability. In layman’s terms, that simply means that the APK file can be modified or replaced during installation without the user’s knowledge. The Installer Hijacking vulnerability affects APK files downloaded to unprotected local storage only because the protected space of Play Store app cannot be accessed by other installed apps.

Let’s take a closer look at what happens.

On Android, there are many ways to trigger the app installation process, for example, when the user clicks a downloaded APK file, or when the user downloads an app from a third party app store app, or when the user clicks on an app promotion advertisement hosted by a mobile advertisement library. No matter which way an APK installation process is triggered, it always follows the same procedure:

First, the system service PackageInstaller starts the installation process by parsing the APK file and retrieves critical information about the app, such as the app name, app icon and the security permissions that the app requests. This is presented to the user in a PackageInstallerActivity view on the screen, as seen below Fig 1:

Fig 1. User reviews the detail information of app to be installed (i.e. “Time to Check”).

This is the “Time to Check”, because it verifies that the user really wants to install the app, and tells the user what permissions that they are authorizing the app to perform. All Android apps perform this step, and the user clicks “Next” to view the full list of permissions, and then clicks “Install” to continue the installation process (as in Fig 1).

A vulnerability exists in this process because while the user is reviewing this information, the attacker can modify or replace the package in the background. Verified with Android OS source code posted in AOSP, it shows that the PackageInstaller on affected versions does not verify the APK file at the “Time of Use”. Thus, in the “Time of Use” (i.e., after clicking the “Install” button), the PackageInstaller can actually install a different app with an entirely different set of permissions.

Exploitation

This vulnerability can be exploited in multiple ways:

Method A: Externally modifying the APK

The attacker can use a benign-looking app to install malware in the future. This method has several stages:

Victim installs “App X” which appears legitimate. This app does not require any particularly dangerous permissions, and it can come from any normal app store. At a later date, the victim installs a perfectly legitimate app store (e.g. Amazon’s App Store app) which then allows the user to install APK files from local file system. Whenever the user attempts to install apps from this app store a PackageInstallerActivity view will been launched. The user sees an app from the legitimate 3rd party app store and attempts to install it. We will call this download “App Y”. The app from step 1, “App X” detects that PackageInstallerActivity view has been launched, and checks if the APK file of “App Y” is on an unprotected file system. If the app is being installed from a public file system (e.g., on /sdcard), then “App X” can overwrite the “App Y” with malware while the user is reviewing the permissions screen. After clicking “Install”, PackageInstaller will install the compromised “App Y” APK with the malware. Arbitrary code is now installed on the device, with any permissions that the attacker needs.

One tricky question with Method A would be how the App X detects that the PackageInstallerActivity view has been launched. There are two approaches here:

The App X can monitor the logcat to detect the app installation and get the information of apk file location to replace the file. This is straightforward on Android <4.1. For Android >=4.1, only rooted devices can access logcat.

The App X can monitor the location of directory where the targeted app saves the APK files downloaded for installation. For example, the Amazon Appstore app version 7.5 stored the APK file downloaded in a directory on sdcard without protection. When the user downloads the APK file from the Appstore app, a new APK file will appear in this directory. The App X does not need to know which file this downloaded file is. When the file appears, it means the installation view (Fig 1) is already popped up on the screen for user to review. So, the App X app can replace this APK file by its malware app at that time. (Please note that Amazon fixed this issue after receiving our report.)

Method B: Self modifying the APK

This exploit can take advantage of the same vulnerability to mask what permissions the app really requires.

Victim installs “App X” which appears legitimate. When the user is using “App X”, it promotes a legitimate “App Y” (e.g. a popular game app) to the user for installation. If the user installs the app, the PackageInstallerActivity view will start. As discussed above, the essential information of “App Y” will be shown in the PackageInstallerActivity view. The “App Y” does not appear to ask for anything out of the ordinary. In fact, the “App Y” may not ask for any permission at all. When the user is viewing the PackageInstallerActivity, “App X” rewrites the APK file of “App Y” with malware. When the user clicks “Install”, the modified version of “App Y” will be installed, ignoring the actual permissions requested. The app actually installed may not be related or similar to App Y in any way.

Scope

This vulnerability affects Android device users as well as Android app developers.

For Android device users, the users may end up with installing apps that are not the ones they agree to install.

Android app developers are also affected, because app-store apps and mobile ads libraries that do not rely on Google Play store would be likely to save the promoted apps in unprotected storage, e.g. /sdcard. Like the example we show with Amazon appstore app, the unprotected storage in /sdcard may allow attackers to replace the promoted apps with malware apps.

We have successfully tested both exploits against Android 2.3, 4.0.3-4.0.4, 4.1.X, and 4.2.x. According to Android Dashboard, this vulnerability affected approximately 89.4 percent of the Android population as of January 2014 (when we first discovered it), and approximately 49.5 percent of the Android population as of March 2015.

These exploits do not require the device to be rooted, but rooted devices are more vulnerable.

Some Android 4.3 Distributions Are Vulnerable

Be aware that some phone vendors’ Android 4.3 distributions may contain this vulnerability as well.

According to source code posted on the AOSP website, Android 4.3_r0.9 introduced a hash check of the Android manifest that is verified between “Time to Check” and “Time to Use”. However, we have found that there are some phone vendors’ Android 4.3 distributions that do not include this check. For instance, we have successfully tested this exploit on Samsung Galaxy S4 Android phones running Android 4.3 (Build version JSS15J.I337UCUEMK2, Built on Nov. 16, 2013), and Amazon Fire OS version 13.3.2.5. Both Samsung and Amazon have released fixed on their affected devices after receiving our vulnerability reports.

We encourage all Android device vendors to verify the existence of this vulnerability on their devices including those with Android 4.3.

Android version 4.4 and later versions have fixed this vulnerability.

Mitigation

Palo Alto Networks has published a vulnerability scanner app in the Google Play store. Also, we have recorded a tutorial video about how to check the existence of installer hijacking vulnerability with our vulnerability scanner app, available here.

To facilitate security researchers and other vendors, we have also open sourced the vulnerability scanner app on Github at https://github.com/PaloAltoNetworks-BD/InstallerHijackingVulnerabilityScanner.

Enterprises concerned about the risk should take the following steps:

Only install software from Google Play in affected devices. These files are downloaded into a protected space, which cannot be overwritten by the attacker.

Deploy mobile devices with Android 4.3_r0.9 and later, but keep in mind that we have found that there are some vulnerable Android 4.3 devices.

Do not provide apps with permission to access logcat. Logcat is a system log, which can be used to simplify and automate the exploit. Android 4.1 and later by default forbid apps from accessing logcat of system and other installed app. But an installed app could still manage to get access to other apps’ logcat on rooted mobile devices with Android 4.1 and later.

Do not allow users to use rooted devices.

App developers concerned about the risk should save the downloaded APK files to protected storage space only.

Vendor Feedback

From Google:

“Android Open Source Project includes patches for this issue for Android 4.3 and later. The patch is available for review here: https://android.googlesource.com/platform/packages/apps/PackageInstaller/+/2b3202c3ff18469b294629bf1416118f12492173

The Android Security Team has not detected any attempts to exploit this vulnerability on user devices.”

From Amazon:

“Customers should move to the latest version of the Amazon AppStore which gets updated automatically on Fire devices and for 3rd party Android devices it can be updated via www.amazon.com/getappstore.”

Disclosure Timeline

January 2014: Initial discovery by Palo Alto Networks

February 2014: Vulnerability reported to Google Android Security Team

March 2014: Vulnerability reported to Samsung

September 2014: Vulnerability reported to Amazon

March 2015: Public Disclosure

Acknowledgements

We would like to thank Ryan Olson, Huagang Xie, Claud Xiao, Colt Blackmore, and Taylor Ettema from Palo Alto Networks for their great help in verifying the vulnerability and communicating with vendors. We also greatly appreciate the help from Scott Simkin, JL Watkins, Baoyue Hu, and Erik Jacobsen from Palo Alto Networks in publishing the discovery and building the scanner app. We appreciate the cooperation with Samsung Knox team, Google Android Security team, and Amazon Web Services & Lab126 for working with us on verifying and patching this vulnerability.