We have recently disclosed a new vulnerability to the Android Security Team. The vulnerability affected many apps, including Settings (the one that is found on every Android device), GmailGoogle NowDropBox and Evernote.  To be more accurate, any App which extended the PreferenceActivity class using an exported activity was automatically vulnerable. A patch has been provided in Android KitKat. If you wondered why your code is now broken, it is due to the Android KitKat patch which requires applications to override the new method, PreferenceActivity.isValidFragment, which has been added to the Android Framework.

In this blog post we will begin with a short introduction on Android and its sandbox, and then we will deep-dive into the vulnerability itself. For the sake of simplicity we omitted some of the details which can be found in our whitepaper.

 

The UI building blocks of Android Apps

The UI of Android apps is made of activities. An Activity provides a single screen with some functionality (for instance: a browser’s bookmarks manager). A Fragment  can be considered as a sub-activity. It is a piece of the App’s UI. Fragments provide some flexibility as they allow reuse in different activities. While a Fragment instance is coupled with the Activity it resides inside, different instances can be embedded in different activities. See Figure 1 for the relation between activities and fragments.

Figure 1: The relation between activities and fragments.
Scroll to view full table

 

Android Sandboxing, Permissions, Inter-app communication and Attacks by Malicious Apps

In Android, apps are isolated from each other and subject to their declared set of permissions by the use of Sandboxing. An app cannot normally access sensitive data of another. That being said, it is possible for one app to invoke application components (such as activities) of another app for feature reuse.  For example, Chrome invokes the Google play app when opening Google Play URLs.  The invocation is done using Intents which are IPC objects that the source application passes to the corresponding API. Intents do not just specify the target, they also contain data in two places. The first location is the data attribute (of URI type) and the second one is a dictionary (Bundle) that can contain an arbitrary amount of information (also known as Intent extras). Activities can be invoked by an external app if they are exported in the application’s manifest file (ApplicationManifest.xml). Making an activity public (exported) creates a potential hole in the Android Sandbox. Since activities access the input Intent’s data, a bad app can invoke the exported activity and provide it with malicious data, that may trigger vulnerabilities if the data are not properly santizied or validated in the target application. As of Fragments, they can receive input by accessing the embedding activity thus its input Intent or as Fragment-specific arguments. See Figure 2 for an attack outline.

 
Figure 2: Attacking exported activities.
Scroll to view full table

 

The PreferenceActivity

The PreferenceActivity is a base class (provided by the Android Framework) for showing a hierarchy of preferences to the user. The preferences are associated with a PreferenceFragment. The PreferenceActivity consumes a few Intent extras. One of them is :android:show_fragment which tells the PreferenceActivity which fragment to display first. The dynamic Fragment loading is done by a chain of calls which start at the activity creation and end at Fragment.instantiate (see Figures 3,4). The latter loads the Fragment using the Java Reflection API.

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

   String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
   Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);

   if (savedInstanceState != null) {

   } else {
       if (initialFragment != null && mSinglePane) {
           // If we are just showing a fragment, we want to run in
           // new fragment mode, but don't need to compute and show
           // the headers.
           switchToHeader(initialFragment, initialArguments);

		} else {

           if (mHeaders.size() > 0) {
               if (!mSinglePane) {
                   if (initialFragment == null) {

                   } else {
                      switchToHeader(initialFragment, initialArguments);
                   }
               }
           }
       }
   }

}

public void switchToHeader(String fragmentName, Bundle args) {
   setSelectedHeader(null);
   switchToHeaderInner(fragmentName, args, 0);
}

private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
   getFragmentManager().popBackStack(BACK_STACK_PREFS,
                                     FragmentManager.POP_BACK_STACK_INCLUSIVE);
   Fragment f = Fragment.instantiate(this, fragmentName, args);
   FragmentTransaction transaction = getFragmentManager().beginTransaction();
   transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
   transaction.replace(com.android.internal.R.id.prefs, f);
   transaction.commitAllowingStateLoss();
}

Figure 3: Chain of calls in PreferenceActivity ending at Fragment.instantiate (as implemented in Android 4.3)

public static Fragment instantiate(Context context, String fname, Bundle args) {
    try {
        Class<?> clazz = sClassMap.get(fname);
        if (clazz == null) {
            // Class not found in the cache, see if it's real, and try to add it
            clazz = context.getClassLoader().loadClass(fname);
            sClassMap.put(fname, clazz);
        }
        Fragment f = (Fragment)clazz.newInstance();
        if (args != null) {
            args.setClassLoader(f.getClass().getClassLoader());
            f.mArguments = args;
        }
        return f;
    }
...
}

Figure 4: Android 4.3 implementation of Fragment.instantiate.

 

The Vulnerability

A malicious application can invoke any exported PreferenceActivity class and supply it with an :android:show_fragment Intent extra in order to make it load an arbitrary class. The goal of the attacker is to execute some code that will break the Android Sandbox, i.e. access sensitive information pertaining to the vulnerable app, or abuse its permissions. Since the attacker cannot supply his own classes as he is limited to ones found under the class loader of the vulnerable app (Android Framework classes and the App classes), the attack is not trivial. In our whitepaper we depict a couple of exploit techniques, one of them is pretty cool. The malicious app can make the PreferenceActivity load an arbitrary Fragment of the vulnerable app, which is normally loaded inside a non-exported Activity to pratically take it from its natural habitat to a hazardous area where input should not be trusted as the malicious app can now control it.  See Figure 5 for the attack outline.

Figure 5: Attacking a Fragment
Scroll to view full table

 

Attacking the Android Settings

As we mentioned above, all apps which make use of PreferenceActivity are vulnerable. We targeted the Settings app since it is a highly privileged application. By exploiting the the vulnerability we managed to successfully subvert its integrity.  The app’s main activity (which is exported), com.android.settings.Settings, extends PreferenceActivity thus it is vulnerable. We searched for interesting fragments in the app’s package, one of them is ChooseLockPassword$ChooseLockPasswordFragment. This Fragment is responsible of handling the credentials changing of the device’s lock screen and is subject to the Device Management Policy.  The Fragment’s natural habitat is the ChooseLockPassword Activity which is non-exported. Normally the  Fragment first asks the user to insert his old credentials (see Figure 6), unless the embedding activity is supplied with an Intent extra, ‘confirm_credentials’ set to false.

Figure 6: Normal behavior of ChooseLockPasswordFragment
Scroll to view full table

Since the activity is not exported, this parameter cannot be easily manipulated by a malicious app, however by exploiting the Fragments Injection vulnerability, we can embed the ChooseLockPassword$ChooseLockPasswordFragment inside an exported activity, com.android.settings.Settings, and supply it with malicious data, confirm_credentials set to false. See Figure 7 for the attack outline, and Figure 8 for the result. Since this exploit requires user-intervention it cannot be used remotely thus it requires a physical attacker that wants to change the credentials. Please note that by exploiting this vulnerability the attacker can also override Device Management Policy such as the minimum password requirements.

 
Figure 7: Attacking Android’s Settings
Scroll to view full table

 

Figure 8: User does not need to supply his old credentials
Scroll to view full table

 

The Fix

Google  has provided a patch in Android 4.4 KitKat by adding a new protected API, PreferenceActivity.isValidFragment, which is called before the Fragment is dynamically instantiated by PreferenceActivity (see Figure 9). The isValidFragment method must be overridden otherwise the default implementation throws an exception, as documented in the SDK Reference. We encourage developers to properly implement this method (e.g. as a white-list) since a weak implementation will keep your app vulnerable.

private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {
        getFragmentManager().popBackStack(BACK_STACK_PREFS,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
        if (!isValidFragment(fragmentName)) {
            throw new IllegalArgumentException("Invalid fragment for this activity: "
                    + fragmentName);
        }
        Fragment f = Fragment.instantiate(this, fragmentName, args);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        transaction.replace(com.android.internal.R.id.prefs, f);
        transaction.commitAllowingStateLoss();
    }

Figure 9: Potentially safe Fragment instantiation in Android KitKat.

 

Vulnerable versions
Android 4.3 Jelly Bean and below.

Non-Vulnerable versions
Android 4.4 KitKat.

Disclosure Timeline
12/05/2013  Reply from Android Security Team: “Issue is fixed”.
12/05/2013  Requested a status update.
11/11/2013  Reply from Android Security Team: “Fix in progress”
10/24/2013  Requested for status update.
07/14/2013  Reply from Android Security Team: “We are now looking into the issue”.
07/12/2013  Disclosure to Android Security Team.

About the IBM Application Security Research Team
The Application Security Research Team researches new security threats and vulnerabilities and provides regular rule updates to AppScan.

 

More from Application Security

X-Force Identifies Vulnerability in IoT Platform

4 min read - The last decade has seen an explosion of IoT devices across a multitude of industries. With that rise has come the need for centralized systems to perform data collection and device management, commonly called IoT Platforms. One such platform, ThingsBoard, was the recent subject of research by IBM Security X-Force. While there has been a lot of discussion around the security of IoT devices themselves, there is far less conversation around the security of the platforms these devices connect with.…

4 min read

Patch Tuesday -> Exploit Wednesday: Pwning Windows Ancillary Function Driver for WinSock (afd.sys) in 24 Hours

12 min read - ‘Patch Tuesday, Exploit Wednesday’ is an old hacker adage that refers to the weaponization of vulnerabilities the day after monthly security patches become publicly available. As security improves and exploit mitigations become more sophisticated, the amount of research and development required to craft a weaponized exploit has increased. This is especially relevant for memory corruption vulnerabilities.Figure 1 — Exploitation timelineHowever, with the addition of new features (and memory-unsafe C code) in the Windows 11 kernel, ripe new attack surfaces can…

12 min read

Backdoor Deployment and Ransomware: Top Threats Identified in X-Force Threat Intelligence Index 2023

4 min read - Deployment of backdoors was the number one action on objective taken by threat actors last year, according to the 2023 IBM Security X-Force Threat Intelligence Index — a comprehensive analysis of our research data collected throughout the year. Backdoor access is now among the hottest commodities on the dark web and can sell for thousands of dollars, compared to credit card data — which can go for as low as $10. On the dark web — a veritable eBay for…

4 min read

Direct Kernel Object Manipulation (DKOM) Attacks on ETW Providers

17 min read - Overview In this post, IBM Security X-Force Red offensive hackers analyze how attackers, with elevated privileges, can use their access to stage Windows Kernel post-exploitation capabilities. Over the last few years, public accounts have increasingly shown that less sophisticated attackers are using this technique to achieve their objectives. It is therefore important that we put a spotlight on this capability and learn more about its potential impact. Specifically, in this post, we will evaluate how Kernel post-exploitation can be used…

17 min read