Распечатанный фрагмент AndroidManifest.xml на бумаге с обведённой строкой экспортируемого компонента. Рядом планшет с запросом к провайдеру контента, латунное пресс-папье и перьевая ручка.


Пентест 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)
После мобильного пентеста результаты ложатся в пост-эксплуатацию: украденный OAuth-токен из SharedPreferences становится вектором lateral movement к backend API; deeplink-redirect превращается в фишинговую атаку на пользователей. Мобильный клиент - не конечная цель, а точка опоры для дальнейшего продвижения.

Требования к окружению для тестирования безопасности 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
Сетевые условия: статический анализ работает полностью offline. Динамический анализ Android требует сетевого взаимодействия с backend приложения. Прокси-сервер должен быть доступен из сети эмулятора или устройства.

Статический анализ 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: инструменты статического анализа​

ИнструментПреимуществаОграниченияКогда использоватьКогда не использовать
jadxJava-подобный вывод, GUI + CLI, быстрый поискНе справляется с тяжёлой обфускацией (DexGuard), нет smali-редактированияПервый проход: анализ логики, поиск секретовAPK обфусцирован DexGuard/iXGuard
apktoolПолный разбор ресурсов, smali-код, пересборка APKsmali сложнее для чтения, чем JavaМодификация APK, патчинг, анализ ресурсовБыстрый review логики
MobSFАвтоматизация, HTML-отчёт, интеграция в CI/CDPattern 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
Для обхода SSL pinning через objection - самый быстрый путь к перехвату трафика:
Код:
objection -g com.target.app explore
# В консоли objection:
android sslpinning disable
Objection хукает стандартные реализации pinning: 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);
    };
});
Ограничение: этот подход работает только против Java-уровневых проверок. Нативный код, вызывающий 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 с правами администратора
Эти находки соответствуют T1005 (Data from Local System) и T1552.001 (Credentials In Files) по MITRE ATT&CK.

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 без rootadb run-asGrey box, внутренний пентест
Exported ContentProvider без permissionData exfiltration через content URIadb shell content query, drozerВнешний и внутренний пентест
Кастомная URI-схема без App Links верификацииDeeplink hijacking, кража OAuth-токеновPoC-приложение, adb shell am startBug bounty, внешний пентест
WebView + addJavascriptInterface + ненадёжный источникJavaScript → Java bridge RCEFrida + crafted HTMLВнешний пентест
SSL pinning через Java-реализациюОбход → перехват API-трафикаobjection, FridaЛюбой контекст
SSL pinning через нативную библиотекуКастомный хук на .soFrida Interceptor + GhidraПродвинутый внутренний пентест
Root detection без нативных проверокMagisk DenyListMagiskСтандартный сценарий
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).
1780034272226.webp

Приложения с 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.
3d2cb344-22de-4f75-83ac-3cdc8924a321.webp

На нерутованном устройстве без 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 - проходят в нескольких модулях с лабами, где можно набить руку на реальных паттернах, а не на учебных примерах.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab