Vulnerability in TikTok Android app could lead to one-click account hijacking

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):

Code depicting adding a JavaScript interface to a WebView object
Figure 1. Adding a JavaScript interface to a WebView object

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:

Code depicting rendering the method callable via the JavaScript code
Figure 2. Rendering the method callable via the JavaScript code

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:

Code depicting a Java method being invoked via the JavaScript interface
Figure 3. Example code invoking a Java method via the JavaScript interface.

The result is returned as a JSON string to a callback defined in the JavaScript code, which takes a single string as an argument.

Diagram depicting the interaction between Java and web components using the JavaScript interface, further detailed in the text below.
Figure 4. Interaction between Java and web components using the JavaScript interface

The above figure visualizes the concept and depicts the following steps:

  1. The application loads the website example.com to its WebView
  2. The JavaScript code, which is fetched from the remote server, invokes the Java method
  3. The method is executed
  4. 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:

Code depicting an example of adding an intent filter in the app's manifest for deep linking
Figure 5. An example of adding an intent filter in the app’s manifest for deep linking.

In the example above in Figure 5,

  1. 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.
  1. 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.
Image of an ambiguation dialog requesting the user to complete the action using either the Chrome browser or an Android app called DeepLinkingExample. It also prompts the user to select whether it should complete the action with the selected application just once or every time.
Figure 6. Ambiguity dialog

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:

Code depicting how to identify deeplinks and their targeted activities using the linked Medusa tool.
Figure 7. Identifying deeplinks and their targeted activities using Medusa

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:   

An image of the TikTok application's WebView successfully loading Tiktok.com. The WebView displays a prompt to Accept all or Decline all cookies from TikTok on this browser, while the app's display has been redacted for privacy.
Figure 8. Using a link to trigger an internally used scheme and load Tiktok.com.

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:

An image of the TikTok app's WebView trying to load Example.com with an error that states: "https://www.example.com This link may be unsafe. To protect our community, we restrict certain content on our platform" followed by a button for the user to go back
Figure 9. The application’s filters rejecting the [redacted-internal-scheme]://webview?url=https://www.example[.]com deeplink

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:

Code depicting the request headers retrieved by the attack
Figure 10. The request headers retrieved by the attack
Code depicting the server's reply including the headers
Figure 11. The server’s reply including the headers

Finally, the message “!! SECURITY BREACH !!!” is set in the user profile’s biography:

An image of a TikTok user's profile with the biography information reading "!! SECURITY BREACH !!!"
Figure 12. Compromising the user’s profile integrity

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.

As part of our responsible disclosure policy through Coordinated Vulnerability Disclosure (CVD) via Microsoft Security Vulnerability Research (MSVR), we disclosed the vulnerability to TikTok in February 2022 as directed on its website. The vulnerability, CVE-2022-28799, was quickly rated as high severity with a score of 8.3, and a fix for the issue was included in an updated version of the app released less than a month after the initial disclosure. We wish to thank the TikTok security team for collaborating quickly and efficiently in resolving these issues.

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

References

READ MORE HERE