Android Applications Basics

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Try Hard Security Group


Модель безпеки Android

Є два рівні:

  • ОС, яка ізолює встановлені додатки один від одного.

  • Сам додаток, який дозволяє розробникам викрити певні функціональності та налаштувати можливості додатка.

Розділення UID

Кожному додатку призначається певний ідентифікатор користувача (UID). Це робиться під час встановлення додатка, щоб додаток міг взаємодіяти лише з файлами, які належать його UID або спільними файлами. Тому лише сам додаток, певні компоненти ОС та користувач з правами root можуть отримати доступ до даних додатків.

Спільний UID

Два додатки можуть бути налаштовані на використання одного Ідентифікатора користувача (UID). Це може бути корисно для обміну інформацією, але якщо один з них скомпрометований, дані обох додатків будуть скомпрометовані. Тому цю поведінку не рекомендується. Для спільного використання одного UID додатки повинні визначити одне й те ж значення android:sharedUserId у своїх маніфестах.

Пісочниця

Пісочниця додатків Android дозволяє запускати кожен додаток як окремий процес під окремим ідентифікатором користувача. Кожен процес має свою власну віртуальну машину, тому код додатка виконується в ізоляції від інших додатків. Починаючи з Android 5.0(L), SELinux застосовується. Фактично, SELinux відхиляє всі взаємодії процесів, а потім створює політики, щоб дозволити лише очікувані взаємодії між ними.

Дозволи

Коли ви встановлюєте додаток і він запитує дозволи, додаток запитує дозволи, налаштовані в елементах uses-permission у файлі AndroidManifest.xml. Елемент uses-permission вказує назву запитаного дозволу в атрибуті name. Він також має атрибут maxSdkVersion, який припиняє запит дозволів на версіях вище вказаної. Зверніть увагу, що додатки для Android не потрібно запитувати всі дозволи відразу, вони також можуть запитувати дозволи динамічно, але всі дозволи повинні бути оголошені в маніфесті.

Коли додаток викриває функціональність, він може обмежити доступ лише для додатків, які мають вказаний дозвіл. Елемент дозволу має три атрибути:

  • Назва дозволу

  • Атрибут permission-group, який дозволяє групувати пов'язані дозволи.

  • Рівень захисту, який вказує, як дозволи надаються. Є чотири типи:

  • Normal: Використовується, коли немає відомих загроз для додатка. Користувачу не потрібно затверджувати його.

  • Dangerous: Вказує, що дозвіл надає запитуючому додатку певний підвищений доступ. Користувачі повинні затвердити їх.

  • Signature: Тільки додатки, підписані тим самим сертифікатом, що і той, який експортує компонент, можуть отримати дозвіл. Це найсильніший тип захисту.

  • SignatureOrSystem: Тільки додатки, підписані тим самим сертифікатом, що і той, який експортує компонент, або додатки, які працюють з рівнем доступу системи, можуть отримати дозволи

Передвстановлені додатки

Ці додатки зазвичай знаходяться в каталогах /system/app або /system/priv-app, і деякі з них оптимізовані (ви навіть не знайдете файл classes.dex). Ці додатки варто перевірити, оскільки іноді вони працюють з надто багатьма дозволами (як root).

  • Ті, що поставляються з AOSP (Android OpenSource Project) ROM

  • Додані виробником пристрою

  • Додані постачальником мобільного телефону (якщо придбано в них)

Рутування

Для отримання прав root на фізичний пристрій Android зазвичай потрібно експлуатувати 1 або 2 вразливості, які зазвичай є специфічними для пристрою та версії. Після успішного використання експлойту зазвичай бінарний файл Linux su копіюється в розташування, вказане в змінній середовища PATH користувача, наприклад /system/xbin.

Після налаштування бінарного файлу su, іншим додатком Android використовується для взаємодії з бінарним файлом su та обробки запитів на отримання прав root доступу, наприклад Superuser та SuperSU (доступні в магазині Google Play).

Зверніть увагу, що процес рутування дуже небезпечний і може серйозно пошкодити пристрій

ROM

Можливо замінити ОС, встановивши власну прошивку. Роблячи це, можна розширити корисність старого пристрою, обійти обмеження програмного забезпечення або отримати доступ до останнього коду Android. OmniROM та LineageOS - дві з найпопулярніших прошивок для використання.

Зверніть увагу, що не завжди потрібно рутувати пристрій, щоб встановити власну прошивку. Деякі виробники дозволяють розблокування їх завантажувачів у документований та безпечний спосіб.

Наслідки

Після рутування пристрою будь-який додаток може запитувати доступ як root. Якщо зловмисний додаток отримає його, він матиме доступ практично до всього і зможе пошкодити телефон.

Основи додатків для Android

  • Формат додатків для Android відомий як формат файлу APK. Це, по суті, ZIP-файл (перейменувавши розширення файлу на .zip, можна розпакувати та переглянути вміст).

  • Вміст APK (не вичерпний)

  • AndroidManifest.xml

  • resources.arsc/strings.xml

  • resources.arsc: містить попередньо скомпільовані ресурси, такі як бінарний XML.

  • res/xml/files_paths.xml

  • META-INF/

  • Ось де знаходиться сертифікат!

  • classes.dex

  • Містить байткод Dalvik, що представляє скомпільований код Java (або Kotlin), який виконується додатком за замовчуванням.

  • lib/

  • Містить власні бібліотеки, розділені за архітектурою ЦП в підкаталогах.

  • armeabi: код для процесорів на основі ARM

  • armeabi-v7a: код для процесорів на основі ARMv7 та вище

  • x86: код для процесорів X86

  • mips: код лише для процесорів MIPS

  • assets/

  • Зберігає різноманітні файли, необхідні для додатка, можливо включаючи додаткові власні бібліотеки або файли DEX, іноді використовувані авторами шкідливих програм для приховування додаткового коду.

  • res/

  • Містить ресурси, які не компілюються в resources.arsc

Dalvik & Smali

У розробці Android використовується Java або Kotlin для створення додатків. Замість використання JVM, як у десктопних додатках, Android компілює цей код у Dalvik Executable (DEX) bytecode. Раніше цей bytecode обробляв віртуальна машина Dalvik, але зараз у новіших версіях Android цю роль виконує Android Runtime (ART).

Для зворотного проектування Smali стає важливим. Це людино-читабельна версія DEX bytecode, що діє як мова асемблера, перетворюючи вихідний код в інструкції bytecode. Smali та baksmali вказують на засоби зборки та розборки в цьому контексті.

Intents

Intents є основним засобом, за допомогою якого Android додатки взаємодіють між своїми компонентами або з іншими додатками. Ці об'єкти повідомлень також можуть передавати дані між додатками або компонентами, схоже на те, як використовуються запити GET/POST у HTTP-зв'язках.

Таким чином, Intent - це повідомлення, яке передається між компонентами. Intents можуть бути спрямовані на конкретні компоненти або додатки, або можуть бути відправлені без конкретного отримувача. Щоб було простіше, Intent може бути використаний:

  • Для запуску Activity, зазвичай відкриття інтерфейсу користувача для додатка

  • Як трансляції для повідомлення системі та додаткам про зміни

  • Для запуску, зупинки та взаємодії з фоновим сервісом

  • Для доступу до даних через ContentProviders

  • Як зворотні виклики для обробки подій

Якщо вразливий, Intents можуть бути використані для виконання різноманітних атак.

Intent-Filter

Intent Filters визначають як активність, сервіс або Broadcast Receiver можуть взаємодіяти з різними типами Intents. Вони суттєво описують можливості цих компонентів, такі як дії, які вони можуть виконувати або типи трансляцій, які вони можуть обробляти. Основне місце для оголошення цих фільтрів - це файл AndroidManifest.xml, хоча для Broadcast Receivers також є можливість кодування їх.

Intent Filters складаються з категорій, дій та фільтрів даних, з можливістю включення додаткових метаданих. Ця настройка дозволяє компонентам обробляти конкретні Intents, які відповідають оголошеним критеріям.

Критичним аспектом компонентів Android (активності/сервіси/постачальники контенту/Broadcast Receiver) є їх видимість або публічний статус. Компонент вважається публічним і може взаємодіяти з іншими додатками, якщо він експортується зі значенням true або якщо для нього оголошено Intent Filter у маніфесті. Однак розробники можуть явно зробити ці компоненти приватними, забезпечуючи, що вони не взаємодіють з іншими додатками ненавмисно. Це досягається шляхом встановлення атрибута експортувати на значення false у їх визначеннях маніфесту.

Більше того, розробники мають можливість додатково захистити доступ до цих компонентів, вимагаючи певних дозволів. Атрибут дозвіл може бути встановлений для забезпечення того, що доступ до компонента можуть мати лише додатки з призначеним дозволом, додаючи додатковий рівень безпеки та контролю над тим, хто може взаємодіяти з ним.

<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>

Неявні наміри

Наміри створюються програмно за допомогою конструктора Intent:

Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));

Дія раніше оголошеного наміру - ACTION_SEND, а Додаткова інформація - це поштова адреса Uri (додаткова інформація, яку очікує намір).

Цей намір повинен бути оголошений у файлі маніфесту, як у наступному прикладі:

<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

Intent-filter повинен відповідати дії, даним та категорії, щоб отримати повідомлення.

Процес "вирішення наміру" визначає, яка програма повинна отримати кожне повідомлення. Цей процес враховує атрибут пріоритету, який може бути встановлений у оголошенні intent-filter, і вибирається той, у якого вищий пріоритет. Цей пріоритет може бути встановлений від -1000 до 1000, і програми можуть використовувати значення SYSTEM_HIGH_PRIORITY. Якщо виникає конфлікт, з'являється вікно "вибору", щоб користувач міг вирішити.

Явні наміри

Явний намір вказує ім'я класу, на який він спрямований:

Intent downloadIntent = new (this, DownloadService.class):

У інших додатках для доступу до раніше визначеного наміру можна використовувати:

Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);

Відкладені наміри

Це дозволяє іншим додаткам виконувати дії від імені вашого додатку, використовуючи ідентифікацію та дозволи вашого додатку. При побудові відкладеного наміру необхідно вказати намір та дію для виконання. Якщо заявлений намір не є явним (не вказує, який намір може його викликати), зловмисний додаток може виконати заявлену дію від імені додатку жертви. Більше того, якщо дія не вказана, зловмисний додаток зможе виконати будь-яку дію від імені жертви.

Наміри трансляції

На відміну від попередніх намірів, які отримує лише один додаток, наміри трансляції можуть бути отримані кількома додатками. Однак починаючи з версії API 14, можливо вказати додаток, який повинен отримати повідомлення, використовуючи Intent.set Package.

Також можна вказати дозвіл при відправці трансляції. Додатку-одержувачу буде потрібно мати цей дозвіл.

Існують два типи трансляцій: звичайні (асинхронні) та впорядковані (синхронні). Порядок базується на налаштованому пріоритеті в елементі-одержувачі. Кожен додаток може обробляти, передавати або відкидати трансляцію.

Можливо відправити трансляцію, використовуючи функцію sendBroadcast(intent, receiverPermission) з класу Context. Також можна використовувати функцію sendBroadcast з LocalBroadCastManager, що забезпечує, що повідомлення ніколи не залишить додаток. Використовуючи це, навіть не потрібно експортувати компонент-одержувач.

Липкі трансляції

Цей тип трансляцій можна отримати довго після їх відправлення. Вони були застарілими на рівні API 21, і рекомендується не використовувати їх. Вони дозволяють будь-якому додатку перехоплювати дані, а також змінювати їх.

Якщо ви знаходите функції, що містять слово "липкі", наприклад sendStickyBroadcast або sendStickyBroadcastAsUser, перевірте вплив і спробуйте їх видалити.

Глибокі посилання / URL-схеми

У додатках для Android глибокі посилання використовуються для ініціювання дії (наміру) безпосередньо через URL. Це робиться шляхом вказання конкретної URL-схеми в межах активності. Коли пристрій Android намагається отримати доступ до URL з цією схемою, запускається вказана активність у додатку.

Схему необхідно вказати в файлі AndroidManifest.xml:

[...]
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="examplescheme" />
</intent-filter>
[...]

Схема з попереднього прикладу - exampleapp:// (зверніть увагу також на категорію BROWSABLE)

Потім у полі даних можна вказати хост та шлях:

<data android:scheme="examplescheme"
android:host="example"
/>

Для доступу до нього з веб-сайту можна встановити посилання такого виду:

<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>

Для того щоб знайти код, який буде виконуватися в додатку, перейдіть до активності, викликаної за допомогою глибинного посилання, та знайдіть функцію onNewIntent.

Дізнайтеся, як викликати глибинні посилання без використання HTML-сторінок.

AIDL - Мова опису інтерфейсу Android

Мова опису інтерфейсу Android (AIDL) призначена для спрощення комунікації між клієнтом та службою в додатках Android через міжпроцесову комунікацію (IPC). Оскільки безпосередній доступ до пам'яті іншого процесу не дозволяється в Android, AIDL спрощує процес, маршалюючи об'єкти в формат, зрозумілий операційною системою, тим самим полегшуючи комунікацію між різними процесами.

Ключові концепції

  • Пов'язані служби: Ці служби використовують AIDL для IPC, дозволяючи активностям або компонентам прив'язуватися до служби, надсилати запити та отримувати відповіді. Метод onBind в класі служби є критичним для ініціювання взаємодії, що робить його важливою областю для перевірки безпеки у пошуку вразливостей.

  • Повідомлення: Діючи як пов'язана служба, Messenger сприяє IPC з фокусом на обробці даних через метод onBind. Важливо докладно перевірити цей метод на наявність небезпечної обробки даних або виконання чутливих функцій.

  • Binder: Хоча пряме використання класу Binder менш поширене через абстракцію AIDL, корисно розуміти, що Binder діє як драйвер рівня ядра, що сприяє передачі даних між пам'ятними просторами різних процесів. Для додаткового розуміння доступний ресурс за посиланням https://www.youtube.com/watch?v=O-UHvFjxwZ8.

Компоненти

До них входять: Активності, Служби, Приймачі трансляцій та Постачальники.

Пускова активність та інші активності

У додатках Android активності схожі на екрани, що показують різні частини користувацького інтерфейсу додатка. Додаток може мати багато активностей, кожна з яких представляє унікальний екран користувачеві.

Пускова активність є головним шлюзом до додатка, який запускається при натисканні на піктограму додатка. Вона визначена в файлі маніфесту додатка з конкретними намірами MAIN та LAUNCHER:

<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Не всі додатки потребують активності запуску, особливо ті, що не мають інтерфейсу користувача, наприклад, фонові служби.

Активності можуть бути доступні для інших додатків або процесів, позначивши їх як "експортовані" в маніфесті. Це налаштування дозволяє іншим додаткам запускати цю активність:

<service android:name=".ExampleExportedService" android:exported="true"/>

Проте, доступ до діяльності з іншої програми не завжди є загрозою для безпеки. Стурбованість виникає, якщо чутлива інформація передається неправильно, що може призвести до витоку інформації.

Життєвий цикл діяльності починається з методу onCreate, налаштовуючи користувацький інтерфейс та підготовлюючи діяльність до взаємодії з користувачем.

Підклас додатку

У розробці Android додатків є можливість створити підклас класу Application, хоча це не є обов'язковим. Коли такий підклас визначений, він стає першим класом, який ініціалізується в додатку. Метод attachBaseContext, якщо він реалізований у цьому підкласі, виконується перед методом onCreate. Ця налаштування дозволяє ранню ініціалізацію перед запуском решти додатку.

public class MyApp extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Initialization code here
}

@Override
public void onCreate() {
super.onCreate();
// More initialization code
}
}

Сервіси

Сервіси - це фонові операції, які можуть виконувати завдання без інтерфейсу користувача. Ці завдання можуть продовжувати виконуватися навіть тоді, коли користувачі переходять до інших додатків, що робить сервіси важливими для тривалих операцій.

Сервіси універсальні; їх можна ініціювати різними способами, причому Інтенти є основним методом запуску їх як точки входу додатка. Після запуску сервісу за допомогою методу startService, його метод onStart починає виконуватися і продовжує роботу до тих пір, поки явно не буде викликаний метод stopService. З іншого боку, якщо робота сервісу залежить від активного підключення клієнта, то для зв'язування клієнта з сервісом використовується метод bindService, який активує метод onBind для передачі даних.

Цікавим застосуванням сервісів є відтворення фонової музики або отримання мережевих даних без перешкодження взаємодії користувача з додатком. Більше того, сервіси можуть бути доступні іншим процесам на тому ж пристрої через експорт. Це не є стандартною поведінкою і вимагає явної конфігурації в файлі маніфесту Android:

<service android:name=".ExampleExportedService" android:exported="true"/>

Приймачі трансляцій

Приймачі трансляцій діють як слухачі в системі обміну повідомленнями, дозволяючи кільком додаткам реагувати на одні й ті ж повідомлення від системи. Додаток може зареєструвати приймач двома основними способами: через Маніфест додатка або динамічно в коді додатка за допомогою API registerReceiver. У Маніфесті трансляції фільтруються за допомогою дозволів, тоді як динамічно зареєстровані приймачі також можуть вказати дозволи при реєстрації.

Фільтри намірів є важливими в обох методах реєстрації, визначаючи, які трансляції спрацьовують приймач. Як тільки відправлена відповідна трансляція, викликається метод onReceive приймача, що дозволяє додатку реагувати відповідно, наприклад, налаштовуючи поведінку відповідно до сповіщення про низький рівень заряду батареї.

Трансляції можуть бути або асинхронними, досягаючи всіх приймачів без порядку, або синхронними, де приймачі отримують трансляцію на основі встановлених пріоритетів. Однак важливо враховувати потенційний ризик безпеки, оскільки будь-яке додаток може встановити для себе пріоритет для перехоплення трансляції.

Щоб зрозуміти функціональність приймача, шукайте метод onReceive у його класі. Код цього методу може маніпулювати отриманим наміром, що підкреслює необхідність перевірки даних приймачами, особливо в Упорядкованих трансляціях, які можуть змінювати або відкидати намір.

Постачальник контенту

Постачальники контенту є важливими для обміну структурованими даними між додатками, підкреслюючи важливість впровадження дозволів для забезпечення безпеки даних. Вони дозволяють додаткам отримувати доступ до даних з різних джерел, включаючи бази даних, файлові системи або мережу. Специфічні дозволи, такі як readPermission та writePermission, є важливими для контролю доступу. Крім того, тимчасовий доступ може бути наданий через налаштування grantUriPermission у Маніфесті додатка, використовуючи атрибути, такі як path, pathPrefix та pathPattern для детального контролю доступу.

Перевірка введення є надзвичайно важливою для запобігання вразливостей, таких як SQL-ін'єкція. Постачальники контенту підтримують базові операції: insert(), update(), delete() та query(), сприяючи маніпулюванню даними та обміну між додатками.

FileProvider, спеціалізований постачальник контенту, спрямований на безпечний обмін файлами. Він визначається в Маніфесті додатка з конкретними атрибутами для контролю доступу до папок, позначених android:exported та android:resource, що вказують на конфігурації папок. Рекомендується обережно діяти при обміні каталогами, щоб уникнути ненавмисного розкриття чутливих даних.

Приклад декларації маніфесту для FileProvider:

<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>

І приклад вказання спільних папок у filepaths.xml:

<paths>
<files-path path="images/" name="myimages" />
</paths>

Для отримання додаткової інформації перевірте:

WebViews

WebViews - це як міні-веб-браузери всередині додатків Android, які витягують контент або з вебу, або з локальних файлів. Вони стикаються з аналогічними ризиками, як і звичайні браузери, але є способи зменшити ці ризики за допомогою конкретних налаштувань.

Android пропонує два основних типи WebView:

  • WebViewClient чудово підходить для базового HTML, але не підтримує функцію сповіщення JavaScript, що впливає на те, як можна тестувати атаки XSS.

  • WebChromeClient діє більше як повноцінний досвід браузера Chrome.

Важливою точкою є те, що браузери WebView не діляться кукісами з основним браузером пристрою.

Для завантаження контенту доступні методи, такі як loadUrl, loadData, та loadDataWithBaseURL. Важливо переконатися, що ці URL-адреси або файли безпечні для використання. Налаштування безпеки можна керувати за допомогою класу WebSettings. Наприклад, відключення JavaScript за допомогою setJavaScriptEnabled(false) може запобігти атакам XSS.

JavaScript "Bridge" дозволяє об'єктам Java взаємодіяти з JavaScript, вимагаючи, щоб методи були позначені як @JavascriptInterface для забезпечення безпеки з Android 4.2 і вище.

Дозвіл доступу до контенту (setAllowContentAccess(true)) дозволяє WebViews отримувати доступ до постачальників контенту, що може бути ризиком, якщо URL-адреси контенту не підтверджені як безпечні.

Для контролю доступу до файлів:

  • Відключення доступу до файлів (setAllowFileAccess(false)) обмежує доступ до файлової системи, з винятками для певних ресурсів, забезпечуючи їх використання лише для нечутливого контенту.

Інші компоненти додатків та управління мобільними пристроями

Цифровий підпис додатків

  • Цифровий підпис є обов'язковим для додатків Android, що забезпечує їх автентичне походження перед встановленням. Цей процес використовує сертифікат для ідентифікації додатка і повинен бути перевірений менеджером пакетів пристрою під час встановлення. Додатки можуть бути самопідписаними або сертифікованими зовнішнім ЦЗ, захищаючи від несанкціонованого доступу та забезпечуючи, що додаток залишається недоторканим під час його доставки на пристрій.

Перевірка додатків для підвищення безпеки

  • Починаючи з Android 4.2, функція під назвою Verify Apps дозволяє користувачам перевіряти додатки на безпеку перед встановленням. Цей процес перевірки може попереджати користувачів про потенційно шкідливі додатки або навіть запобігати встановленню особливо зловмисних, підвищуючи безпеку користувача.

Управління мобільними пристроями (MDM)

  • Рішення MDM забезпечують нагляд та безпеку для мобільних пристроїв через API адміністрування пристроєм. Вони вимагають встановлення додатка Android для ефективного управління та захисту мобільних пристроїв. Основні функції включають застосування політик паролю, обов'язкове шифрування сховища та дозвіл на видалення даних віддалено, забезпечуючи повний контроль та безпеку над мобільними пристроями.

// Example of enforcing a password policy with MDM
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminComponent = new ComponentName(context, AdminReceiver.class);

if (dpm.isAdminActive(adminComponent)) {
// Set minimum password length
dpm.setPasswordMinimumLength(adminComponent, 8);
}

Група з безпеки Try Hard

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated