Содержание статьи
- Почитать
- StrandHogg — уязвимость с «подменой» приложений
- Обход защиты на снятие скриншотов
- Обход ограничения на доступ к камере, микрофону и местоположению в фоне
- Разработчику
- Хорошие и плохие приемы программирования на Kotlin
- Typealias в Kotlin
- Инлайновые классы в Kotlin
- Корректное выделение текста на фоне
- Статистика распределения версий Android
- Инструменты
- Библиотеки
Почитать
StrandHogg — уязвимость с «подменой» приложений
The StrandHogg vulnerability — подробности нашумевшей уязвимости всех версий Android (включая 10), позволяющей подменить экран (активность) одного приложения на экран другого.
Что произошло: специалисты норвежской компании Promon обнаружили в Android уязвимость, которая позволяет подменить экран (активность) легитимного приложения, подсунув вместо нее экран зловредного приложения. В результате у злоумышленников появляется возможность провести атаку с использованием фишинга или, например, запросить для зловредного приложения дополнительные полномочия якобы от лица другого приложения.
Что произошло на самом деле: в Android у активностей есть флаг taskAffinity
. Он позволяет указать имя задачи (task), в стек активностей которой попадет указанное приложение. Это нужно для более тонкого управления стеками обратных переходов. Но есть одна проблема: по умолчанию значение taskAffinity
равно имени пакета приложения, а это значит, что в ряде случаев можно незаметно всунуть активность своего приложения в стек активностей чужого. А если еще и указать флаг allowTaskReparenting="true"
, эту активность можно передвинуть на самый верх и при следующем клике по иконке целевого приложения она появится на экране первой (то есть будет находиться на вершине стека).
Страшно? Конечно, но, как и обычно, стоит копнуть глубже — и страх пройдет.
Во-первых, об этой «уязвимости» известно уже много лет. Предыдущая ее вариация называлась Android Task Hijacking, и мы писали о ней еще в 2017 году.
Во-вторых, эксплуатация уязвимости требует, чтобы и зловредное приложение, и приложение-жертва были уже запущены. Последовательность действий пользователя должна быть такой: он запускает приложение-жертву, возвращается на рабочий стол, затем запускает зловредное приложение, затем снова запускает приложение-жертву. В этот момент вместо холодного запуска Android просто показывает самую «верхнюю» активность в стеке, а ей оказывается активность зловредного приложения.
В-третьих, Google действительно отказывается исправлять уязвимость на протяжении нескольких лет. Просто потому, что это так называемый design flaw, то есть ошибка проектирования, исправление которой сломает существующий софт.
Наконец, в-четвертых, у проблемы уже давно есть решение. Достаточно указать taskAffinity=""
в элементе Application
, и все активности твоего приложения станут неуязвимы к атаке.
Мораль: не читайте советских газет, читайте доки по безопасности.
Обход защиты на снятие скриншотов
Android Frida hooking: disabling FLAG_SECURE — статья о том, как с помощью Frida отключить защиту на снятие скриншота приложения.
Кратко: Android позволяет разработчику приложения запретить снимать скриншоты определенных активностей приложения. Для этого необходимо установить флаг FLAG_SECURE
для окна:
public class FlagSecureTestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.main);
...
}
}
Обойти эту защиту можно несколькими способами. Например, использовать модуль Xposed DisableFlagSecure, который перехватывает функцию setFlags
и просто отфильтровывает флаг FLAG_SECURE
:
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedHelpers.findAndHookMethod(Window.class, "setFlags", int.class, int.class, mRemoveSecureFlagHook);
}
private final XC_MethodHook mRemoveSecureFlagHook = new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Integer flags = (Integer) param.args[0];
flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
param.args[0] = flags;
}
};
Однако Xposed требует права root на устройстве (есть проект VirtualXposed, не требующий root, но многие модули в нем не работают). Frida, с другой стороны, может работать на любом устройстве без необходимости получать права root.
Вот как выглядит тот же код отключения в варианте для Frida:
Java.perform(function () {
var FLAG_SECURE = 0x2000;
var Window = Java.use("android.view.Window");
var setFlags = Window.setFlags;
setFlags.implementation = function (flags, mask) {
console.log("Disabling FLAG_SECURE...");
flags &= ~FLAG_SECURE;
setFlags.call(this, flags, mask);
};
});
Использовать так:
$ frida -U -l наш_скрипт.js -f имя.пакета.приложения --no-pause
Обход ограничения на доступ к камере, микрофону и местоположению в фоне
Androids Invisible Foreground Services and How to (Ab)use Them — доклад с конференции Black Hat Europe 2019 с описанием очень простой техники обхода защиты на доступ к камере, микрофону и местоположению в Android 9 и 10.
Проблема: в Android 9 появилось ограничение на доступ к камере и микрофону, если в данный момент приложение находится в фоне. В Android 10 добавилось ограничение на доступ к местоположению с возможностью выбрать, хочет ли пользователь, чтобы приложение могло получать координаты, только пока видимо на экране, или в фоне тоже.
Исключение дается только приложениям, имеющим активный foreground-сервис, который, в свою очередь, обязан вывести видимое пользователю уведомление и иконку в строке состояния.
Если мы хотим создать гипотетическую малварь, лучше оставаться скрытными и никаких уведомлений не показывать. Но как это сделать?
Решение: начиная с пятой версии в Android есть механизм JobScheduler, который позволяет запускать код периодически или при наступлении определенных событий (например, подключение к зарядному устройству). Мы могли бы использовать его для периодического запуска наших шпионских функций, но задачи JobScheduler’а тоже выполняются в фоне.
Выход состоит в том, чтобы при наступлении события JobScheduler’а запустить сервис, затем сделать его foreground-сервисом с помощью startForeground
, быстро получить доступ к камере, микрофону и местоположению и остановить сервис:
@Override
public int onStartCommand(Intent intent, int flags, int startId){
Notification notification = createCustomNotification();
this.startForeground(1, notification)
accessMicrophone();
stopForeground(true);
return START_STICKY;
}
Трюк состоит в том, что, если сделать работу достаточно быстро (по утверждению автора доклада — за пять секунд), система просто не покажет уведомление.
Proof of concept есть на GitHub. Баг уже исправлен, теперь уведомление будет показано в любом случае.
Разработчику
Хорошие и плохие приемы программирования на Kotlin
Good And Bad Practices Of Coding In Kotlin — статья о практиках программирования на Kotlin, хороших и плохих.
Первый пример
fun main {
val file = File("/my_file")
val writer = file.printWriter()
try {
writer.println("Hello World")
} catch(__: Exception){
// Обработка исключения
} finally {
writer.close()
}
}
Это стандартный способ записи строки в файл: открываем файл и с помощью PrintWriter
записываем строку. В завершение закрываем PrintWriter даже в том случае, если будет выброшено исключение.
Этот код можно переписать так:
fun main () {
val file = File("/my_file")
file.printWriter().use {
it.println("Hello World")
}
}
В случае с объектами, реализующими интерфейс Closeable
(здесь PrintWriter
), функция-расширение use
автоматически вызывает метод close
после выполнения кода лямбды.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»