From 92f761550246e60016ce1c37f1c19869536756af Mon Sep 17 00:00:00 2001 From: Carlos Valdivia Date: Mon, 8 Sep 2014 20:12:24 -0700 Subject: [PATCH] SECURITY: Prevent preference intents from exploiting settings. Settings has super powers because it shares the system uid. We prevent those powers from being exploited by malicious authenticators by checking the intents those authenticators provide. We will only launch intents that resolve to Activities that are exported=true or owned by the same UID as the authenticator. Bug: 14408627 Change-Id: Ia179df8561d29745767dac0f3c97eb0f68083f59 --- .../settings/accounts/ManageAccountsSettings.java | 51 ++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java index 8787bced4d..074176bd71 100644 --- a/src/com/android/settings/accounts/ManageAccountsSettings.java +++ b/src/com/android/settings/accounts/ManageAccountsSettings.java @@ -18,6 +18,7 @@ package com.android.settings.accounts; import android.accounts.Account; import android.accounts.AccountManager; +import android.accounts.AuthenticatorDescription; import android.app.ActionBar; import android.app.Activity; import android.content.ContentResolver; @@ -25,7 +26,11 @@ import android.content.Intent; import android.content.SyncAdapterType; import android.content.SyncInfo; import android.content.SyncStatusInfo; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -423,7 +428,7 @@ public class ManageAccountsSettings extends AccountPreferenceBase * intent, and hack the location settings to start it as a fragment. */ private void updatePreferenceIntents(PreferenceScreen prefs) { - PackageManager pm = getActivity().getPackageManager(); + final PackageManager pm = getActivity().getPackageManager(); for (int i = 0; i < prefs.getPreferenceCount();) { Preference pref = prefs.getPreference(i); Intent intent = pref.getIntent(); @@ -461,8 +466,22 @@ public class ManageAccountsSettings extends AccountPreferenceBase pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - getActivity().startActivityAsUser(preference.getIntent(), - mUserHandle); + Intent prefIntent = preference.getIntent(); + /* + * Check the intent to see if it resolves to a exported=false + * activity that doesn't share a uid with the authenticator. + * + * Otherwise the intent is considered unsafe in that it will be + * exploiting the fact that settings has system privileges. + */ + if (isSafeIntent(pm, prefIntent)) { + getActivity().startActivityAsUser(prefIntent, mUserHandle); + } else { + Log.e(TAG, + "Refusing to launch authenticator intent because" + + "it exploits Settings permissions: " + + prefIntent); + } return true; } }); @@ -473,6 +492,32 @@ public class ManageAccountsSettings extends AccountPreferenceBase } } + /** + * Determines if the supplied Intent is safe. A safe intent is one that is + * will launch a exported=true activity or owned by the same uid as the + * authenticator supplying the intent. + */ + private boolean isSafeIntent(PackageManager pm, Intent intent) { + AuthenticatorDescription authDesc = + mAuthenticatorHelper.getAccountTypeDescription(mAccountType); + ResolveInfo resolveInfo = pm.resolveActivity(intent, 0); + if (resolveInfo == null) { + return false; + } + ActivityInfo resolvedActivityInfo = resolveInfo.activityInfo; + ApplicationInfo resolvedAppInfo = resolvedActivityInfo.applicationInfo; + try { + ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0); + return resolvedActivityInfo.exported + || resolvedAppInfo.uid == authenticatorAppInf.uid; + } catch (NameNotFoundException e) { + Log.e(TAG, + "Intent considered unsafe due to exception.", + e); + return false; + } + } + @Override protected void onAuthDescriptionsUpdated() { // Update account icons for all account preference items -- 2.11.0