Microsoft discovered a path traversal-affiliated vulnerability pattern in multiple popular Android applications that could enable a malicious application to overwrite files in the vulnerable application’s home directory. The implications of this vulnerability pattern include arbitrary code execution and token theft, depending on an application’s implementation. Arbitrary code execution can provide a threat actor with full control over an application’s behavior. Meanwhile, token theft can provide a threat actor with access to the user’s accounts and sensitive data.
We identified several vulnerable applications in the Google Play Store that represented over four billion installations. We anticipate that the vulnerability pattern could be found in other applications. We’re sharing this research so developers and publishers can check their apps for similar issues, fix as appropriate, and prevent introducing such vulnerabilities into new apps or releases. As threats across all platforms continue to evolve, industry collaboration among security researchers, security vendors, and the broader security community is essential in improving security for all. Microsoft remains committed to working with the security community to share vulnerability discoveries and threat intelligence to protect users across platforms.
After discovering this issue, we identified several vulnerable applications. As part of our responsible disclosure policy, we notified application developers through Coordinated Vulnerability Disclosure (CVD) via Microsoft Security Vulnerability Research (MSVR) and worked with them to address the issue. We would like to thank the Xiaomi, Inc. and WPS Office security teams for investigating and fixing the issue. As of February 2024, fixes have been deployed for the aforementioned apps, and users are advised to keep their device and installed applications up to date.
Recognizing that more applications could be affected, we acted to increase developer awareness of the issue by collaborating with Google to publish an article on the Android Developers website, providing guidance in a high-visibility location to help developers avoid introducing this vulnerability pattern into their applications. We also wish to thank Google’s Android Application Security Research team for their partnership in resolving this issue.
In this blog post, we continue to raise developer and user awareness by giving a general overview of the vulnerability pattern, and then focusing on Android share targets, as they are the most prone to these types of attacks. We go through an actual code execution case study where we demonstrate impact that extends beyond the mobile device’s scope and could even affect a local network. Finally, we provide guidance to users and application developers and illustrate the importance of collaboration to improve security for all.
Overview: Data and file sharing on Android
The Android operating system enforces isolation by assigning each application its own dedicated data and memory space. To facilitate data and file sharing, Android provides a component called a content provider, which acts as an interface for managing and exposing data to the rest of the installed applications in a secure manner. When used correctly, a content provider provides a reliable solution. However, improper implementation can introduce vulnerabilities that could enable bypassing of read/write restrictions within an application’s home directory.
The Android software development kit (SDK) includes the FileProvider class, a subclass of ContentProvider that enables file sharing between installed applications. An application that needs to share its files with other applications can declare a FileProvider in its app manifest and declare the specific paths to share.
Every file provider has a property called authority, which identifies it system-wide, and can be used by the consumer (the app that wants to access the shared files) as a form of address. This content-based model bears a strong resemblance to the web model, but instead of the http scheme, consumers utilize the content scheme along with the authority, followed by a pseudo-path to the file that they want to access.
For example, assuming that the application com.example.server shares some files under the file:///data/data/com.example.server/files/images directory that it has previously declared as shared using the name shared_images, a consumer can use the content://[authority]/shared_images/[sub-path]/[filename] URI to index these files.
Access is given by the data sharing application most commonly using the grantUriPermissions attribute of the Android manifest, in combination with special flags that are used to define a read or write mode of operation. The data sharing application creates and sends an intent to the consumer that provides temporary fine-grained access to a file. Finally, when a provider receives a file access request, it resolves the actual file path that corresponds to the incoming URI and returns a file descriptor to it.
Implementation pitfalls
This content provider-based model provides a well-defined file-sharing mechanism, enabling a serving application to share its files with other applications in a secure manner with fine-grained control. However, we have frequently encountered cases where the consuming application doesn’t validate the content of the file that it receives and, most concerning, it uses the filename provided by the serving application to cache the received file within the consuming application’s internal data directory. If the serving application implements its own malicious version of FileProvider, it may be able to cause the consuming application to overwrite critical files.
Share targets
In simple terms, a share target is an Android app that declares itself to handle data and files sent by other apps. Common application categories that can be share targets include mail clients, social networking apps, messaging apps, file editors, browsers, and so on. In a common scenario, when a user clicks on a file, the Android operating system triggers the share-sheet dialog asking the user to select the component that the file should be sent to: