Android’s Accessibility API offers a way for developers to build tools that help users with disabilities. The API, for example, enables apps to read the contents of the screen and perform inputs on behalf of the user, functions that are essential to screen readers and alternative input systems. These same functions also enable malware to do things like steal a 2FA code from an authenticator app or press a button in a banking app to transfer money out of a user’s account. To mitigate these kinds of attacks, Android 14 introduces a new API that lets developers limit what kinds of accessibility services can interact with their apps.
In early 2020, Dutch mobile security firm ThreatFabric spotted a version of the “Cerberus” malware strain that could steal 2FA codes from the popular authenticator app Google Authenticator. Just last month, Italian firm Cleafy identified another malware strain called “Nexus” that had the ability to snoop on 2FA codes generated by Google Authenticator. Both of these malware strains were found to abuse Android’s Accessibility API to retrieve 2FA codes in the Google Authenticator app.
Many other malware strains targeting Android have been identified over the years, and they’re commonly found to have abused the Accessibility API. That’s why Google has been cracking down on misuse of the Accessibility API for the past several years.
In Android 12, for example, the company introduced the isAccessibilityTool attribute. Only apps that are actually designed to support people with disabilities (such as screen readers) are allowed to declare that they’re an accessibility tool and be uploaded to Google Play. Accessibility tools are exempt from completing the prominent disclosure and consent requirement that Google Play requires for non-accessibility tools, ie. apps that use the Accessibility API for any purpose other than aiding people with disabilities.
In Android 13, Google made another significant change to mitigate Accessibility API abuse. The Android OS now prevents the user from easily enabling the Accessibility Service of an app that was sideloaded from outside of an app store. The OS now keeps track of how an app was installed. If it was installed using a non-session-based installation method, then it probably wasn’t installed by an app store. If it was installed by an app that uses the session-based installation method, then the app that did the installation was probably an app store. In the former case, the user is restricted from enabling the sideloaded app’s Accessibility Service, because the non-session-based method is typically invoked through users opening an APK they downloaded from the web or from within an app that has no need to implement app store-like functionality.
This new restriction made it harder for a malicious app to trick users into enabling its Accessibility Service, because the dialog gives users pause about what they’ve installed. However, the restriction wasn’t absolute. Users could manually go to a malicious app’s info page and tap “allow restricted setting” from the overflow menu, at least prior to Android 14. Malware authors could also use a dropper that implements the session-based installation API to sideload the malicious app payload that uses the Accessibility API. Once a user actually enables a malicious app’s Accessibility Service, there’s nothing stopping it from snooping on other apps or sending unwanted inputs on behalf of the user.
Starting in Android 14, though, developers can prevent non-accessibility tools from interacting with their app. By setting the new ACCESSIBILITY_DATA_PRIVATE_YES attribute on a View, only accessibility tools can interact with that View. This can be used by an app like Google Authenticator to ensure that only declared accessibility tools (like TalkBack) can read 2FA codes.
Android’s FLAG_SECURE attribute is commonly used to prevent DRM-protected content from appearing in screenshots, screen recordings, or on non-secure displays, but it does not protect against a rogue Accessibility Service, as demonstrated by researcher Yanick Fratantonio. Using his proof of concept as a basis, I created a mock authenticator app that shows a TOTP in a View without ACCESSIBILITY_DATA_PRIVATE_YES enabled, a View with FLAG_SECURE enabled, and a View with ACCESSIBILITY_DATA_PRIVATE_YES enabled. Only the View with ACCESSIBILITY_DATA_PRIVATE_YES enabled prevented the 2FA code from being leaked.
Android 14’s new ACCESSIBILITY_DATA_PRIVATE_YES attribute will be useful for apps that deal with sensitive user data like personal details or passwords or apps that want to limit fraud. Since it’s only available for apps compiled against the Android 14 SDK, however, it will take some time for it to be implemented broadly.
While there’s seemingly nothing preventing malware from falsely declaring the isAccessibilityTool attribute, in doing so they would have to implement seemingly genuine accessibility functionality for users with disabilities to make it onto Google Play. These malicious apps would then have a harder time targeting users without disabilities, however. Malware could falsely declare the isAccessibilityTool attribute in an app that appeals to those users if the malicious app is delivered outside of Google Play, but keep in mind that Android 13+ made it harder to enable a sideloaded app’s Accessibility Service.
Ultimately, this new Android 14 security feature presents just one more roadblock that malware has to overcome to harm users. Adding one more roadblock could save some users (primarily those who use trusted app stores like Google Play) from getting their data stolen.