Vendor: Google
Product: Docs Android app
Version: 1.20.302.01.40
Platform: Android
Reported: 7/11/2020
Fixed: 8/26/2020
CVE: N/A

This write-up covers a low-severity vulnerability found in Google Docs Android app. Hope it is of interest!

Quick primer on Android app security. An Android app can use a framework, content providers, to make data available to other internal components or share data with third party apps. Content providers accept a URI (Uniform Resource Identifier) and return data, usually from a database or a file. A URI loosely consists of a protocol, host, path, and parameters, for example protocol://host.value/path/to/resource?param=value. You may be familiar seeing web URIs like http://example.com/path?x=1 in your browser’s address bar. Content providers use similar structure.

Content providers use the content:// protocol. The host value is an arbitrary, developer chosen string specified in the app’s manifest file. Android distinguishes different providers on a device by the host value, thus, the host value is intended to be unique per content provider. Providers made available, or exported, to third party apps are interesting from a security perspective. If an exported provider holds sensitive information and lacks safeguards (like permission tags or runtime checks), it can lead to a security vulnerability.

Armed with this background information, let’s dive in…

While analyzing the Google Docs Android mobile app, I noticed it exported a content provider with no permissions associated:

Reviewing the decompiled code revealed the provider took the input URI and parse out the path value. The parsed path was compared against a couple hardcoded values – text/plain and text/html. While it wasn’t apparent to me at the time, it later turned out the provider would return different data based on this path value.

The next step in analysis was to connect my test device to my computer and launch a device shell with adb shell. Android has a command line tool, content, which allows us to interact with providers straight from the shell. I tested the behaviour of the Docs provider by attempting to “read” a file from the provider, with one of the mimetypes appended to the end.

content read --uri content://com.google.android.apps.docs.editors.kix.editors.clipboard/text/plain

Running this in my shell yielded the following output:

I recognized this as content I had copied to my clipboard while editing a test document within Google Docs earlier!

Re-running the content command with path text/html instead of text/plain yielded the same data with HTML markup:
content read --uri content://com.google.android.apps.docs.editors.kix.editors.clipboard/text/html

Google Docs was apparently storing data last copied to clipboard when editing a Docs file. The content provider exposed this data. The text/plain path returned plaintext copied data while the text/html path returned the copied data wrapped in HTML markup.

After further testing I also discovered if a image was copied to the clipboard in Docs, the text/html markup included the image’s URL, which looked like *.googleusercontent.com/<long random value>. The image URL didn’t require authentication. By parsing image URLs from the HTML representation of clipboard data, we could access images embedded in the doc if they had been copied to clipboard. The text/plain content did not include image references even if one had been copied to the clipboard.

The provider continued to return the last copied data even after leaving the app and even after copying text to the Android clipboard from within another app.

At this point, I had determined any app on the device could access data last copied to the clipboard within Google Docs. But clipboards fundamentally exist to enable data transfer between apps. Was this really a security issue?

Prior to Android 10, any app could access Android clipboard data at any time. Exposing data that existed on the clipboard at some point wasn’t really an issue since the clipboard was essentially a public data bucket on the device. However, Android 10 introduced a new restriction. Apps can only access clipboard data if they are the currently focused app or are the input app i.e. the keyboard (https://developer.android.com/about/versions/10/privacy/changes#clipboard-data). The exported content provider now broke an Android 10 security boundary. A non-input app without focus could read data previously copied to the clipboard within Docs.

Let’s consider the following scenario on Android 10:

  1. User edits a file in Docs, copies content to clipboard.
  2. User exits Docs, opens web browser.
  3. User copies content from web page.

After step 3, the data copied to the clipboard in Docs is no longer on the clipboard. The only apps permitted access to the data while on the clipboard were Docs, the input app (keyboard), and the web browser app. However, the vulnerable provider allowed any app on the device to read the copied data, starting from when it was put on the clipboard up until the user next copies something inside Docs, minutes, days, or theoretically years later.

Bingo! Vulnerability.

I (and Google) considered this a low severity issue since an attacker can’t control what data they get and a user is unlikely to copy an entire document at once, just a snippet. Nevertheless it was a valid leak and Google patched it. Querying the vulnerable content provider now causes an exception and no data is returned.

All glory be to Jesus Christ! Thanks for reading and have a great day. Until next time,
Carl

John 3:16