
Помощник для оценки Android deeplink, Intent и WebView bridge для этичного взлома
Помощник для оценки Android deeplink, Intent и WebView bridge
apk-interceptor — это портативный APK для тестирования Android в рамках авторизованных оценок безопасности приложений. Он помогает инженерам по безопасности проверить, как Android-приложение обрабатывает внешние точки входа, такие как пользовательские схемы URI, deeplink, экспортированные Activity и WebView JavaScript bridge.
Инструмент намеренно ограничен:
android.permission.INTERNETcontent://Во время оценки безопасности Android-приложений многие находки статического анализа всё ещё требуют небольшого Proof of Concept на устройстве, прежде чем они могут быть подтверждены: регистрация пользовательской схемы URI, отправка явного Intent, предоставление локальной полезной нагрузки content:// или проверка, может ли JavaScript достичь WebView bridge.
Создание нового одноразового тестового приложения для каждого случая повторяемо и чревато ошибками. Небольшие различия в записях манифеста, authority, предоставлении URI, именах пакетов или построении Intent могут замедлить проверку и сделать результаты менее воспроизводимыми.
apk-interceptor был создан, чтобы сделать этот шаг подтверждения повторяемым. Вместо написания нового PoC APK для каждой оценки вы собираете этот инструмент с нужной авторизованной схемой или идентификатором приложения, запускаете тест на устройстве и сохраняете рабочий процесс ограниченным по проекту: без разрешения INTERNET, без передачи данных вовне, без выполнения команд оболочки и без зависимости от root.
apk-interceptor полезен для следующих задач оценки:
Подробные разборы уязвимостей:
content://Приложение ведет журнал оценки в памяти для отправленных Intent, полученных deeplink, обратных вызовов bridge, результатов JavaScript и ошибок. Журналы исчезают, когда процесс приложения убит. Поскольку журналы не сохраняются, фиксируйте доказательства с помощью скриншотов или записи экрана во время работы.
apk-interceptor — это инструмент подтверждения, а не фреймворк для обнаружения или эксплуатации. Он предполагает, что вы уже знаете, что тестировать (схема, класс Activity, имя bridge) из статического анализа, и предоставляет безопасный способ на устройстве проверить достижимость и зафиксировать доказательства. Он создан для установки на устройство оценки и даже для передачи клиенту, поэтому не требует разрешения INTERNET, выполнения команд оболочки, эксфильтрации данных и root.
Где он находится рядом с обычными инструментами Android:
Две области, в которых apk-interceptor имеет наиболее явное преимущество перед альтернативами:
adb/статический анализ не могут показать.content:// → WebView bridge: неэкспортированный однофайловый провайдер, нагрузка которого доставляется только через временное разрешение Intent на чтение, плюс локальный тестовый WebView для предварительной проверки синтаксиса нагрузки.apk-interceptor по-разному относится к отправке и перехвату, и это самое важное, что нужно понять перед использованием:
| Действие | Модуль | Нужна ли пользовательская схема во время сборки? |
|---|---|---|
| Отправить Intent или deeplink в другое приложение | Sender | Нет, можно ввести любой URI, пакет или Activity во время выполнения |
| Перехватить (получить) deeplink для пользовательской схемы | Interceptor | Да, схема фиксируется в APK во время сборки |
Чтобы отправить подготовленный deeplink в оцениваемое приложение, пересобирать не нужно: используйте режим Implicit Deeplink на вкладке Sender и введите любой URI.
Чтобы перехватить deeplink, то есть заставить Android направить пользовательскую схему на apk-interceptor, чтобы вы могли наблюдать возможный перехват схемы, вы должны собрать APK с этой схемой через --scheme. Схема фиксируется во время сборки намеренно (проектное ограничение); apk-interceptor никогда не регистрирует произвольные схемы во время выполнения. Если вы меняете оцениваемую схему, пересоберите и переустановите.
adb для установки на устройство и дополнительного тестирования из командной строкиСоберите APK с пользовательской схемой URI, которую вы авторизованы оценивать:
./build-interceptor.sh --scheme <authorized_custom_scheme>
adb install ./out/apk-interceptor-<authorized_custom_scheme>-debug.apk
Необязательные флаги сборки:
./build-interceptor.sh \
--scheme <authorized_custom_scheme> \
--app-id <custom.application.id> \
--output ./out
--app-id устанавливает идентификатор установленного приложения (идентификатор пакета на устройстве и authority content://<applicationId>.payload) во время сборки. По умолчанию — com.sterrasec.apkinterceptor. Переопределите с помощью --app-id, когда вам нужно несколько отдельных устанавливаемых сборок для разных оценок. Эквивалент для Windows — build-interceptor.bat.
Схема по умолчанию intercept-poc-example — безвредный заполнитель. Скрипт сборки отказывается создавать оценочный APK с этой схемой по умолчанию.
При первом запуске каждой версии приложения apk-interceptor показывает диалог авторизованного использования. После нажатия I understand та же версия больше не показывает диалог. На вкладке Sender по-прежнему отображается постоянное предупреждение, так как она может отправлять Intent другим приложениям.
| Sender | Payload | Interceptor |
|---|---|---|
![]() | ![]() | ![]() |
Используйте эту вкладку для проверки перехвата пользовательской схемы URI.
Что она показывает:
Базовый рабочий процесс:
О Send Test Deeplink: он всегда отправляет <scheme>://test?<your params> с фиксированным хостом test, поэтому предназначен для подтверждения того, что apk-interceptor получает и регистрирует схему, а не для управления конкретными маршрутами deeplink оцениваемого приложения. Чтобы отправить подготовленный deeplink, соответствующий требуемому хосту или пути оцениваемого приложения, используйте вместо этого режим Implicit Deeplink на вкладке Sender.
Пример через adb:
adb shell am start -W \
-a android.intent.action.VIEW \
-d 'my-authorized-scheme://test?source=adb\&message=hello%20world'
Используйте \& при отправке нескольких параметров запроса через adb shell; в противном случае оболочка устройства может интерпретировать & как разделитель команд.
Ожидаемый результат:
RECEIVEDИспользуйте эту вкладку для отправки контролируемых Intent во время авторизованного теста.
Режимы:
Intent(ACTION_VIEW, Uri.parse(uri))Поля и элементы управления:
Рабочий процесс с неявным deeplink:
Рабочий процесс с явной Activity:
Примечания:
content:// полезно при проверке, передаёт ли целевая Activity непроверенные данные Intent в WebView.data Intent, что перезапишет URI, который вы вводите в режиме Implicit Deeplink, поэтому опция там скрыта.PayloadProvider не экспортирован. Оцениваемое приложение может прочитать прикреплённый content:// полезной нагрузки только потому, что Intent предоставляет ему временное разрешение на чтение через FLAG_GRANT_READ_URI_PERMISSION. Оставьте этот флаг включённым и доставляйте URI через Intent. URI content://, открытый любым другим способом, не будет читаться другим приложением.Используйте эту вкладку для создания локальной HTML-нагрузки и проверки синтаксиса JavaScript bridge в собственном тестовом WebView apk-interceptor.
Что она содержит:
content://Формат сгенерированного URI нагрузки:
content://<applicationId>.payload/current.html
Провайдер обслуживает только этот фиксированный файл:
filesDir/payloads/current.html
Рабочий процесс самопроверки нагрузки:
localBridge.BRIDGE_RESULT, console.log и evaluateJavascript result в журнале.Пример JavaScript для самопроверки:
console.log("payload loaded");
window.localBridge.logResult(window.localBridge.getInfo());
Тестовый bridge предоставляет:
window.<bridgeName>.logResult("message");
window.<bridgeName>.getInfo();
Важное ограничение:
Тестовый WebView подтверждает, что ваша локальная нагрузка и синтаксис вызова bridge работают внутри apk-interceptor. Он не может наблюдать, выполнил ли WebView другого приложения вашу нагрузку или вызвал собственный bridge. Для оцениваемого приложения проверяйте через его UI, логи, тестовые перехватчики или Chrome DevTools, если приложение отлаживаемо.
Риск:
Android-приложение регистрирует пользовательскую схему URI вместо проверенной App Link. Любое другое приложение может зарегистрировать ту же самую схему, поэтому Android может показать выбор приложений или направить ссылки в другое приложение.
Используйте apk-interceptor, чтобы проверить:
Шаги:
Доказательства для фиксации:
Риск:
Оцениваемое приложение доверяет параметрам deeplink для навигации, загрузки URL, флагов функций, выбора учётной записи или рендеринга без достаточной проверки.
Используйте apk-interceptor, чтобы проверить:
Шаги:
Пример заполнителя:
my-authorized-scheme://open?next=https%3A%2F%2Fauthorized-test.example%2Flanding
Не используйте реальные сторонние домены или учётные записи, если они явно не входят в область оценки.
Риск:
Экспортированная Activity выполняет чувствительные действия или отображает чувствительные данные без проверки вызывающего, состояния пользователя или требуемой авторизации.
Используйте apk-interceptor, чтобы проверить:
Шаги:
content://.Доказательства для фиксации:
content://Риск:
Оцениваемое приложение загружает непроверенные данные Intent content:// в WebView, который также раскрывает JavaScript bridge через addJavascriptInterface.
Используйте apk-interceptor, чтобы проверить:
content://Шаги:
Важное ограничение:
apk-interceptor не может получать результаты от другого приложения, если только это приложение явно не возвращает или не отображает их. Инструмент предназначен для доставки локальной нагрузки и проверки синтаксиса, а не для эксфильтрации данных.
Убедитесь, что APK не запрашивает сетевой доступ:
aapt dump permissions ./out/apk-interceptor-<scheme>-debug.apk
Ожидаемый результат: отсутствие android.permission.INTERNET.
Запустить deeplink явно в apk-interceptor:
adb shell am start -W \
-n com.sterrasec.apkinterceptor/.InterceptActivity \
-a android.intent.action.VIEW \
-d 'my-authorized-scheme://test?source=adb'
Запустить deeplink через резолвер Android:
adb shell am start -W \
-a android.intent.action.VIEW \
-d 'my-authorized-scheme://test?source=adb'
Явная команда подтверждает поведение InterceptActivity. Неявная команда подтверждает Intent-фильтр манифеста и поведение резолвера.
Модульные тесты выполняются на JVM с Robolectric, поэтому устройство или эмулятор не требуются. Они покрывают PayloadProvider, включая проверки белого списка путей и обхода, которые не позволяют провайдеру обслуживать что-либо, кроме единственной полезной нагрузки current.html.
./gradlew testDebugUnitTest
Результаты тестов записываются в app/build/reports/tests/testDebugUnitTest/index.html. Та же задача выполняется в CI при каждом push и pull request в main.
android.permission.INTERNET/current.html обслуживается PayloadProviderMIT
| Сценарий | Модуль | Что помогает проверить |
|---|
| Перехват пользовательской схемы URI | Interceptor | Может ли другое приложение зарегистрировать ту же пользовательскую схему и получать ссылки |
| Обработка параметров deeplink | Sender | Принимает ли оцениваемое приложение небезопасные параметры запроса/пути |
| Экспонирование экспортированной Activity | Sender | Может ли экспортированная Activity быть запущена напрямую другим приложением |
Экспонирование WebView bridge через content:// | Payload + Sender | Может ли локальная HTML-нагрузка достичь WebView JavaScript bridge |
| Проверка синтаксиса локальной нагрузки | Payload | Выполняется ли ваша HTML/JS нагрузка в тестовом WebView |
| Инструмент | Роль | Чем отличается apk-interceptor |
|---|
| jadx / MobSF / QARK / Semgrep | Поиск уязвимых точек входа (статический) | apk-interceptor не сканирует и не декомпилирует; он подтверждает находку, которая у вас уже есть |
deep-C / NSdeepLink / adb am start | Перечисление и отправка deeplink | apk-interceptor тоже может отправлять, но его отличительная особенность — приём перехваченной схемы и отображение точного URI и параметров |
| drozer | Общий фреймворк атак на устройстве (агент + часто root) | apk-interceptor — это один легковесный APK с преднамеренными защитными ограничениями, более узкой областью применения и более простым безопасным распространением клиентам |
| Metasploit / Frida | Вооружение или перехват (например, addJavascriptInterface RCE) | apk-interceptor проверяет только достижимость bridge с безвредной нагрузкой; он никогда не эксфильтрует и не выполняет команды оболочки |