Возможность получения доступа к произвольному ContentProvider
Критичность: СРЕДНИЙ | |
Способ обнаружения: IAST |
Описание
Уязвимость позволяет получить доступ к внутренним неэкспортируемым ContentProvider.
Уязвимость присутствует в приложениях, которые используют Intent из недоверенного источника (например, полученные из стороннего приложения с помощью методов getIntent
, getParcelableExtra
или onActivityResult
) для возврата данных с помощью метода setResult
.
Например, вредоносное приложение может использовать такой код:
Intent intent = new Intent();
intent.setData(Uri.parse("content://com.victim.provider/secret_data.txt"));
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setClassName("vuln.app.pkg", "vuln.app.pkg.SomeActivity");
startActivityForResult(intent, 0);
Целевое уязвимое приложение (SomeActivity.java):
super.onCreate(savedInstanceState);
setResult(RESULT_OK, getIntent());
finish();
В результате вредоносное приложение получит доступ к ContentProvider com.victim.provider
уязвимого приложения.
Рекомендации
Для устранения подобных проблем в приложении необходимо убедиться в соответствии нескольким правилам:
-
Реализовать private/in-house видимость у компонентов, которые принимают Intent и используют его в методе
setResult
. Например, объявление Activity внутренней — отсутствуютintent-filter
или флагexported
выставлен в значениеfalse
.<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.swordfishsecurity.appsec.android.activity.privateactivity" > <application android:allowBackup="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <!-- Private activity --> <!-- *** 1 *** Не используйте taskAffinity --> <!-- *** 2 *** Не используйте launchMode --> <!-- *** 3 *** Явно указывайте атрибут exported="false" --> <activity android:name=".PrivateActivity" android:label="@string/app_name" android:exported="false" /> <!-- Public activity запускаемая по умолчанию --> <activity android:name=".PrivateUserActivity" android:label="@string/app_name" android:exported="true" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
-
Проводить валидацию Intent на предмет вредоносности:
-
Такой Intent не должен направляться в private/in-house компоненты или компоненты внешних приложений.
Intent intent = getIntent(); Intent redirectIntent = (Intent) intent.getParcelableExtra(“redirect_intent”); ComponentName name = redirectIntent.resolveActivity(getPackageManager()); // проверяем целевое имя пакета и класса if(name.getPackageName().equals(“safe_package”) && name.getClassName().equals(“safe_class”)) { startActivity(redirectIntent); }
-
Если всё же предусмотрен запуск компонент внешних приложений, то нужно проводить валидацию/санитизацию Permissions передаваемых в «to-be-redirected Intent».
Пример валидации:Intent resultIntent = (Intent) intent.getParcelableExtra(“result_intent”); int flags = resultIntent.getFlags(); if((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION == 0) && (flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION == 0)) { setResult(RESULT_OK, resultIntent); }
Пример для санитизации:
resultIntent.removeFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); resultIntent.removeFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); setResult(RESULT_OK, intent);
-