March 21, 2023

    Protecting Against Android Accessibility Services Threats

    The Accessibility Service on Android is a powerful feature that allows users with disabilities to interact with their devices in new ways. It reads text aloud, fills in forms, and clicks buttons for the user. However, this functionality also comes with potential security risks, as the accessibility service can be abused to steal sensitive data or control the device.

    This misconduct happened a lot in recent years and left thousands of victims with empty bank accounts. For example, in Brazil in 2022, a malware called BrasDex targeted mobile banking apps with fast payment to steal money. Then, Xenomorph malware hit the authenticator apps to extract user credentials. Both were using an accessibility service as their main attack vector. Let’s describe what an accessibility service is and how you can protect your app against it.

    Learn how to defend against malware in our Mobile Application Security Research Center >

    Accessibility service

    An accessibility service is just another app but it runs in the background instead of the foreground as usual. Every time you interact with the UI, the background service receives the current content of your screen. For example, the screenshot below shows logs of an accessibility service inspecting a banking app.

    Protecting-Against-Android-Accessibility-Services-Threats-01

    Given the amount of confidential data an accessibility service has access to, a user must trust that the developer won’t misuse this data. Many accessibility service providers are indeed genuine but let’s not forget that anyone can upload an app to the Google Play Store. These malicious apps often pretend to be generic apps such as memory cleaners, torches, and calculators.

    The accessibility service has one more alarming feature. It can simulate clicking on the buttons. Combined with its reading capabilities, this is a perfect tool to perform stealthy operations, such as transferring money or confirming an OTP token on behalf of the user. Below you can see a simulation of this attack on a banking app.

    The Accessibility Service is able to access your passcode by constantly monitoring your activity within the app, including the buttons you press to enter the passcode. Once you have entered your passcode, the service is able to store it for future use.

    Protections - DIY

    Detect an active accessibility service

    With just a simple code snippet, your app can easily detect if there are any active accessibility services currently running. You can use this technique to limit the functionality of your app if any accessibility service is present. We have encountered some mobile app protection vendors claiming to provide paid features to protect against malware, but in reality, they are implementing simple checks like the one below, without clearly communicating the tradeoffs.

    static boolean isAccessibilityEnabled(Context ctx) {
      AccessibilityManager am = ((AccessibilityManager) ctx.getSystemService(Context.ACCESSIBILITY_SERVICE));
      return am.isEnabled();
    }
    

    In many cases, blocking access to accessibility services may not be desirable, breaking the accessibility of your app can impact the UX of your app and sometimes go against regulations or legal requirements to provide accessibility. Before taking such an aggressive stance against accessibility services, you should familiarize yourself with your legal requirements. An alternative approach would be to define a predetermined list of allowed accessibility services using the package name, though the question becomes, which accessibility services should be permitted? The code snippet below demonstrates how this can be implemented.

     static boolean isAccessibilityServiceAllowed(Context context) {
      List<String> allowedServices = Arrays.asList("com.mytrusted.assistant", "com.trusted.package");
      AccessibilityManager am =(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
      List<AccessibilityServiceInfo> services = am.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK);
      for (AccessibilityServiceInfo asi : services) {
         if (!allowedServices.contains(asi.getId()))
            return false;
         }
      return true;
    }

    If you need even more fine-grained control, a robust strategy would be to validate these services at the server-side and limit functionality or simply identify users who may be impacted by vulnerable use of accessibility services.

    Android 14 - hope on the horizon, kind of

    In Android 14, Google introduced the accessibilityDataSensitive property for Views. Any View with this property is visible only to the services that complete the Permission Declaration Form by Google. This is a good solution, but of course relies on restricting access to your app to >Android 14 which will take some time to be mainstream, so an interim approach will still be needed to cater to the majority of older devices.

    <TextView
       accessibilityDataSensitive="yes"
       android:text="Your PIN number is 1234" />

    Related threats

    The Overlay Service is a feature that is frequently exploited by malicious apps, similar to the Accessibility Service. This service allows an app to overlay its views over other app views. It is commonly used in tapjacking attacks to deceive users into granting access to the accessibility service. However, it can also be used to alter the screen content in a way that the user is unaware of, such as modifying the destination bank number or prompting the user to enter login credentials into a fake overlay instead of the legitimate app.

    Secure architecture

    While detecting a threat can be a simple and direct solution, implementing a robust security architecture can eradicate the threat at its core.

    Use Keystore with biometrics

    During crucial stages such as confirming a bank transfer, it is recommended to use biometrics as an added layer of security. Unlike entering a passcode, the Accessibility Service cannot verify any biometric actions. If your platform provides the option to add a description to the biometric screen, it is advisable to use it, as the system prohibits any services from tampering with it.

    Passcode per device

    After a user logs in to their account on a device, it is recommended to perform "device registration" within your app. This involves generating a passcode or private key on the device that the user will subsequently use to authenticate any sensitive actions. By implementing device registration, even if the passcode is compromised, it will only be leaked for that specific device.

    Use images or render sensitive UI elements

    As the Accessibility Service cannot recognize images, consider replacing your passcode buttons with images of digits and randomly positioning them. By doing so, you can avoid automated attacks via the Accessibility Service. Doing so can increase the UX complexity of your app. So it is a tradeoff.

    Conclusion

    As is often the case with difficult security problems, there is no single answer to addressing abuse of accessibility services. There are a range of ways to approach mitigating the security risk, each with tradeoffs or considerations. As always, we recommend carefully examining the risk of abuse to your application and making a security decision based on the risk and tradeoffs that make sense for your app.

    Lastly, be wary of vendors who claim to provide a simple solution to malware attacks against your application. Such solutions often promote themselves by advertising against a single case of malware, but cannot protect your app from the diverse set of attacks that exist. The simplicity of these solutions will also leave you with little controls and may ultimately create additional business risk due to the tradeoffs in their technical approach.

    Learn more in our follow-up blog: Protecting Against Android Overlay Attacks

    Read More >

    Other posts you might be interested in