Пентест Android-приложений — это комплексный аудит безопасности, который сочетает в себе статический (SAST) и динамический (DAST) анализ мобильного клиента, а также проверку серверной части (API).
При пентесте Android-приложения финтех-сервиса я наткнулся на экспортированный ContentProvider, через который вытаскивалась полная история транзакций произвольного пользователя. От скачивания APK до рабочего PoC прошло двадцать минут - jadx показал
android:exported="true" без permission в AndroidManifest.xml, команда adb shell content query подтвердила отсутствие проверок на стороне провайдера, а дальше оставалось сформировать content URI с нужным user_id. Приложение перед этим прошло автоматизированное MobSF-сканирование и внутренний аудит - ни один из них не зацепил проблему. Почему? Потому что оба проверяли манифест на уровне паттернов, а не анализировали логику Java-кода провайдера. Эта статья - методика тестирования безопасности Android, собранная так, чтобы подобные баги не проскакивали мимо.Место мобильного пентеста Android в цепочке атаки
Пентест Android приложений - не изолированная процедура, а звено в операционной цепочке. Прежде чем запускать jadx, разберитесь, какую задачу вы решаете в полном engagement'е и что уже сделано: есть ли результаты recon по backend API, проведён ли аудит веб-версии сервиса. Мобильный клиент часто работает с теми же endpoint'ами, но с другой логикой авторизации - баги рождаются на стыке.JADX - это инструмент с интерфейсами командной строки и графическим интерфейсом, позволяющий декомпилировать DEX-файлы (Dalvik Executable) и преобразовывать их в читаемый исходный код на Java.
Важно при пентесте Android приложений, не пологаться на один инструмент, рассмотрим вкратце альтернативные компиляторы похожие на JADX, которые можно применить в крайнем случае.
Bytecode Viewer - это продвинутый и легковесный просмотрщик байт-кода Java, а также графический декомпилятор Java, редактор байт-кода, интерфейсы для работы со Smali и Baksmali, редакторы APK и DEX, декомпиляторы APK и DEX, графические оболочки для декомпиляторов Procyon, Krakatau, CFR и FernFlower, утилиты DEX2Jar и Jar2DEX, инструмент Jar-Jar, шестнадцатеричный просмотрщик, средство поиска по коду, отладчик и многое другое.
CFR - инструмент способен декомпилировать современные возможности Java — вплоть до значительной части функционала версий 9, 12 и 14 включительно; при этом сам декомпилятор полностью написан на Java 6, а потому будет работать где угодно!
Fernflower — это первый действительно работающий аналитический декомпилятор для Java и, вероятно, для высокоуровневых языков программирования в целом.
Типичные точки входа через мобильный клиент ложатся на конкретные техники MITRE ATT&CK:
- Initial Access - эксплуатация публично доступного приложения (T1190) или вредоносный deeplink, запускающий код на стороне клиента (T1203)
- Privilege Escalation - повышение привилегий через уязвимости Android-компонентов или ядра (T1068)
- Credential Access - извлечение токенов и ключей из файлов приложения (T1552.001) или перехват ввода через accessibility-сервисы (T1056.001)
- Collection - сбор данных из локального хранилища приложения (T1005)
- Credential Access / Collection - перехват трафика через evil twin или MitM (T1557.004)
- Defense Evasion - обфускация кода для затруднения анализа (T1027)
Требования к окружению для тестирования безопасности Android
Перед первой командой проверьте окружение - пропуск этого шага стоит часов отладки. Проверено на собственном опыте.Аппаратная часть:
- RAM: минимум 8 ГБ при работе с эмулятором Android через AVD, рекомендуется 16 ГБ
- CPU: x86_64 с поддержкой аппаратной виртуализации (VT-x/AMD-V) для эмулятора, или ARM-устройство с разблокированным загрузчиком
- Физический девайс: Pixel 4a/5a/6a - стабильная поддержка root через Magisk, актуальные security-патчи. Для начала хватит за глаза
- ОС хоста: Kali Linux 2024.x или Ubuntu 22.04+ (macOS работает, но ARM-эмуляция нестабильна - будьте готовы к сюрпризам)
- Android SDK Platform Tools - adb, fastboot (последние версии)
- Java 11+ для jadx и apktool
- Python 3.10+ для Frida и objection
- Frida 16.x:
pip install frida-tools frida - jadx - декомпилятор APK в Java-подобный код
- apktool - разбор ресурсов и smali-кода
- objection - runtime exploration на базе Frida:
pip install objection - MobSF - автоматизированный статический и динамический анализ APK
Статический анализ APK: fingerprinting и поверхность атаки
Статический анализ APK - первый этап, на котором формируется карта атаки. Задача - не просто прогнать сканер, а построить модель приложения: какие компоненты экспортированы, какие deeplink-схемы зарегистрированы, где хранятся данные, какие SDK подключены.Декомпиляция и разбор манифеста
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Что искать в результатах декомпиляции:
- В файлах strings.xml и secrets.xml ищутся API-ключи сторонних сервисов(платёжные шлюзы), Пароли, закрытые криптографические ключи, тестовые учётные записи, точки доступа и захардкоженные URL приватных стейджинг-серверов.
- Exported Activities/Services/ContentProviders без permission - прямой вектор для inter-app атак. ContentProvider с
exported="true"безandroid:permissionпозволяет любому приложению на устройстве читать и писать данные - Deeplink-схемы (
myapp://,https://) - основа для атак категории MASVS-PLATFORM - Использование WebView с
setJavaScriptEnabled(true)плюсaddJavascriptInterface- потенциал для RCE - Небезопасная криптография - DES, ECB-режим, MD5, SHA-1 в хеш-функциях аутентификации
- Network Security Config - разрешён ли cleartext-трафик, настроен ли certificate pinning
Trade-off: инструменты статического анализа
| Инструмент | Преимущества | Ограничения | Когда использовать | Когда не использовать |
|---|---|---|---|---|
| jadx | Java-подобный вывод, GUI + CLI, быстрый поиск | Не справляется с тяжёлой обфускацией (DexGuard), нет smali-редактирования | Первый проход: анализ логики, поиск секретов | APK обфусцирован DexGuard/iXGuard |
| apktool | Полный разбор ресурсов, smali-код, пересборка APK | smali сложнее для чтения, чем Java | Модификация APK, патчинг, анализ ресурсов | Быстрый review логики |
| MobSF | Автоматизация, HTML-отчёт, интеграция в CI/CD | Pattern matching без dataflow, ложные срабатывания | Быстрый скоринг перед ручным анализом | Поиск логических багов, бизнес-уязвимостей |
| drozer | Прямой анализ IPC: ContentProvider, intents, broadcast | Проблемы совместимости с API Level 33+, последний стабильный релиз - 2024 | Аудит экспортированных компонентов | Новые устройства без root, API 34+ |
MobSF полезен как второй проход, но полагаться только на него - ошибка. Инструмент работает pattern matching'ом и не анализирует потоки данных. Тот самый экспортированный ContentProvider с валидацией внутри Java-кода MobSF не поймает - нужен ручной анализ в jadx. На одном проекте я потратил полдня на разбор MobSF-отчёта с 47 finding'ами, из которых реальных проблем оказалось три. А критический баг в ContentProvider инструмент пропустил.
Динамический анализ Android: Frida hooking и обход защит
Динамический анализ - работа с запущенным приложением в реальном времени. Frida Android hooking - основной инструмент для инструментирования процесса, обхода SSL pinning и root detection, перехвата вызовов API.Подключение и первые шаги
На рутированном устройстве запускаем frida-server соответствующей архитектуры (arm64 для большинства современных девайсов). С хоста:- Список процессов:
frida-ps -Uai(USB, applications, include identifiers) - Спавн с инструментированием:
frida -U -f com.target.app - Аттач к уже запущенному:
frida -U com.target.app
Код:
objection -g com.target.app explore
# В консоли objection:
android sslpinning disable
TrustManagerImpl, OkHttp, CertificatePinner, Retrofit interceptors. Но если приложение реализует pinning через нативную библиотеку (JNI), objection бессилен - требуется кастомный Frida-скрипт с Interceptor.attach на конкретные функции в .so. И вот тут начинается настоящая работа.Android root detection bypass
Банковские приложения и финтех-сервисы проверяют root через несколько слоёв: наличие файлов (/system/bin/su, /system/xbin/su), установленные пакеты (com.topjohnwu.magisk), SafetyNet/Play Integrity API, чтение /proc/self/maps на предмет строк Frida.Magisk DenyList скрывает root от конкретных приложений на уровне mount namespace - закрывает большинство Java-уровневых проверок. Для приложений с агрессивным detection нужны Frida-хуки:
JavaScript:
// Обход root detection - подмена результатов File.exists()
Java.perform(function () {
var File = Java.use('java.io.File');
var origExists = File.exists;
File.exists.implementation = function () {
var path = this.getAbsolutePath();
if (path.indexOf('su') !== -1 || path.indexOf('magisk') !== -1) {
return false; // тут нас нет, проходите мимо
}
return origExists.call(this);
};
});
access() или stat() напрямую, требует хуков через Interceptor.attach - нужен реверс конкретной .so-библиотеки, что на порядок сложнее. На практике - это разница между «закрыл за вечер» и «провозился неделю».Уязвимости Android приложений: вектора атак по OWASP MASVS
Структурирование мобильного пентеста по категориям OWASP MASVS (Mobile Application Security Verification Standard) даёт системный подход вместо хаотичного ковыряния. Пересказывать весь MASVS в сотый раз не вижу смысла - разберём те категории, где в 2026 году реально находятся баги.MASVS-STORAGE: утечки из локального хранилища
Согласно MASVS-STORAGE, приложение должно использовать Android Keystore для криптографических ключей и шифровать чувствительные данные. На самом деле - три повторяющихся паттерна:- SharedPreferences открытым текстом - токены, session ID, пользовательские данные в XML. Проверка:
adb shell run-as com.target.app cat shared_prefs/*.xml(если debuggable) или через root-доступ - SQLite без шифрования - базы с PII в
/data/data/com.target.app/databases/. Вытаскиваются черезadb pull, открываются любым SQLite-клиентом - Логи с секретами -
adb logcat | grep -i "token\|password\|session"периодически выдаёт неожиданное. На одном проекте так вывалился полный JWT с правами администратора
MASVS-PLATFORM: deeplink, WebView, ContentProvider
Категория MASVS-PLATFORM покрывает взаимодействие с операционной системой - и именно тут находятся наиболее критичные уязвимости Android приложений в 2026 году.Deeplink hijacking. Приложение регистрирует кастомную URI-схему (
myapp://callback?token=XXX). Любое другое приложение на устройстве может зарегистрировать ту же схему и перехватить intent с параметрами авторизации. Для App Links (https://) с корректно настроенным assetlinks.json атака не работает - но проверяйте, действительно ли Digital Asset Links верифицированы. Типичный баг: myapp://reset-password?token=XXX передаёт токен сброса пароля без проверки источника.Также приложение может регистрировать схему ссылки в AndroidManifest.xml через intent-filter, любое другое приложение может инициировать переход по этой ссылке.
WebView RCE. Связка
setJavaScriptEnabled(true) + addJavascriptInterface + загрузка контента из ненадёжного источника (через deeplink или HTTP-redirect) - потенциальный RCE. На Android API < 17 (исторический вектор, практически не встречается при minSdkVersion >= 21) через рефлексию был доступен любой публичный метод объекта. На API 17+ доступны только методы с аннотацией @JavascriptInterface - и реальный вектор сегодня именно в них: разработчики экспортируют методы с доступом к токенам, файловой системе или IPC. Видел случай, когда через @JavascriptInterface торчал метод getAuthToken() - и он возвращал действующий Bearer-токен.Флаг
setAllowFileAccess(true) и setAllowFileAccessFromFileURLs(true) позволяет JS-коду запущенному в WebView читать локальные файлы приложения из директории /data/data...Exported ContentProvider. Если провайдер экспортирован без permission-атрибута, любое приложение может запросить данные. Проверка через ADB:
adb shell content query --uri content://com.target.app.provider/users. Если возвращаются данные без аутентификации - это data exfiltration. Именно это я нашёл в примере из вступления.MASVS-NETWORK: TLS и certificate pinning
Категория MASVS-NETWORK требует TLS, certificate pinning и отсутствия cleartext HTTP. Что проверять:android:usesCleartextTraffic="true"в манифесте - прямое нарушение, позволяет MitM-атаку (T1557.004)- Network Security Config без pin'ов - приложение доверяет любому CA из системного хранилища, достаточно установить сертификат прокси
- Pin на промежуточный CA вместо leaf - при ротации сертификата pinning ломается, разработчики его отключают «временно», а временное становится постоянным. Классика.
MASVS-RESILIENCE: anti-reverse engineering
Категория MASVS-RESILIENCE описывает защиту от реверса - root detection, anti-debug, anti-emulator, integrity checks. Для пентестера это препятствие, а не цель.Обфускация через ProGuard/R8 превращает имена классов в
a.b.c(), но строковые литералы и URL endpoint'ов остаются - ищите по ним. DexGuard/iXGuard шифруют строки и добавляют integrity-проверки - тут помогает Frida: хуки на String constructor или StringBuilder.toString() показывают расшифрованные строки в runtime. Это оправдывает переход к динамическому анализу Android вместо попыток статического разбора обфусцированного кода. По документации DexGuard обещает «надёжную защиту от реверса». На практике - Frida ломает эту защиту за час-два.Выбор вектора: decision tree для Android пентеста
Не каждый APK заслуживает полного reverse engineering. Мобильный пентест - это методика выбора наиболее эффективного вектора под конкретные условия:| Условие | Вектор | Инструмент | Контекст |
|---|---|---|---|
APK debuggable (android:debuggable="true") | Прямой доступ к sandbox без root | adb run-as | Grey box, внутренний пентест |
| Exported ContentProvider без permission | Data exfiltration через content URI | adb shell content query, drozer | Внешний и внутренний пентест |
| Кастомная URI-схема без App Links верификации | Deeplink hijacking, кража OAuth-токенов | PoC-приложение, adb shell am start | Bug bounty, внешний пентест |
WebView + addJavascriptInterface + ненадёжный источник | JavaScript → Java bridge RCE | Frida + crafted HTML | Внешний пентест |
| SSL pinning через Java-реализацию | Обход → перехват API-трафика | objection, Frida | Любой контекст |
| SSL pinning через нативную библиотеку | Кастомный хук на .so | Frida Interceptor + Ghidra | Продвинутый внутренний пентест |
| Root detection без нативных проверок | Magisk DenyList | Magisk | Стандартный сценарий |
| Root detection + Frida detection (RASP) | Кастомная сборка Frida, Frida Gadget | Модифицированный Frida | Продвинутый, банковские приложения |
| Тяжёлая обфускация (DexGuard) | Динамический анализ вместо статического | Frida runtime hooking | Любой контекст |
| Пентест без root, non-debuggable APK | Статика + deeplinks + exported components + трафик через VPN-прокси | jadx, adb, прокси | Ограниченный scope |
Логика простая: начинайте с наименее затратного вектора. Если APK debuggable - sandbox открыт без root. Если есть exported components - проверяйте их до того, как возиться с SSL pinning. Frida и реверс нативного кода - последний рубеж, когда остальные вектора исчерпаны.
Где мобильный пентест ломается: ограничения техник
Ни один инструмент мобильного пентеста не универсален. Конкретные ситуации, где стандартный подход не работает:Frida detection (RASP).
Приложения с RASP-интеграцией (Promon SHIELD, Guardsquare iXGuard) детектят Frida по нескольким признакам: имя процесса
frida-server, открытый порт 27042, строки gum-js-loop и frida-agent в /proc/self/maps. Обходы существуют - кастомная сборка Frida с изменёнными строками, использование Frida Gadget вместо frida-server с инъекцией в APK - но это эскалация затрат на порядок. Не на каждом проекте бюджет позволяет потратить два дня на сборку кастомной Frida.Play Integrity API. Серверная аттестация целостности устройства от Google. Обход на уровне Frida невозможен - ответ верифицируется на стороне сервера. Magisk с модулями для маскировки bootloader-статуса работает ограниченно и ломается с каждым обновлением API. Если приложение жёстко зависит от Play Integrity, полноценный динамический анализ возможен только через бинарный патчинг APK (удаление проверки) или white box с помощью разработчика.
Нативный код (NDK). Критическая логика в
.so-библиотеках - jadx бесполезен, нужен Ghidra или IDA Pro для ARM-реверса. Frida Interceptor работает с нативными функциями, но в stripped binary без символов адреса приходится искать вручную через exports-анализ или pattern scanning. На проектах, где ядро логики в NDK, время на реверс увеличивается в 3-5 раз. Это та ситуация, когда «препарирование» .so под Ghidra напоминает хирургическую операцию вслепую.Пентест без root.
На нерутованном устройстве без debuggable-флага возможности сужаются: статический анализ APK, перехват трафика через VPN-based прокси (если нет pinning), тестирование deeplinks через
adb shell am start, проверка exported components через adb shell content query. Для полноценного динамического анализа Android нужен root или debuggable-сборка от заказчика.Flutter / React Native. Кроссплатформенные фреймворки усложняют пентест Android приложений. Flutter использует Dart AOT-компиляцию - jadx декомпилирует только тонкую Java-обёртку, основная логика в
libapp.so. React Native упаковывает JS-бандл - искать его в assets APK и анализировать отдельно. Стандартные Frida-скрипты для SSL pinning bypass на Flutter-приложениях не работают - нужны специализированные скрипты для Dart SecurityContext. Каждый такой фреймворк - отдельный зоопарк со своими правилами.Подход к мобильному пентесту за последние пару лет сдвинулся, и мало кто проговаривает это вслух. OWASP MASTG даёт структуру, MobSF автоматизирует первый проход, Frida решает 80% задач динамического анализа - и разработчики адаптировались. Банковские приложения в 2025 году уже не хранят токены в SharedPreferences открытым текстом и обычно не оставляют ContentProvider без permission (хотя, как показывает мой пример из вступления, исключения случаются чаще, чем хотелось бы). Реальные баги сместились на уровень глубже: в логику deeplink-маршрутизации, в race condition между серверной валидацией и клиентским кэшем, в WebView-конфигурации внутри SDK третьих сторон, которые разработчик не писал и не аудировал.
Стандартный чеклист по MASVS покрывает значительную часть поверхности атаки, но часть живёт в бизнес-логике и SDK-зависимостях, и ни один автоматизированный сканер их не достаёт. Если мобильный пентест ограничивается прогоном MobSF, обходом SSL pinning и проверкой SharedPreferences - закрывается только то, что разработчик и так закроет при первом же аудите. Настоящие находки - там, где автоматика заканчивается и начинается ручной реверс конкретной бизнес-логики. В моих последних десяти пентестах большинство критических багов были именно в этой зоне - в нестандартных интеграциях, а не в классических OWASP-категориях. И чем активнее индустрия внедряет RASP и Play Integrity, тем больше пентест мобильных приложений становится инженерной задачей по обходу конкретных продуктов, а не проверкой по чеклисту. На курсе WAPT эту цепочку - от статики до эксплуатации deeplink и WebView - проходят в нескольких модулях с лабами, где можно набить руку на реальных паттернах, а не на учебных примерах.
Последнее редактирование модератором: