Closed Bug 1928334 (CVE-2025-1939) Opened 1 year ago Closed 11 months ago

Animation-based tapjacking on Custom Tabs

Categories

(Firefox for Android :: General, defect, P2)

Firefox 131
All
Android
defect

Tracking

()

RESOLVED FIXED
Tracking Status
firefox135 --- wontfix
firefox136 + fixed
firefox137 + fixed

People

(Reporter: philipp.beer, Assigned: boek)

References

Details

(Keywords: csectype-clickjacking, reporter-external, sec-high, Whiteboard: [fxdroid][group1][adv-main136+])

Attachments

(5 files)

Steps to reproduce:

Attack Summary

We discovered a vulnerability in which an Android app without any permissions can exploit animations and launch a Firefox Custom Tab (CT) to bypass permission checks on websites and perform clickjacking attacks against arbitrary websites.

Primitives

Android applications can use Custom Tabs (CT) to open web content with minimal context switching, as Custom Tab Activities are launched within the same task as the requesting application. Through the ActivityOptions.makeCustomAnimation method, Android also allows applications to specify custom enter and exit animations for cross-activity and same-task transitions, such as the transition between an app and a Firefox CT.

An application installed on the user's device can exploit this functionality by launching a Custom Tab and setting an enter animation with a long fade-in duration, set to low opacity. This transition brings the Custom Tab to the foreground yet keeps it invisible to the user while the animation completes since the CT is basically transparent (e.g., opacity=0.0005). As the CT Activity is on top of the stack, and Firefox does not wait for animations to be finished before handling touches, screen interactions are handled by the browser.

The following minimum working example demonstrates this exploit, assuming Firefox is the default browser:

MainActivity.kt

val builder = CustomTabsIntent.Builder()
// setStartAnimation internally uses ActivityOptions#makeCustomAnimation
builder.setStartAnimations(this, R.anim.fade_in, R.anim.fade_out) 
val customTabsIntent = builder.build()
customTabsIntent.launchUrl(this, victimUrl)

res/anim/fade_in.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Long-running animation with low opacity -->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0.0"
    android:toAlpha="0.0005"
    android:duration="20000"/>

res/anim/fade_out.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- This boils down to no animation, as duration = 0 -->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1.0"
    android:toAlpha="1.0"
    android:duration="0" />

This report is part of a coordinated responsible disclosure on the underlying animation-based tapjacking vulnerability that we discovered on Android.

Impact

The vulnerability opens doors for the following Web-specific issues:

  1. Permission Bypass

By launching a CT with this technique, an application can open an attacker-controlled website that requests sensitive permissions, such as microphone or camera access. By luring the user to tap a button that is positioned at the same location as the allow button in the permission prompt, the permission is granted to the website without user awareness. Since CT permissions are shared with Firefox, any permissions granted in this way go beyond the CT, granting persistence to the attacker in the victim's browser.

  1. Web Clickjacking Attacks

An app can secretly request a website, i.e, a checkout page of an online store, and lure the user into performing critical actions, such as clicking the 'buy' button. Existing standard web-based clickjacking peventions, such as the Content Security Policy frame-ancesters directive and the X-Frame-Options headers do not apply here and do not mitigate these attacks.

Practicality of the Attack

A slow fade-in transition would reveal the Firefox window after a few seconds, but an app can re-launch its own activity before the animation ends to effectively hide the Custom Tab. A delay of 2500ms between starting the CT and re-launching the activity of the app is effective according to our experiments. This means that the permission prompt is clickable for 2.5s. Although this is a rather short time frame for user interaction, attack scenarios like games, where users are prompted to tap quickly, make this attack practical.

Actual results:

Touches while the animation is running and the Firefox activity is essentially invisible are handled by Firefox.

We created a proof of concept application that demonstrates how to bypass the Firefox permission prompt via tapjacking. Additionally, we attached a video demonstrating the attack.

Notice that the button positioning is manually adjusted for a Pixel 6a and might require some tweaking to generalize to different devices.
The application opens https://webrtc.github.io/test-pages/src/iframe-video/, which immediately on load requests for the camera permission.

To replicate the permission tapjacking, follow these steps:

  • Grant Firefox permission to access the user's camera
  • Install the PoC application (find the source code here)
  • Click "Choose browser" and choose Firefox
  • Click "open com.org.mozilla.firefox"
  • Click on the redd buttons when they appear (the first button is positioned so that the user clicks the "remember the decision" checkbox, the second to allow the permission)
  • The site is now allowed to access the camera

Expected results:

Touches should be ignored during enter animations.

The source of this vulnerability is twofold: (1) Firefox does not wait for animations to be finished until it handles touches, and (2) Android allows long-running animations with low opacity.

To offer mitigations to protect users until (2) is fixed on the system level, we propose to also fix (1) and mitigate this issue at the browser level. Firefox can ignore all touch events until the onEnterAnimationComplete lifecycle method is called. This method is triggered once the enter animations are complete, thereby protecting against animation-based tapjacking.

Severity: -- → S3
Priority: -- → P3
Priority: P3 → P2

Hi, we have also responsibly disclosed this issue with the Android Security Team (issue 376620895) as well as the following other affected browser vendors:

  • Chrome (issue 1928334)
  • Brave (issue 2813717)
  • Edge (issue VULN-137894)

Best,
Philipp

Could you provide a link to the Chrome issue? That is too short a number for their current bug tracker, and the redirector for links to their old URLs says that's not a migrated issue. Or is it a number received from some other communication path with them? We know we won't be able to see their hidden bugs, but it's useful to have the reference in case we need to ask them about it.

Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(philipp.beer)

Since this requires installing a malicious app perhaps sec-high is overstating it? But "sec-moderate" wouldn't convey the near-high severity of it.

Hi, here is the correct Chrome issue: https://issues.chromium.org/issues/376491759

Flags: needinfo?(philipp.beer)

The severity field for this bug is set to S3. However, the bug is flagged with the sec-high keyword.
:boek, could you consider increasing the severity of this security bug?

For more information, please visit BugBot documentation.

Flags: needinfo?(jboek)
Flags: needinfo?(jboek)
Severity: S3 → S2

Hey Jeff, this is a sec-high one - would you please add this to your queue?

Whiteboard: [fxdroid][group1]

Dear Firefox Security Team,

I’d like to provide an update from our side. We are in the process of publishing our findings and evaluation of the Android Tapjacking vulnerability at the USENIX Security Symposium 2025. While the paper does not focus directly on Firefox, it discusses the broader impact of this vulnerability on the Web ecosystem as well, including Firefox.

The paper is currently under review. If accepted, it will be published in June 2025 and presented at the conference in August 2025.

Additionally, I'd like to give you an update from the Chrome side. Chrome has recently implemented mitigations for this issue by blocking touches until the onEnterAnimationComplete function is called (see https://chromium-review.googlesource.com/c/chromium/src/+/6244912 (public) and https://issuetracker.google.com/issues/376491759 (restricted)).

Best,
Philipp

Attached file Sec Approval Request

[Security approval request comment]
How easily could an exploit be constructed based on the patch?
The patch clearly points to the potential of a tap jacking exploit.

Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?
All versions of Firefox for Android are affected.

Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be?
No backports have been created. The patch should uplift cleanly. If fix is verified in Nightly risk should be low.

How likely is this patch to cause regressions; how much testing does it need?
Unlikely, but not impossible. Should continue to try to intentionally break it.

Is the patch ready to land after security approval is given?
Yes.

Attachment #9466902 - Flags: sec-approval?
Assignee: nobody → jboek

Comment on attachment 9466902 [details]
Sec Approval Request

Approved to land and request uplift.

(It's generally easier to flag the actual patch for sec-approval rather than adding a new attachment, but no worries.)

Attachment #9466902 - Flags: sec-approval? → sec-approval+
Attachment #9467249 - Flags: approval-mozilla-beta?

beta Uplift Approval Request

  • User impact if declined: Vulnerability will exist in 136
  • Code covered by automated testing: yes
  • Fix verified in Nightly: no
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing: steps can be found in the originating bug
  • Risk associated with taking this patch: Low - Untested changes
  • Explanation of risk level: The changes arent under unit test, but UI tests should catch any potential regressions
  • String changes made/needed: none
  • Is Android affected?: yes

:boek a reminder this needs to land in autoland today

Flags: needinfo?(jboek)
Pushed by jboek@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/19a8b589de11 Handles animating activities r=android-reviewers,matt-tighe
Flags: needinfo?(jboek)
Attachment #9467249 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Group: mobile-core-security → core-security-release
Whiteboard: [fxdroid][group1] → [fxdroid][group1][adv-main136+]
Attached file advisory.txt
Alias: CVE-2025-1939
Regressions: 1966095
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: