Microsoft discovered a high-severity vulnerability in the TikTok Android application, which could have allowed attackers to compromise users’ accounts with a single click. The vulnerability, which would have required several issues to be chained together to exploit, has been fixed and we did not locate any evidence of in-the-wild exploitation. Attackers could have leveraged the vulnerability to hijack an account without users’ awareness if a targeted user simply clicked a specially crafted link. Attackers could have then accessed and modified users’ TikTok profiles and sensitive information, such as by publicizing private videos, sending messages, and uploading videos on behalf of users.
The vulnerability allowed the app’s deeplink verification to be bypassed. Attackers could force the app to load an arbitrary URL to the app’s WebView, allowing the URL to then access the WebView’s attached JavaScript bridges and grant functionality to attackers. We’ve previously researched JavaScript bridges for their potential wide-reaching implications. Emphasizing the importance of exercising caution when clicking unknown links, this research also displays how collaboration within the security community is necessary to improve defenses for the overall digital ecosystem.
TikTok has two flavors of its Android app: one for East and Southeast Asia under the package name com.ss.android.ugc.trill, and another for the remaining countries under the package name com.zhiliaoapp.musically. Performing a vulnerability assessment of TikTok, we determined that the issues were affecting both flavors of the app for Android, which have over 1.5 billion installations combined via the Google Play Store. After carefully reviewing the implications, a Microsoft security researcher notified TikTok of the issues in February 2022, as part of our responsible disclosure policy through Coordinated Vulnerability Disclosure (CVD) via Microsoft Security Vulnerability Research (MSVR). TikTok quickly responded by releasing a fix to address the reported vulnerability, now identified as CVE-2022-28799, and users can refer to the CVE entry for more information. We commend the efficient and professional resolution from the TikTok security team. TikTok users are encouraged to ensure they’re using the latest version of the app.
In this blog post, we share information on the issues we discovered, examine how they could have been leveraged in an attack to quickly and quietly take over targeted users’ accounts, and walk-through best practices and protections. As threats across platforms continue to grow, we also share details of our research, disclosure, and collaboration with the larger security community in the effort to continually improve security for all, regardless of the platform or device in use.
JavaScript interfaces
Exploitation of the vulnerability relies on the app’s implementation of JavaScript interfaces, which are provided by a component of the Android operating system called WebView. WebView allows applications to load and display web pages and, using the addJavascriptInterface API call, can also provide bridge functionality that allows JavaScript code in the web page to invoke specific Java methods of a particular class in the app. Loading untrusted web content to WebView with application-level objects accessible via JavaScript code renders the application vulnerable to JavaScript interface injection, which may lead to data leakage, data corruption, or, in some cases, arbitrary code execution.
In our example, the code below demonstrates how a JavaScript interface is used, an instance of the JsObject class is injected into WebView (line 8) and it is referenced by the injectObject variable within the JavaScript code, which is loaded via the loadUrl API method (line 10):
Prior to Android API level 18 (released in 2013 with Android 4.3), any method of the injected class was exposed to this JavaScript code. From API level 18 onwards, only class methods with the “@JavascriptInterface” annotation can be invoked (depicted above in line 2).
JavaScript bridge
TikTok for Android uses JavaScript interfaces extensively, enhancing WebView capabilities that are used within the app. We identified a class of interest that makes use of such a WebView. It registers a JavaScript bridge that has access to every type of functionality implemented by the classes of the [redacted].bridge.* package. This bridge exposes the method depicted below:
The arg1 corresponds to a JSON string that consists of several attributes, with the func and params attributes as the most relevant.
The func attribute corresponds to the name of the Java method that is invoked from the JavaScript code, while the params attribute sets arguments that this method takes. For example, to call the Java method with signature String foo(String arg1, String arg2) from the JavaScript code, the following statement must be used:
The result is returned as a JSON string to a callback defined in the JavaScript code, which takes a single string as an argument.
The above figure visualizes the concept and depicts the following steps:
The application loads the website example.com to its WebView
The JavaScript code, which is fetched from the remote server, invokes the Java method
The method is executed
The result is returned as a parameter to the callback function
Finally, the handler method can process the result locally or send it to an external server using an XMLHttpRequest, a built-in browser object that can also be leveraged during an attack to send stolen data to an attacker’s server.
Diving into deeplinks
The vulnerability itself was ultimately found to reside in the app’s handling of a particular deeplink. In the context of the Android operating system, a deeplink is a special hyperlink that links to a specific component within a mobile app and consists of a scheme and (usually) a host part. When a deeplink is clicked, the Android package manager queries all the installed applications to see which one can handle the deeplink and then routes it to the component declared as its handler. A deeplink must be declared in the application’s manifest to be used by components outside of the application’s context:
In the example above in Figure 5,
The user clicks the link http://www.example[.]com/gizmos. Since more than one application can handle the scheme, the system then presents a dialog box, also known as ambiguity dialog, similar to the one depicted below in Figure 6.
A deeplink in the form of example://gizmos is routed directly to the activity GizmosActivity, the component declared as the deeplink handler in this case.
To avoid the ambiguity dialog for http and https schemes, an application may declare an Android App Link by using the autoVerify attribute in its intent filter to signal the system to verify the association between the app and the declared URL domain. Additionally, a JSON file that contains the application’s package name and its certificate’s SHA256 fingerprint must be published under https://domain.name/.well-known/directory. TikTok for Android uses this feature for the domain m.tiktok.com, meaning all the links matching to the specific domain will be routed to the application without presenting the ambiguity dialog.
Besides deeplinks that are exported in the Android manifest, an application can also exchange data between its components using internal deeplinks. Trying to open an internal deeplink from outside the application, like in a web browser, will return an “unable to resolve Intent” error message as the system can’t route it to the appropriate handler.
Vulnerability findings
It’s important to understand the various components at play that allow the vulnerability to be exploited, such as the app’s implementation of JavaScript interfaces, since they determine the impact of the vulnerability itself. While reviewing the app’s handling of a specific deeplink, we discovered several issues that, when chained together, could have been used to force the application to load an arbitrary URL to the application’s WebView. By crafting this URL with additional query parameters, it was possible to inject an instance of the JavaScript bridge that provides full access to the functionality implemented by the [redacted].bridge.* package.
What follows is a technical description of the vulnerability, which we analyzed using the TikTok Android application with the package name com.zhiliaoapp.musically. The same description applies for the TikTok Android application com.ss.android.ugc.trill, as the vulnerabilities were found in common SDKs.
Triggering the app’s internal deeplinks
TikTok for Android uses multiple deeplink schemes, some of which are exported via the manifest, while some are used only internally by the application. Among the exported ones, the https://m.tiktok[.]com/redirect link is handled by the [redacted] class and is used to redirect URIs to various components of the application via a query parameter:
We determined that it’s possible to trigger internal deeplinks via the query parameter and call non-exported activities, expanding the attack surface of the application. According to TikTok, this redirection to internal deeplinks doesn’t raise any additional concerns.
As a proof of concept, we crafted a URL that uses a particular non-exported scheme to load https://www.tiktok[.]com to the application’s WebView, as displayed below in Figure 8:
Although the [redacted-internal-scheme]://webview?url=<website> deeplink can be used to load URLs to the CrossPlatformActivity’s WebView via a query parameter, the application imposes filters to reject untrusted hosts. In contrast to the Tiktok.com domain successfully loading, as shown in Figure 8 above, Figure 9 below displays the domain Example.com being rejected by the application filters:
The filtering takes place on the server-side and the decision to load or reject a URL is based on the reply received from a particular HTTP GET request. Our static analysis indicated that it is possible to bypass the server-side check by adding two additional parameters to the deeplink.
The WebView attached to the activity creates instances of the JavaScript bridge, which we verified dynamically using Medusa’s WebView module. From this point on, the website assigned to the query parameter of the [redacted-scheme]://webview scheme has full access to the JavaScript bridge, meaning the website’s JavaScript code can now access and invoke any exposed functionality found under the [redacted].bridge.* package.
Exposed functionality
Reviewing the functionality accessible to the JavaScript code in web pages loaded to WebView, we identified more than 70 exposed methods. When paired with an exploit to hijack WebView, such as the vulnerability we discovered, these methods can be invoked to grant functionality to attackers. Some of the exposed methods can access or modify users’ private information, while others can perform authenticated HTTP requests to any URL given as a parameter. Moreover, the method accepts a set of parameters in the form of a JSON string that can be used to form the body of a POST request and returns the server’s reply, including the headers.
By invoking such methods, an attacker can:
Retrieve the user’s authentication tokens by triggering a request to a controlled server and logging the cookie and the request headers.
Retrieve or modify the user’s TikTok account data, such as private videos and profile settings, by triggering a request to a TikTok endpoint and retrieving the reply via the JavaScript callback.
In short, by controlling any of the methods able to perform authenticated HTTP requests, a malicious actor could have compromised a TikTok user account.
Proof of concept
In the following proof of concept, the attacker sends a crafted link to a targeted TikTok user. Once the user clicks the link, the video uploading authentication tokens are sent back to the attacker and, subsequently, the script modifies the user’s biography information to read “!! SECURITY BREACH !!”:
Once the attacker’s specially crafted malicious link is clicked by the targeted TikTok user, the attacker’s server, https://www.attacker[.]com/poc, is granted full access to the JavaScript bridge and can invoke any exposed functionality. The attacker’s server returns an HTML page containing JavaScript code to send video upload tokens back to the attacker as well as change the user’s profile biography.
The video uploading authentication tokens are sent back to the attacker via an XMLHttpRequest. The attacker also receives the reply body and the header, depicted in Figure 10 and 11 below:
Finally, the message “!! SECURITY BREACH !!!” is set in the user profile’s biography:
JavaScript interface best practices
As this case and our prior research has shown, from a programming perspective, using JavaScript interfaces poses significant risks. A compromised JavaScript interface can potentially allow attackers to execute code using the application’s ID and privileges. Thus, we recommend that the developer community be aware of the risks and take extra precautions to secure WebView.
In cases where using JavaScript interfaces cannot be avoided, we suggest using an approved list of trusted domains to be loaded to the application’s WebView to prevent loading malicious or untrusted web content. Additionally, we suggest the following secure coding practices:
Use the default browser to open URLs that don’t belong to the application’s approved list.
Keep the approved list up to date and track the expiration dates of the included domains. This can prevent attackers from hijacking WebView by claiming an expired domain on the approved list.
Avoid using partial string comparison methods to compare and verify a URL with the approved list of trusted domains.
Avoid adding stage or internal network domains to the approved list as these domains could be spoofed by an attacker to hijack WebView.
Responsible disclosure and industry collaboration improves security for all
Leveraging new threats, techniques, and attacker capabilities, adversaries continue to focus on identifying and taking advantage of unpatched vulnerabilities and misconfigurations as a vector to access systems and sensitive information for malicious purposes. Responding to the changing threat landscape requires us to expand our knowledge and expertise into other devices and platforms as part of our commitment to continuously improve security from Microsoft, not just for Microsoft.
We use collaborative research such as this to improve our protection technologies across platforms, ensuring Microsoft Defender Vulnerability Management detects and alerts on installed applications with known vulnerabilities—including those affecting non-Windows devices. While we’re not aware of any active exploitation of this vulnerability in the wild, users can further follow the security guidelines below to defend against this and similar types of issues:
Avoid clicking links from untrusted sources
Always keep the device and the installed applications updated
Never install applications from untrusted sources
Immediately report any strange application behavior to the vendor, such as setting changes triggered without user interaction.
This case displays how the ability to coordinate research and threat intelligence sharing via expert, cross-industry collaboration is necessary to effectively mitigate issues. As threats across platforms continue to grow in numbers and sophistication, vulnerability disclosures, coordinated response, and other forms of threat intelligence sharing are needed to help secure users’ computing experience, regardless of the platform or device in use. We will continue to work with the larger security community to share research and intelligence about threats in the effort to build better protection for all.
Dimitrios Valsamaras Microsoft 365 Defender Research Team
Microsoft researchers found multiple vulnerabilities in OpenVPN that could lead to an attack chain allowing remote code execution and local privilege escalation. This attack chain could enable attackers to gain full control over targeted endpoints, potentially resulting in data breaches, system compromise, and unauthorized access to sensitive information.
Microsoft discovered a vulnerability pattern in multiple popular Android applications that could enable a malicious application to overwrite files in the vulnerable application’s internal data storage directory, which could lead to arbitrary code execution and token theft, among other impacts. We have shared our findings with Google’s Android Application Security Research team, as well as the developers of apps found vulnerable to this issue. We anticipate that the vulnerability pattern could be found in other applications. We’re sharing this research more broadly so developers and publishers can check their apps for similar issues, fix as appropriate, and prevent them from being introduced into new apps or releases.
Microsoft has observed ongoing activity from mobile banking trojan campaigns targeting users in India with social media messages and malicious applications designed to impersonate legitimate organizations and steal users’ information for financial fraud scams.
Microsoft discovered that the SHEIN Android application periodically read the contents of the Android device clipboard and, if a particular pattern was present, sent the contents of the clipboard to a remote server.