Accessibility delegates

      Technique summary
    Technique Accessibility delegates
    Against Malicious accessibility services
    Limitations None
    Side effects Views that use protection based on accessibility delegates, will not be available for legitimate accessibility services as well, which causes reduced functionality for the users relying on accessibility services
    Recommendations Only use for views that users with accessibility needs do not need to work with

    Accessibility delegates in Android are a vital feature for customizing app accessibility. They allow developers to define or improve the accessibility of their views that may not be adequately served by the default accessibility services provided by Android.

    Accessibility delegates can be used to fine-tune defense against malicious accessibility services.

    Preventing accessibility services from spying on users' data

    Malicious accessibility services can access text in Android Views.

    a11y-accessing-view-text

    Accessing view text with a11y services

    The defense solution constitutes registering delegates in sensitive views to modify the way accessibility events will originate from those views.

    For example, to prevent accessibility services from accessing the view text, create a class inheriting from View.AccessibilityDelegate, and override the callbacks onPopulateAccessibilityEvent and onInitializeAccessibilityNodeInfo. In these callbacks, modify the text from the AccessibilityEvent object and from the AccessibilityNodeInfo object. This way, the accessibility events will be modified at their source, and no accessibility service will have access to the original text. Note that both callbacks need to be overridden, as each one of them protects against a different type of data recovery.

    public class MyA11yDelegate extends AccessibilityDelegate { // (...) @Override public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { super.onPopulateAccessibilityEvent(host, event); if (event.getText().size() > 0) { event.getText().clear(); event.getText().add("CENSORED"); } } @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); if (info.getText().toString().length() > 0) { info.setText("CENSORED"); } } }

    Assign the delegate to sensitive views:

    MyA11yDelegate delegate = new MytA11yDelegate(); emailView.setAccessibilityDelegate(delegate); passwordView.setAccessibilityDelegate(delegate);

    a11y-delegates

    Failed view text access

    Preventing accessibility services from spoofing users' input

    Malicious accessibility services can interact with data input elements, for example they can enter text or click buttons.

    You can use delegates to prevent accessibility services from interacting with input elements.

    @Override public boolean performAccessibilityAction(@NonNull View host, int action, @Nullable Bundle args) { String actionDescription; switch(action) { case AccessibilityNodeInfo.ACTION_SET_TEXT: actionDescription = "set text"; break; case AccessibilityNodeInfo.ACTION_CLICK: actionDescription = "click"; break; default: return super.performAccessibilityAction(host, action, args); } Log.d("ANTI_CLICKERS", "[!] " + actionDescription + " action has been restricted!"); // dispatch clicker detection as wished (...) return false; } override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean { val actionDescription = when (action) { AccessibilityNodeInfo.ACTION_SET_TEXT -> "set text" AccessibilityNodeInfo.ACTION_CLICK -> "click" else -> return super.performAccessibilityAction(host, action, args) } Log.d("ANTI_CLICKERS", "[!] $actionDescription action has been restricted!") // dispatch clicker detection as wished (...) return false }

    Guardsquare

    Table of contents