Отсутствие проверки на root-доступ
Критичность: СРЕДНЯЯ | |
Способ обнаружения: IAST |
Описание
Запуск и работа приложений в ОС без проверки окружения может нести значительные риски.
Злоумышленник или легальный пользователь могут запускать приложение на устройстве с правами root с целью создания фейковых аккаунтов, накруток различных показателей, исследования взаимодействия приложения с ОС и другими приложениями, а также исследования взаимодействия приложения по сети, в том числе с серверной частью (исследование API). Установка и работа в таком окружении значительно снижает безопасность данных пользователя и потенциально увеличивает риск финансовых и репутационных потерь для поставщика приложения.
Запуск приложения на устройстве, на котором пользователь имеет права root, серьезно снижает существующие защитные механизмы ОС Андроид. Пользователю и в некоторых случаях приложениям становятся доступны приватное хранилище, запуск неэкспортированных компонентов и другие опасные действия.
Рекомендации
Приложение при запуске и во время работы должно проверять косвенные и непосредственные значения параметров ОС, указывающие на наличие прав root и эмулятора.
Для определения прав root возможны следующие проверки:
-
Поиск файлов из списка:
"su"
,"busybox"
,"supersu"
,"Superuser.apk"
,"KingoUser.apk"
,"SuperSu.apk"
,"magisk"
, к примеру:public static final String[] paths = {"/system", "/system/bin", "/system/sbin", "/system/xbin", "/vendor/bin", "/sbin", "/etc"}; public boolean chekBinaryFile(String fileName) { boolean result = false; for (String path : paths) { if (new File(path, fileName).exists()) { Log.d("detect", "binary " + fileName + "detected"); result = true; } } return result; }
-
Проверка наличия характерных для «рутованных» устройств пакетов:
"com.noshufou.android.su"
,"com.noshufou.android.su.elite"
,"eu.chainfire.supersu"
,"com.koushikdutta.superuser"
,"com.thirdparty.superuser"
,"com.yellowes.su"
,"com.koushikdutta.rommanager"
,"com.koushikdutta.rommanager.license"
,"com.dimonvideo.luckypatcher"
,"com.chelpus.lackypatch"
,"com.ramdroid.appquarantine"
,"com.ramdroid.appquarantinepro"
,"com.devadvance.rootcloak"
,"com.devadvance.rootcloakplus"
,"de.robv.android.xposed.installer"
,"com.saurik.substrate"
,"com.zachspong.temprootremovejb"
,"com.amphoras.hidemyroot"
,"com.amphoras.hidemyrootadfree"
,"com.formyhm.hiderootPremium"
,"com.formyhm.hideroot"
,"me.phh.superuser"
,"eu.chainfire.supersu.pro"
,"com.kingouser.com"
,"com.topjohnwu.magisk"
.Пример кода:
String[] rootPackages = { "com.noshufou.android.su", "com.noshufou.android.su.elite", "eu.chainfire.supersu", "com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.koushikdutta.rommanager", "com.koushikdutta.rommanager.license", "com.dimonvideo.luckypatcher", "com.chelpus.lackypatch", "com.ramdroid.appquarantine", "com.ramdroid.appquarantinepro", "com.devadvance.rootcloak", "com.devadvance.rootcloakplus", "de.robv.android.xposed.installer", "com.saurik.substrate", "com.zachspong.temprootremovejb", "com.amphoras.hidemyroot", "com.amphoras.hidemyrootadfree", "com.formyhm.hiderootPremium", "com.formyhm.hideroot", "me.phh.superuser", "eu.chainfire.supersu.pro", "com.kingouser.com", "com.topjohnwu.magisk", "com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.topjohnwu.magisk", "com.kingroot.kinguser", "com.kingo.root", "com.smedialink.oneclickroot", "com.zhiqupk.root.global", "com.alephzain.framaroot", "com.koushikdutta.rommanager", "com.koushikdutta.rommanager.license", "com.dimonvideo.luckypatcher", "com.chelpus.lackypatch", "com.ramdroid.appquarantine", "com.ramdroid.appquarantinepro", "com.android.vending.billing.InAppBillingService.COIN", "com.chelpus.luckypatcher" }; boolean checkRootPackages(String[] arr) { List<String> pkgs = Arrays.asList(arr); StringBuilder s = new StringBuilder(); PackageManager pm = getPackageManager(); for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.GET_META_DATA)) { if (pkgs.contains(packageInfo.packageName)) { return true; } } return false; }
-
Проверка системных свойств:
"ro.build.selinux"
,"ro.debuggable"
,"service.adb.root"
,"ro.secure"
.Пример кода:
try { propertyStream = Runtime.getRuntime().exec("getprop").getInputStream(); } catch (IOException | NoSuchElementException e) { e.printStackTrace(); } if (propertyStream == null) { // no accesss to getprop } else { BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(propertyStream)); StringBuilder log = new StringBuilder(); String line; try { while ((line = bufferedReader.readLine()) != null) { //getprop возвращает список свойств в виде списка // [<propertyName>]:[<propertyvalue>] }
-
Запуск команд через shell, к примеру поиск бинарного файла su (
process = Runtime.getRuntime().exec(new String[]{"which", "su"});
) -
Проверка режимов доступа к файлам и директориям.
Можно проверить, имеются ли права на чтение для директории /data
.
Для проверки наличия этих прав могут использоваться методы Java API:
-
File.canRead
, -
File.canWrite
, -
а также метод языка C —
access()
.
Также, можно попытаться создать временный файл в одной из директорий (для проверки прав записи) или прочитать содержимое директории (для проверки прав чтения).
или
- Проверка запущенных процессов/приложений
Метод ActivityManager.getRunningAppProcesses
возвращает список запущенных процессов.
Он может быть использован для поиска тех приложений, которые требуют root-привилегий.
Аналогично, методы getRunningServices
и/или getRecentTasks
могут быть использованы для поиска запущенных сервисов и задач приложений.
И еще несколько советов:
-
Не используйте стандартные имена переменных
isRooted/ rooted
. -
Можно использовать простую модель с накоплением и границей. То есть, для каждой проверки назначается некоторый вес и, при превышении порогового значения, приложение считает, что устройство скомпроментировано.
-
Нужно продумать, что именно делать в случае обнаружения root, запрещать ли пользователю работать с приложением или просто уведомлять его? Также хорошо бы передавать эту информацию в профильные подразделения, например в антифрод.
-
Одним из хороших способов является использование библиотек DetectFrida и DetectMagiskHide. Данные библиотеки реализуют проверки в нативном коде, что существенно усложняет их анализ и модификацию.
-
Стоит учитывать, что существуют приложения, которые скрывают root-доступ и определить его будет сложнее:
-
Magisk.
-
RootCloak.
-