Android Guards – Telegram
Android Guards
3.8K subscribers
93 photos
1 video
7 files
222 links
Статьи, исследования, полезные ссылки и многое другое из мира безопасности Android платформы и приложений. Только проверенный контент!

YouTube: https://www.youtube.com/c/AndroidGuards

Поблагодарить: https://news.1rj.ru/str/+oMgsdsq2ydY5MjQy
Download Telegram
Начиная с Java 9 стал доступен инструмент JShell. Фактически это такой же REPL как в python или других языках, но только для Java. И это весьма удобная штука. Особенно когда в приложениях попадаются конструкции вида Class a = Class.forName(new String(new byte[]{106,97,118,97,46,108,97,110,103,46,83,116,114,105,110,103})); и нужно быстро понять что это за класс вообще. Да, эти байтики можно разобрать чем угодно. А если там используется какая-то специфика Java, которую не всегда просто переложить на другие языки? Подобные механизмы защиты также могут включать в себя отдельные библиотеки в виде jar-файлов и все это сильно усложнит вам жизнь при попытке разобрать это в каком-нибудь питоне. А в jshell можно просто закидывать java-код и играть с ним как душе угодно. Сторонние jar-ники также можно подкидывать через параметры команды, и вообще посмотрите на выдачу jshell -h, там есть интересные опции.
#aht
🤔9👍2
Современные приложения на Xamarin хранят dll-ки в XABA архиве, который лежит в ресурсах приложения по пути assemblies/assemblies.blob (могут быть также разделены по архитектурам). Там же рядом лежит assemblies.manifest с списком всех сборок. Для того чтобы извлечь все сборки в виде dll-файлов и спокойно реверсить, можно воспользоваться утилитой pyxamstore. Она также умеет собирать все обратно.
#aht
👍152🔥1😢1
Там ребята опять собираются делать Standoff Hacks в ноябре, и, по уже сложившейся традиции объявили конкурс чтобы на мероприятие попали не только известные (и всем надоевшие!) личности, но и свежая кровь. Всего есть 6 инвайтов и 1 бонусный. Все условия читайте здесь, повторяться не хочу. От себя добавлю, что мероприятие действительно крутое. Позволяет очень сильно подумать мозгами и посоревноваться с очень толковыми людьми. Я был на двух прошлых, и впечатления исключительно положительные. Вопрос: какого Фрейда ты пишешь это в канале про мобилки? Ответ: что на первом, что на втором хаксе в скоупе были мобилки. Очень много мобилок. Не за все из них платили хорошо и местами мне приходилось сильно бодаться с триажерами, но все равно это очень полезный и интересный опыт. Давайте уже развивать мобильное багбаунти, а то все веб да веб...

P.S. А на этот хакс меня пока не позвали... Видимо придется в конкурсе участвовать 🌚
👍7👎3🥰2🤡21
Перехват трафика приложений на Xamarin выглядит довольно изученной темой. Но так выглядит ровно до тех пор пока не сталкиваешься со странностями из-за которых почему-то ничего не работает как нужно. Про перехват трафика я уже писал большую статью, и если у вас что-то не получается с перехватом, то лучше обратиться к ней. Но базовый алгоритм для Xamarin я все же напишу здесь:
1. Сбросить все настройки прокси, которые были сделаны до этого (wifi или глобальный). Смартфон должен иметь чистый доступ к интернету.
2. Убедиться, что все MITM-сертификаты установлены корректно как в пользовательское, так и в системное хранилище. А лучше накатить их заново выгрузив из текущей версии burp.
3. В настройках прокси, в burp, выставить галочку Support invisible proxy (во вкладке Request handling)
4. Закинуть на смартфон этот скрипт, зайти в adb под root-ом и выполнить его.

Если ничего не заработало, то путь самурая начинается здесь...
#aht
🔥7👍2
Порой очень хочется поработать с т.н. "скрытым" API в Android. Есть несколько способов дотянуться до этой возможности. Самый простой - включить эту настройку через adb с помощью команды: adb shell settings put global hidden_api_policy 1. Но это может не сработать, и getDeclaredMethod будет падать с ошибкой. Тогда на помощь приходит вот такой трюк:
val parcel = Parcel.obtain()  
val writeString8 = parcel::class.java.declaredMethods.filter { it.name == "writeString8" }[0]
writeString8.invoke(parcel,scheme)

Здесь метод writeString8 получается не напрямую, а через поиск по коллекции методов. Кому интересно почему это работает - смотрите исходники.
#aht
👍151
Умение обходить фильтры - очень важный навык. Обычно он складывается из двух компонентов: развитого аналитического мышления и знания трюков. Сегодня будут трюки. Представим себе такой синтетический фильтр:
val input = "http://evil.com"

val filter = """^(https?)://.*@?evil\..+""".toRegex()

if (filter.matches(input)) {
throw MalformedURLException("Banned URL!")
}

val okhttp = OkHttpClient()
val req = Request.Builder().url(URL(input)).build()


Есть мысли как его обойти? Подумайте 30 секунд.

Один из способов - модифицировать input любым из этих способов:
- url:http://evil.com
- http://evil.com (первый символ - пробел)

Но проверка по черному списку встречается все реже. Кажется, что разработчики начинают что-то подозревать 😰
#aht
👍13👎1😱1
Продолжая тему фильтров стоит сказать про более сложный в эксплуатации вариант - фильтрация по белому списку. Приложение может принимать только заданный список доменов и отклонять все остальные. Но варианты эксплуатации есть и в этом случае. Нужно сместить фокус внимания на список разрешенных доменов и искать проблемы уже в них. Допустим мы хотим грузить произвольный контент в WebView. В этом случае может помочь найденная на одном из доменов белого списка уязвимость CRLF. Чаще всего ее можно трансформировать в возможность внедрения произвольного HTML, а там уже и XSS и все остальные приятные штуки с этим связанные. Сам эксплойт может выглядеть как-то так:
val payload = "%0d%0aContent-Length:35%0d%0aX-XSS-Protection:0%0d%0a%0d%0a23%0d%0a<noscript%20onload=alert(document.domain)>%0d%0a0%0d%0a/%2f%2e%2e"  

val i = Intent().apply {
setClassName("com.app.victim", "com.app.victim.WebViewActivity")
putExtra("url", "https://whitelisted.victim.com/$payload")
}

startActivity(i)

Подробнее: раз, два.
#aht
👍8🤔1
Android предоставляет весьма широкие возможности по логированию различных событий. Одним из наиболее полезных, на мой взгляд, является логирование SQL запросов, которые делают приложения. Не важно, напрямую или через ORM. В логах будут те запросы, которые непосредственно выполняет БД. Включить эту возможность можно командой: adb shell setprop log.tag.SQLiteStatements VERBOSE. После чего в logcat должны появиться логи запросов. А если поискать в исходниках Android ссылки на метод isLoggable, то можно найти другие подобные теги и включить логирование для них аналогичным способом.
#aht
🔥17👍1
Параметризация скриптов для Frida может быть весьма полезной опцией когда написать что-то сложное уже нужно, но делать обертки на python пока не хочется. В этой ситуации поможет следующий трюк:
'use strict';

var argv = {};

rpc.exports = {
init: function (stage, parameters) {
argv = parameters;
},
};

Java.perform(function() {
if (argv.debug) {
console.log('Debug message');
}
console.log('Main flow');
});


Теперь, если запустить фриду вот так:
frida -U -f com.myapp -l hook.js -P '{"debug":true}', то сработает ветка условия с отладочным сообщением.
#aht
🔥16
Для удобной работы с Binder есть классная утилита с весьма экстравагантным названием: BDSM. Она сильно упрощает ковыряния в этой области системы, и позволяет например получить список всех системных сервисов и их методов (если AIDL загружен), а также узнать кто в системе использует этот сервис. Для демонстрации покажу как получить инфу по всем соединениям с БД и запросам: su -c bdsm dump dbinfo

Да, все эти возможности можно получить написав свое тестовое приложение и дергая в нем Context.getSystemService(..), но во-первых это требует гораздо больше телодвижений, а во-вторых названия сервисов еще нужно добыть из документации. А с помощью утилиты, просто вбиваем JCOLOR=1 su -c bdsm list и получаем все доступные сервисы. Ну и конечно ее можно использовать в сложных пайплайнах и скриптах.
Обязательно почитайте документацию!
#aht
🔥13😁9👍4
Это должна была быть короткая заметка в Telegram, но потом что-то пошло не так... Делюсь своими мыслями по поводу новой редакции OWASP Mobile Top Ten 2023. Обсуждения приветствуются!
🔥22
Чтобы не копировать каждый раз базу данных с устройства можно воспользоваться утилитой входящей в Android Studio: View -> Tool Windows -> App Inspection -> Database Inspector. Он покажет все базы данных с которыми работает приложение и даст возможность в них поковыряться. Единственный нюанс: приложение должно иметь флаг android:debuggable=true, иначе инспектор просто не увидит такое приложение. Установить этот флаг очень просто: разбираем приложение с помощью apktool, добавляем флаг в application и собираем заново.
#aht
🔥12👍4
Android собирает разную интересную статистику по использованию смартфона, которая может быть полезна товарищу майору специалистам по форензике. Одним из таких инструментов являются логи доступа к приложениям. Они показывают когда работали с приложением и сколько времени это заняло.

В простом варианте эти логи можно получить если в звонилке набрать "секретный код" *#*#4636#*#*. Откроется UsageStatsActivity из приложения Settings, в которой нужно ткнуть Usage statistics (другие пункты тоже обязательно потыкайте, там тоже интересно).

Более расширенную версию этих логов можно получить с помощью команды adb shell dumpsys usagestats | less и позалипать на прекрасное.

Отдельно скажу про комбинации вида *#*#<код>#*#*: их довольно много в системных приложениях, а также подобные комбинации используют обычные клиентские приложения для доступа ко всяким отладочным интерфейсам и не только.
#aht
👍23🔥1🤔1
Продолжим тему секретных кодов. Я покажу один из возможных способов их извлечения через dumpsys. Тут придется немного погрепать или что-то заскриптовать чтобы выглядело красиво, но в базовом варианте команда будет выглядеть так: adb shell dumpsys package -f | grep -A 5 "android.provider.Telephony.SECRET_CODE". Далее можно или бездумно вводить каждый код, пытаясь понять почему же он не работает, или исследовать receiver который этот код слушает.

В самих же кодах нет никакой магии. Например код *#*#225#*#* отправленный из звонилки приведет к отправке intent-а с URI: android_secret_code://225, который и будет разбирать целевой receiver. А это значит, что можно отправить такой intent из своего приложения, и если в receiver-е нет проверки на action, то он будет обработан. Так можно проэксплуатировать какую-нибудь уязвимость в receiver-е.
#aht
🔥16👍3🤔2
У ребят из Стингрей вышла статья про то, как магазины приложений проверяют приложения на уязвимости. Спойлер: очень плохо проверяют.

В общем-то для меня это довольно очевидное положение дел. Почему? Да потому что статический анализ приложений это сложно. Вероятно, если отдавать магазинам *.map файлы для деобфускации, то дело пошло бы лучше, но в здравом уме так делать никто не будет. Поэтому анализаторы вынуждены пытаться наковырять что-то в обфусцированной каше, которая может быть изначально написана на любых пришедших в голову разработчика технологиях. Даже навигация в приложениях до сих пор не стандартизирована. И скорее всего не будет =)
Короче, результат немного предсказуем и показывает что даже у Google нет нормального taint анализа и хорошо работающих подходов к автоматизированному сканированию приложений. Возможно ситуация улучшится с изобретением AGI, но это не точно ;)

В общем, господа разработчики - безопасность это ваша ответственность и никто кроме вас ее в приложении не сделает.
👍16
Ситуация: приложение хранит в keystore ключи, которые использует для шифрования/расшифровки некоторых данных в запросах. Возможности поставить хуки — нет. Нужно извлечь ключи. Сделать это на устройстве не выйдет, там hardware-backed keystore. Поэтому ставим приложение на эмулятор, проходим сценарий во время которого создаются ключи и забираем с эмулятора файл /data/misc/keystore/persistent.sqlite
Далее, делаем к этой базе запрос:
SELECT KE.id, KE.alias, BE.blob
FROM keyentry as KE
JOIN blobentry as BE
ON BE.keyentryid = KE.id
WHERE KE.alias = 'secret'
Должны вернуться две записи. Одна для приватного, вторая для публичного ключа. Выгружаем содержимое поля blob в файлы blob1 и blob2 и натравливаем binwalk чтобы понять где какой ключ. Теперь выполняем команды для извлечения и перекодирования ключей:
$ openssl x509 -in blob1 -pubkey -noout > pub.pem
$ binwalk -D "private key":.der blob2
$ openssl rsa -in extracted.der -text > priv.pem

Все, теперь у нас есть ключи, которые использует приложение 😎
#aht
👍26🔥15🌭5
В нативных библиотеках можно найти много интересного. Но что если в приложении их штук 50, и не очень понятно с какими из них приложение работает напрямую, а какие являются зависимостями для других библиотек. Можно поискать по коду ключевое слово native, которое используется для обозначения методов вызываемых из библиотек, а можно поступить чуть-чуть проще и сразу увидеть всю возможную поверхность атаки c помощью утилиты nm. Для этого нужно распаковать приложение и выполнить следующую команду в директории с библиотеками:
$ nm -A -D *.so | grep -E "(Java_|JNI_OnLoad)" 2>/dev/null

В ответ получаем примерно следующее:
libTransform.so: 00000b8c T Java_com_huawei_location_lite_common_util_coordinateconverter_Transform_gcj02to84Native
libTransform.so: 000008ec T Java_com_huawei_location_lite_common_util_coordinateconverter_Transform_wgs84to02Native
libcrashlytics-handler.so: 00006968 T JNI_OnLoad
libcrashlytics.so: 00006f58 T JNI_OnLoad

Что помогает быстро понять какие библиотечные функции доступны в JVM мире.
#aht
👍241
Если приложение пытается бороться с фридой и не дает себя хукать, то можно попробовать поставить альтернативную сборку этого фреймворка, которая содержит полезные патчи, способные отстрелить базовые методы детекта. Патчи построены в основном на рандомизации и кодировании имен различных компонентов, чтобы понизить узнаваемость фриды для систем безопасности. Код патчей однозначно стоит изучить, потому что это хорошая отправная точка для создания собственной сборки со своим уникальным набором патчей, что позволит избегать обнаружения более успешно. Для любителей ставить фриду из модуля MagiskFrida, я сделал форк, который вместо оригинального репозитория, подтягивает уже запатченную фриду и собирает ее в модуль для Magisk. Сам форк не очень красивый, и PR-ы для улучшения приветствуются.
#aht
👍19
Классный доклад с удачным примером бинарной эксплуатации небезопасной десериализации в приложении AliExpress. Всем кто не стесняется заглядывать на уровень ниже виртуальной машины - однозначно рекомендую посмотреть.

Финальный эксплойт забирайте здесь. Пароль на архив: cc79dc9a77483e3de7c75c39bd13b41b
🔥172👍1
Существует много сценариев в которых приложение кидает юзера в веб, а потом через редирект возвращает обратно. Проблема том, что приложение может не знать про все возможные редиректы, которые происходят в вебе, а значит не учитывать какие-то из них. Если в url-е такого редиректа содержатся важные данные, то их можно перехватить создав activity с intent-фильтром под этот редирект:
<intent-filter android:label="Перейти в приложение">  
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="victim.com"
android:pathPrefix="/pages/sensitive/data"
android:scheme="https" />
</intent-filter>

После редиректа в уязвимом приложении, появится стандартный диалог, где будет браузер и приложение хакера. Нужно пошаманить с иконкой, чтобы юзер захотел кликнуть 😋 И после клика, данные улетят в приложение злоумышленника.
#aht
👍30😁2🔥1🤣1
Рубрика #aht прощается с вами.

Это был очередной эксперимент с контентом канала, который я считаю в общем-то удачным. Но, как и всякий эксперимент, этот тоже должен быть завершен. Я поддерживал эту рубрику практически год, и в ней вышло 49 постов, которые, судя по реакциям, были кому-то полезны. У меня есть еще идеи для контента, часть из которых я планирую начать реализовывать с начала следующего года. Как всегда — без спойлеров. Чтобы оставить себе пространство для маневра 🙃Всех с наступающим!
😢51👍18🤝4🤔3🤬1