RESEARCH | April 1, 2019

Multiple Vulnerabilities in Android’s Download Provider (CVE-2018-9468, CVE-2018-9493, CVE-2018-9546)

Android’s Download Provider is a component of the Android framework and is designed to handle external downloads for other applications, such as web browsers (including Google Chrome), email clients (including Gmail), and the Google Play Store, among many others. In this blog post, I’ll describe three different high-severity vulnerabilities which affected several of the most recent versions of Android.

Android’s Download Provider

Any app can delegate its external downloads through this provider. As a developer, you’ll only need to insert a row with the appropriate parameters (invoking the Download Content Provider, part of the Download Provider, also called Download Manager). The Android Framework will handle the download for you automatically, in a background process which offers different configuration options. The notification with a progress bar that you’ve most likely seen several times (when downloading documents, attachments, or apps, for instance) is related to this provider, as illustrated in the following screenshots.

Overview of Vulnerabilities

By performing a research-driven manual code inspection of the Download Provider, using a very similar approach to the one I took with the Personal Dictionary Provider, I discovered three high-severity vulnerabilities. The following issues were reported to Google, along with their corresponding proof-of-concept tools for exploitation:

  • CVE-2018-9468: Permission bypass
  • CVE-2018-9493: SQL injection
  • CVE-2018-9546: Headers disclosure

CVE-2018-9468: Download Provider Permission Bypass

The Download Provider is secured by different permissions and other protection mechanisms with various levels of access. As a general rule, a regular application should only have access to its own downloads. However, by exploiting this trivial vulnerability, any application (even without any permissions granted at all) can access any download that was requested by any other application or component of the OS itself, through the following content provider URI:

  • content://downloads/public_downloads/#

A malicious application would only need the identifier of a targeted download to gain access to it. This identifier is a sequential number, so all downloads are very easy to locate using a simple iteration. Once an existing download is located, most of the information stored in the provider’s database will be directly accessible through the Download Content Provider, including its title, description, size, full URL, etc. This may leak potentially sensitive information, including authentication tokens in the URL, email addresses, confidential document titles, email subjects found in the title or description columns, and so on.

This is only one of the aspects a malicious app can leverage. Actually, the impact is notably higher, because the openFile() method of the Content Provider is also affected by the vulnerability, since it relies on the query() call to check for permissions. That means that the attacker would also have unrestricted read and write access to the downloaded files. By exploiting this flaw, it’s possible to leak any downloaded file, and even worse, to overwrite it with arbitrary content, even before the download is complete.

This would allow a malicious app to read and potentially exfiltrate all your downloads (think about email attachments, electronic bank statements, or any other file you may download while browsing the Internet), which is obviously pretty bad for your confidentiality and the integrity of your data.

The following video demonstrates how all this data, including file contents, is publicly accessible by any other app. The proof-of-concept exploit just iterates through a range of identifiers, dumps some fields from the internal database, and displays the initial chunk of the downloaded file. The results are limited for brevity and demonstration purposes only, but keep in mind that the entire file would be accessible.

Gmail disclosure

Given the ability to write to these files, a malicious app can run a background service which monitors and overwrites any download requested through Android’s Download Provider. Since the Over-The-Air (OTA) updating process and the Google Play Store also use this provider, a malicious app can constantly overwrite any update or new app your smartphone is downloading, preventing a legitimate user from installing new apps or updating existing ones, including the OS itself, as demonstrated in the following videos.

DoS installing apps
DoS updating apps

In addition, any other downloaded attachment or file could easily be overwritten with arbitrary content using the very same process. This could be abused to replace files that you or your apps may consider trusted (from your bank, company intranet, HTTPS resources, apps using certificate pinning, etc.) to leverage a wide variety of potential exploits, as the downloads can’t be considered trusted anymore. These videos demonstrate the issue using different attack scenarios.

Gmail attachment hijack
Image file hijack
PDF file hijack

The source code and compiled APK for the proof-of-concept application used in these videos can be found in the following GitHub repository:

https://github.com/IOActive/AOSP-DownloadProviderHijacker

CVE-2018-9493: Download Provider SQL Injection

Some columns in the internal database (such as CookieData) are considered private and can’t be accessed directly through the Download Content Provider, unless the caller has unrestricted permissions (the URI is protected by the signatureOrSystem access level).

Specifying any of the restricted columns directly in the projection parameter won’t give us the results, obviously, but exploiting an SQL injection in the where expression, bypassing the setStrict filter, will allow us to extract content from the internal database, including restricted columns for any download. This vulnerability was introduced in 2016 in a change to enable search and filtering capabilities.

Note that this injection can also be combined with the previously described vulnerability (CVE-2018-9468), bypassing the permission’s requirement (by accessing the public_downloads URI, rather than my_downloads). Otherwise, it only requires the INTERNET permission (which isn’t considered dangerous and most apps have) in order to be exploited separately.

The source code and compiled APK for the proof-of-concept application that exploits this vulnerability can be found in the following GitHub repository:

https://github.com/IOActive/AOSP-DownloadProviderDbDumper

CVE-2018-9546: Download Provider Headers Disclosure

Consider an application that requests a download which, apart from the URL, needs some HTTP headers, such as authentication, cookies, or anti-CSRF tokens, for instance. To support this feature, Android’s Download Provider allows developers to request a download with any standard or custom HTTP headers. These headers will be stored in the database and exposed through the Downloads Content Provider, by simply specifying the identifier of the related download.

Unfortunately, Android never checks if you have permission to access the desired rows belonging to the identifier you’re requesting, so all headers of every single download can be trivially dumped by simply iterating through all existing identifiers.

A malicious app only requires the INTERNET permission to gain read access to all these headers. For instance, the default Android Browser app (not the latest versions of Google Chrome) in Android 5.1 stores all HTTP cookies in this table. This could lead to a highly sensitive information leak, allowing an attacker to steal your sessions if you happen to download any file from an authenticated website using that browser, as demonstrated in the following video.

cookie disclosure

The source code and compiled APK for the proof-of-concept application used in the video can be found in the following GitHub repository:

https://github.com/IOActive/AOSP-DownloadProviderHeadersDumper

Remediation

As an Android user, make sure your device is fully patched and never install untrusted apps. These vulnerabilities were fixed in the AOSP patches released on September and October 2018. For different vendors, check their security bulletins to ensure all three CVEs enumerated here are listed as patched.

As a developer, always apply defense-in-depth best practices and never trust a downloaded file that could have been tampered with in transit or at rest, as demonstrated in the videos in this post. Beware of potential race conditions or TOCTOU (Time-of-Check to Time-of-Use) vulnerabilities in your validation process.

Conclusions

It wasn’t hard to find these high-severity vulnerabilities. I discovered them in a few hours, by simply inspecting some source code fragments and understanding a relatively small component of the Android Framework, such as the Download Content Provider.

Whether you are working from a developer’s or a security auditor’s perspective, make sure to identify all entry points, understand the big picture, and pay attention to every detail that might lead to a vulnerability. Most of the time, the problem isn’t in the code that you can read, but in the code that you can’t see because it isn’t there, even though it should be, such as missing validations, permission checks, and so on.

More Information

Find more detailed information in our corresponding security advisories:

IOActive Security Advisory – Android’s Download Provider Permission Bypass (CVE-2018-9468)
IOActive Security Advisory – Android’s Download Provider SQL Injection (CVE-2018-9493)
IOActive Security Advisory – Android’s Download Provider Request Headers Disclosure (CVE-2018-9546)