Tapjacking Protection
Tapjacking is a security issue that occurs when the app screen is completely or partially obscured by an overlay window. The user can be tricked into thinking that they are interacting with the overlay. However, their input (a tap) can instead perform actions in the underlying app.
Malwarelytics for Android tries to prevent tapjacking. This is done by preventing click events when a part of the app screen is obscured by an overlay and at least one app that can create such overlays is deemed “problematic”.
Tapjacking protection sensitivity is configurable in the SDK.
Limitations
Identifying Tapjacking Culprit
Android APIs prevent an app from determining specifically which other app is creating an overlay; it is only possible to obtain a list of apps that are capable of doing so. Utilizing data obtained by Anti-Malware feature tapjacking protection can identify which of these apps are indeed “problematic”.
Tapjacking protection sensitivity is ignored when the Anti-Malware feature is disabled in AntivirusConfig
. As a result, the SDK cannot distinguish which apps are problematic and all apps capable of creating overlays are marked as “problematic”. In such scenarios, it’s not recommended to use tapjacking protection because of the significant risk of false positives.
Protecting Dialogs
Tapjacking protection doesn’t work on dialogs because the contents of a dialog receive taps through an overlay regardless of the way the dialog is created.
Configuration
This feature can be configured during the Malwarelytics initialization phase:
val raspConfig = RaspConfig.Builder()
.tapjacking(
TapjackingBlockConfig.Builder()
.action(BlockConfig)
.ignoreTapjackingSystemApps(Boolean)
.blockTapjackingSensitivity(ThreatIndex)
.allowedTapjackingApps(Collection<RaspConfig.ApkAllowlistItem>)
.build()
)
// configuration of other RASP features
.build()
Method | Description |
---|---|
action(BlockConfig) |
specifies the automatic behavior of the tapjacking protection feature. Defaults to BlockConfig.Block . However, tapjacking is not blocked unless a “problematic” app is installed on the device. An app is deemed “problematic” when it meets sensitivity criteria defined by blockTapjackingSensitivity . |
ignoreTapjackingSystemApps(Boolean) |
indicates whether tapjacking protection should ignore system apps in the checks. Defaults to false . If set to true all system apps will be ignored and tapjacking will get blocked only if a non-system “problematic” app is present. |
blockTapjackingSensitivity(ThreatIndex) |
defines tapjacking protection sensitivity. Defaults to ThreatIndex.HIGHLY_DANGEROUS . |
allowedTapjackingApps(Collection<RaspConfig.ApkAllowlistItem>) |
defines a collection of allowed app capable of tapjacking. It is empty by default. |
Available values of BlockConfig
:
Value | Description |
---|---|
NoAction |
indicates that tapjacking will not be automatically blocked. A manual check for tapjacking apps is still possible. |
Block |
indicates that tapjacking will be automatically blocked. |
Usage
After initialization, the tapjacking protection feature can be accessed via RaspManager
. This can be used to register an observer or to trigger a manual tapjacking detection check.
Registering an Observer
Tapjacking detection can trigger a certain action. To achieve that, an observer needs to be configured and registered.
Observer configuration:
val raspObserver = object : RaspObserver {
override fun onTapjackingDetected(tapjackingDetection: TapjackingDetection) {
// handle tapjacking detection
}
// handle detection of other RASP features
}
The observer can be registered in RaspManager
. When it is no longer needed, it can be unregistered again.
raspManager.registerRaspObserver(raspObserver)
raspManager.unregisterRaspObserver(raspObserver)
Triggering a Manual Check
Tapjacking detection check can be triggered manually in RaspManager
. Two methods are available. isBadTapjackingCapableAppPresent()
indicates whether any apps deemed “problematic” are installed on the device. getTapjackingDetection()
provides more details about tapjacking protection configuration. The returned data depends on the configuration - both on the sensitivity and on ignoring system apps.
val isBadTapjackingCapableAppPresent = raspManager.isBadTapjackingCapableAppPresent()
val tapjackingDetection = raspManager.getTapjackingDetection()
Tapjacking protection feature is applied to the app’s activities. Details about behavior and APIs relevant to activity protection can be found in Activity protection.
Troubleshooting for App Developers
In case a tapjacking-capable app is frequently used by the app’s userbase and its threat index triggers the protection (the threat index is higher than tapjacking protection sensitivity) it can be ignored by configuring raspConfig.allowedTapjackingApps(Collection<RaspConfig.ApkAllowlistItem>)
.
Allowed tapjacking apps can be specified either by their package name and signature or by their package name only. However, the former is recommended to avoid allowing fake (and often malicious) apps.
Obtaining Package Name
Obtaining the app package name is simple – it is listed as a query param id
in the URL of the app page on Google Play. For example, the package name of the Android Accessibility Suite is com.google.android.marvin.talkback
as can be seen in this Google Play URL: https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback.
Obtaining App Signature
Obtaining the correct app signature is more complicated because a signed APK is necessary. Installing the app from Google Play is recommended. Next, the APK must be pulled from the device.
Find the APK location on the device:
adb shell pm list packages -f | grep "$PACKAGE$" | sed "s/package://" | sed "s/=$PACKAGE//"
Pull the APK from the device:
adb pull "$APK_LOCATION"
Obtain the signature hash in the right format:
apksigner verify --print-certs ${SOME_APK} | grep "SHA-1" | sed "s/.*: //"
The result is the app signature that can be used as the second argument for RaspConfig.ApkAllowlistItem(String, String)
.
Troubleshooting for Users
The SDK tries to simplify a potential troubleshooting process as much as possible. The app developer is provided with a list of “problematic” apps triggering the protection. Furthermore, the SDK offers a utility method that opens the system settings responsible for granting/removing the system overlay permission for installed apps:
RaspUtilities.openSystemOverlaySettings(Context)
The device user can then adjust the settings to make the app respond to clicks again.
More information on general RASP feature configuration and usage can be found in this overview.