Недостаточная проверка на запуск на эмуляторе
![]() |
Критичность: СРЕДНЯЯ |
Способ обнаружения: IAST |
Описание
Запуск и работа приложений в ОС без проверки окружения может нести значительные риски.
Злоумышленник или легальный пользователь могут запускать приложение на эмуляторе с целью создания фейковых аккаунтов, накруток различных показателей, исследования взаимодействия приложения с ОС и другими приложениями, а также исследования взаимодействия приложения по сети, в том числе с серверной частью (исследование API). Установка и работа в таком окружении значительно снижает безопасность данных пользователя и потенциально увеличивает риск финансовых и репутационных потерь для поставщика приложения.
Использование эмулятора зачастую противоречит политике и целям производителя приложения. В некоторых случаях установка на эмулятор производится с целью получения прямой выгоды пользователем или преимущества перед другими пользователями. Кроме того, исследование и использование приложений злоумышленниками в большинстве случаев производится также на эмуляторах.
Слабой или недостаточной проверкой на запуск на эмуляторе является использование менее двух проверок разного типа.
Стандартная проверка на эмулятор:
-
SystemProperties;
-
BuildProperites;
-
наличие пакетов, сопутствующих эмуляторам (
"com.bluestacks"
,"com.google.android.launcher.layouts.genymotion"
и т. д.); -
наличие файлов, сопутствующих эмуляторам (
ueventd.ttVM_x86.rc
,fstab.andy
и т. п.); -
проверка мобильного оператора на значение
"Android"
; -
проверка телефонии на наличие известных фейковых значений (проверка номера телефона, проверка
DEVICE_ID
).Примечание
Проверкой одного типа называется проверка, использующая один из методов API. При этом сама проверка может быть использована многократно с разными входными данными. Яркий пример — использование метода
File.exist()
для проверки наличия в файловой системе некоторого перечня файлов. Другой пример — использование статических полей классаBuild
для проверки на эмулятор. Данный класс содержит множество полей, однако их использование относится к одному и тому же типу проверок.
Рекомендации
Приложение при запуске и во время работы должно проверять косвенные и непосредственные значения параметров ОС, указывающие на наличие прав root и эмулятора.
Определение эмулятора:
-
Поиск файлов, характерных для различных эмуляторов:
"ueventd.android_x86.rc"
,"x86.prop"
,"ueventd.ttVM_x86.rc"
,"init.ttVM_x86.rc"
,"fstab.ttVM_x86"
,"fstab.vbox86"
,"init.vbox86.rc"
,"ueventd.vbox86.rc"
,"/dev/socket/qemud"
,"qemud"
,"/dev/qemu_pipe"
,"qemu_pipe"
,"/system/lib/libc_malloc_debug_qemu.so"
,"libc_malloc_debug_qemu.so"
,"/sys/qemu_trace"
,"/system/bin/qemu-props"
,"qemu_trace"
,"qemu-props"
,"/dev/socket/genyd"
,"genyd"
,"/dev/socket/baseband_genyd"
,"baseband_genyd"
,"/dev/goldfish_pipe"
,"goldfish_pipe"
. -
Проверка системных свойств:
"init.svc.qemud"
,"init.svc.qemu-props"
,"qemu.hw.mainkeys"
,"qemu.sf.fake_camera"
,"qemu.sf.lcd_density"
,"ro.bootloader"
,"ro.bootmode"
,"ro.hardware"
,"ro.kernel.android.qemud"
,"ro.kernel.qemu.gles"
,"ro.kernel.qemu"
,"ro.product.device"
,"ro.product.model"
,"ro.product.name"
,"ro.serialno"
,"ro.build.display.id"
,"ro.product.cpu.abi"
,"ro.debuggable"
,"ro.secure"
.Следует учитывать, что проверять надо не наличие или отсутствие свойств, а их значение, например:
ro.debuggable == 0
и т.п. -
Проверка полей класса
Build
:"FINGERPRINT"
,"MODEL"
,"MANUFACTURER"
,"BRAND"
,"BOARD"
,"ID"
,"SERIAL"
,"TAGS"
,"USER"
,"HARDWARE"
,"PRODUCT"
,"TYPE"
.Пример кода:
public static boolean isEmulator() { return (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic") || Build.FINGERPRINT.startsWith("generic") || Build.FINGERPRINT.startsWith("unknown") || Build.HARDWARE.contains("goldfish") || Build.HARDWARE.contains("ranchu") || Build.MODEL.contains("google_sdk") || Build.MODEL.contains("Emulator") || Build.MODEL.contains("Android SDK built for x86") || Build.MANUFACTURER.contains("Genymotion") || Build.PRODUCT.contains("sdk_google") || Build.PRODUCT.contains("google_sdk") || Build.PRODUCT.contains("sdk") || Build.PRODUCT.contains("sdk_x86") || Build.PRODUCT.contains("vbox86p") || Build.PRODUCT.contains("emulator") || Build.PRODUCT.contains("simulator")); }
-
Проверка телефонии: телефонный номер в списке известных фейковых номеров,
device_id
в списке известных фейковыхdevice_id
и т. п. пример кода:static final String[] DEVICE_IDS = { "000000000000000", "e21833235b6eef10", "012345678912345" }; boolean checkDeviceId() { TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); @SuppressLint("HardwareIds") String deviceId = telephonyManager.getDeviceId(); for (String known_deviceId : DEVICE_IDS) { if (known_deviceId.equalsIgnoreCase(deviceId)) { return true; } } return false; }
Информация
При реализации любых проверок следует учитывать, что они не дают 100% гарантии достоверности как положительных, так и отрицательных сигналов. Вследствие огромной фрагментации устройств на Android, всегда может найтись устройство, на котором проверка "обнаружит" эмулятор.
Поэтому лучшим решением будет введение системы скоринга: каждая проверка добавляет некоторый вес к результату, и при превышении определенного порога принимается решение об обнаружении недоверенной среды.