Tapjacking
Reading time: 6 minutes
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Basic Information
Tapjacking is an attack where a malicious application is launched and positions itself on top of a victim application. Once it visibly obscures the victim app, its user interface is designed in such a way as to trick the user to interact with it, while it is passing the interaction along to the victim app.
In effect, it is blinding the user from knowing they are actually performing actions on the victim app.
Detection
In order to detect apps vulnerable to this attacked you should search for exported activities in the android manifest (note that an activity with an intent-filter is automatically exported by default). Once you have found the exported activities, check if they require any permission. This is because the malicious application will need that permission also.
You can also check the minimum SDK version of the app, checking the value of android:minSdkVersion
in the AndroidManifest.xml
file. If the value is lower than 30, the app is vulnerable to Tapjacking.
Protection
Android 12 (API 31,32) and higher
According to this source, tapjacking attacks are automatically prevented by Android from Android 12 (API 31 & 30) and higher. So, even if the application is vulnerable you won't be able to exploit it.
filterTouchesWhenObscured
If android:filterTouchesWhenObscured
is set to true
, the View
will not receive touches whenever view's window is obscured by another visible window.
setFilterTouchesWhenObscured
The attribute setFilterTouchesWhenObscured
set to true can also prevent the exploitation of this vulnerability if the Android version is lower.
If set to true
, for example, a button can be automatically disabled if it is obscured:
<Button android:text="Button"
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:filterTouchesWhenObscured="true">
</Button>
Exploitation
Tapjacking-ExportedActivity
The most recent Android application performing a Tapjacking attack (+ invoking before an exported activity of the attacked application) can be found in: https://github.com/carlospolop/Tapjacking-ExportedActivity.
Follow the README instructions to use it.
FloatingWindowApp
An example project implementing FloatingWindowApp, which can be used to put on top of other activities to perform a clickjacking attack, can be found in FloatingWindowApp (a bit old, good luck building the apk).
Qark
caution
It looks like this project is now unmaintained and this functionality isn't properly working anymore
You can use qark with the --exploit-apk
--sdk-path /Users/username/Library/Android/sdk
parameters to create a malicious application to test for possible Tapjacking vulnerabilities.\
The mitigation is relatively simple as the developer may choose not to receive touch events when a view is covered by another. Using the Android Developer’s Reference:
Sometimes it is essential that an application be able to verify that an action is being performed with the full knowledge and consent of the user, such as granting a permission request, making a purchase or clicking on an advertisement. Unfortunately, a malicious application could try to spoof the user into performing these actions, unaware, by concealing the intended purpose of the view. As a remedy, the framework offers a touch filtering mechanism that can be used to improve the security of views that provide access to sensitive functionality.
To enable touch filtering, call
setFilterTouchesWhenObscured(boolean)
or set the android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework will discard touches that are received whenever the view's window is obscured by another visible window. As a result, the view will not receive touches whenever a toast, dialog or other window appears above the view's window.
Accessibility Overlay Phishing (Banking-Trojan Variant)
Besides classic Tapjacking, modern Android banking malware families (e.g. ToxicPanda, BrasDex, Sova, etc.) abuse the Accessibility Service to place a full-screen WebView overlay above the legitimate application while still being able to forward the user input to the view underneath. This dramatically increases believability and allows attackers to steal credentials, OTPs or even automate fraudulent transactions.
How it works
- The malicious APK requests the highly-sensitive
BIND_ACCESSIBILITY_SERVICE
permission, usually hiding the request behind a fake Google/Chrome/PDF-viewer dialog. - Once the user enables the service, the malware programmatically simulates the taps required to grant additional dangerous permissions (
READ_SMS
,SYSTEM_ALERT_WINDOW
,REQUEST_INSTALL_PACKAGES
, …). - A WebView is inflated and added to the window manager using the
TYPE_ACCESSIBILITY_OVERLAY
window type. The overlay can be rendered totally opaque or semi-transparent and can be flagged as “through” so that the original touches are still delivered to the background activity (thus the transaction really happens while the victim only sees the phishing form).
WebView phishingView = new WebView(getApplicationContext());
phishingView.getSettings().setJavaScriptEnabled(true);
phishingView.loadUrl("file:///android_asset/bank_login.html");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY, // <-- bypasses SYSTEM_ALERT_WINDOW prompt
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, // «through» flag → forward touches
PixelFormat.TRANSLUCENT);
wm.addView(phishingView, lp);
Typical workflow used by banking Trojans
- Query installed packages (
QUERY_ALL_PACKAGES
) to figure out which banking / wallet app is currently opened. - Download an HTML/JS overlay template from the C2 that perfectly imitates that specific application (Logo, colours, i18n strings…).
- Display the overlay, harvest credentials/PIN/pattern.
- Use the Accessibility API (
performGlobalAction
,GestureDescription
) to automate transfers in the background.
Detection & Mitigation
- Audit the list of installed apps with
adb shell pm list packages -3 -e BIND_ACCESSIBILITY_SERVICE
. - From the application side (bank / wallet):
- Enable
android:accessibilityDataSensitive="accessibilityDataPrivateYes"
(Android 14+) on sensitive views to block non-Play-Store services. - Combine with
setFilterTouchesWhenObscured(true)
andFLAG_SECURE
.
- Enable
- System hardening:
- Disable Install from Unknown Sources & Accessibility for untrusted apps.
- Enforce PlayProtect & up-to-date devices.
For additional details on leveraging Accessibility Services for full remote device control (e.g. PlayPraetor, SpyNote, etc.) see:
References
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.