1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-android-app-sec-guidebook

Клонировать/Скачать
5.2.3.md 27 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 27.11.2024 20:24 c13bfb7

В запросе текст технической направленности из области разработки и тестирования программного обеспечения. Основной язык текста запроса — английский.

Перевод текста на русский язык:

В поддельном AndroidManifest.xml пользователя объясняется обнаружение подделки прав доступа пользователя. Однако подделка приложения не ограничивается только правами доступа, во многих других случаях приложение используется без каких-либо изменений исходного кода. Например, просто заменив ресурсы на свои собственные, они распространяют приложения других разработчиков (подделывают) на рынок, как если бы они были их собственными приложениями. Здесь мы покажем более общий метод обнаружения подделки APK-файла.

Чтобы подделать APK, необходимо декодировать APK-файл в папку и файлы, изменить его содержимое, а затем перестроить его в новый APK-файл. Поскольку у фальсификатора нет ключа оригинального разработчика, он должен использовать свой собственный ключ для подписания нового APK-файла. Поскольку подделка APK неизбежно приведёт к изменению подписи (сертификата), можно сравнить сертификат в APK с сертификатом разработчика, встроенным в исходный код, чтобы определить, было ли оно подделано во время выполнения.

Вот пример кода. Кроме того, профессиональные хакеры смогут легко обойти обнаружение подделки. Обратите внимание, что это простой пример реализации, пожалуйста, примените этот пример кода к своему приложению.

Основные моменты:

  1. Перед началом основной операции проверьте, принадлежит ли сертификат приложения разработчику.

SignatureCheckActivity.java

package org.jssec.android.permission.signcheckactivity;

import org.jssec.android.shared.PkgCert;
import org.jssec.android.shared.Utils;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;

public class SignatureCheckActivity extends Activity {

    // Self signed certificate hash value
    private static String sMyCertHash = null;
    
    private static String myCertHash(Context context) {
        if (sMyCertHash == null) {
            if (Utils.isDebuggable(context)) {
                // Certificate hash value of "androiddebugkey" of debug.
                sMyCertHash = "0EFB7236 328348A9 89718BAD DF57F544 D5CCB4AE B9DB34BC 1E29DD26 F77C8255";
            } else {
                // Certificate hash value of "my company key" of keystore
                sMyCertHash = "D397D343 A5CBC10F 4EDDEB7C A10062DE 5690984F 1FB9E88B D7B3A7C2 42E142CA";
            }
        }
        return sMyCertHash;
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // *** POINT 1 *** Verify that an application's certificate belongs to the developer before major processing is started
        if (!PkgCert.test(this, this.getPackageName(), myCertHash(this))) {
            Toast.makeText(this, "Self-sign match NG", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        Toast.makeText(this, "Self-sign match OK", Toast.LENGTH_LONG).show();
    }
}

PkgCert.java

package org.jssec.android.shared;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;

public class PkgCert {

    public static boolean test(Context ctx, String pkgname, String correctHash) {
        if (correctHash == null) return false;
        correctHash = correctHash.replaceAll(" ", "");
        return correctHash.equals(hash(ctx, pkgname));
    }
    
    public static String hash(Context ctx, String pkgname) {
        if (pkgname == null) return null;
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pkginfo = pm.getPackageInfo(pkgname, PackageManager.GET_SIGNATURES);
            if (pkginfo.signatures.length != 1) return null; // Will not handle multiple signatures.
            Signature sig = pkginfo.signatures[0];
            byte[] cert = sig.toByteArray();
            byte[] sha256 = computeSha256(cert);
            return byte2hex(sha256);
        } catch (NameNotFoundException e) {
            return null;
        }
    }
    
    private static byte[] computeSha256(byte[] data) {
        try {
            return MessageDigest.getInstance("SHA-256").digest(data);
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }
    
    private static String byte2hex(byte[] data) {
        if (data == null) return null;
        final StringBuilder hexadecimal = new StringBuilder();
        for (final byte b : data) {
            hexadecimal.append(String.format("%02X", b));
        }
        return hexadecimal.toString();
    }}

5.2.3.4 Проблема повторного делегирования полномочий

При доступе к контактной информации или GPS, которые содержат защищённую информацию и функции Android OS, приложение должно объявить использование разрешений. Когда необходимые разрешения предоставляются, полномочия делегируются приложению, и приложение сможет получить доступ к защищённой информации и функциям.

Согласно дизайну программы, приложение, которому предоставлены разрешения, может получить защищённые данные. Кроме того, приложение может предоставить защищённые данные другому приложению без необходимости обеспечивать те же разрешения, что равносильно тому, что приложение без разрешений может получить доступ к данным, защищённым разрешениями. Это фактически повторное делегирование полномочий, называемое проблемой повторного делегирования разрешений. Поэтому только Управление правами доступа в Android: защита данных и предотвращение несанкционированного доступа

Для управления прямым доступом к данным из сторонних приложений используется механизм прав доступа Android.

На рисунке 5.2-9 показан конкретный пример. Приложение в центре демонстрирует, что оно объявило о своём использовании права android.permission.READ_CONTACTS, чтобы читать контакты, а затем сохранять их в своей собственной базе данных. Если информация, которая уже была сохранена, передаётся через контент-провайдера другому приложению без каких-либо ограничений, возникает проблема повторного предоставления прав.

В качестве аналогичного примера можно привести приложение, которое объявило о своем использовании права android.permission.CALL_PHONE. Оно использует это право для получения телефонного номера от другого приложения (возможно, введённого пользователем), но не объявило такое же право. Если номер будет вызван без проверки пользователя, также возникнет проблема повторного предоставления прав.

Иногда необходимо, чтобы другое приложение предоставило данные или функциональные возможности, которые были получены с помощью прав доступа. В таких случаях приложение-поставщик должно требовать те же права для сохранения исходного уровня защиты. Кроме того, если предоставляется только часть информации или функциональных возможностей, уровень защиты должен быть соответствующим образом адаптирован в зависимости от степени ущерба, который может быть нанесён этой частью. Можно использовать меры защиты, подобные тем, что описаны в разделе «4.1.1.1 Создание/использование частных действий» или «4.1.1.4 Создание/использование частных действий», чтобы подтвердить согласие пользователя и установить ограничения на действия целевого приложения и другие.

Эта проблема повторного предоставления прав не ограничивается только Android. Для приложений Android получение необходимой информации и функциональных возможностей из других приложений, сетей и носителей данных является обычным делом. Во многих случаях доступ к ним требует определённых прав и ограничений. Например, если источником является другое Android-приложение, то это право; если это сеть, то это механизм аутентификации; если это носитель данных, то существуют ограничения доступа. Поэтому после тщательного рассмотрения необходимо реализовать эти меры в приложении, поскольку информация и функции не должны использоваться способом, противоречащим намерениям пользователя. Это особенно важно, когда информация или функции предоставляются косвенно другому приложению или переносятся в сеть или на носитель данных. При необходимости вы должны обеспечить соблюдение прав или ограничений на использование прав, таких как права Android. Запрос согласия пользователя является частью решения.

В следующем коде мы демонстрируем ситуацию, где приложение, использующее право READ_CONTACTS для доступа к списку контактов, обеспечивает соблюдение этого же права для целевой информации.

Ключевые моменты:

  • Обеспечение соблюдения поставщиком тех же прав.
  • В файле AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.jssec.android.permission.transferpermission"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk
        android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".TransferPermissionActivity"
            android:label="@string/title_activity_transfer_permission">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:name=".TransferPermissionContentProvider"
            <!-- *** Point1 *** Enforce the same permission that the provider does. -->
            android:authorities="org.jssec.android.permission.transferpermission"
            android:enabled="true"
            android:exported="true"
            android:readPermission="android.permission.READ_CONTACTS">
        </provider>
    </application>
</manifest>

Если приложение обеспечивает несколько прав, этот метод не решает проблему. Используя Context#checkCallingPermission() или PackageManager#checkPermission(), он проверяет, объявлено ли в манифесте вызывающего приложения использование всех прав, указанных в uses-permission.

В активности:

public void onCreate(Bundle savedInstanceState) {
    [...]
    
    if (checkCallingPermission("android.permission.READ_CONTACTS") == PackageManager.PERMISSION_GRANTED
        && checkCallingPermission("android.permission.WRITE_CONTACTS") == PackageManager.PERMISSION_GRANTED) {
        // Processing during the time when an invoker is correctly declaring to use
        return;
    }
    finish();
}

5.2.3.5 Механизм проверки подписи разрешений (Android 5.0 и выше)

Начиная с Android 5.0 (API Level 21), если выполняются следующие условия, невозможно установить приложение, определяющее собственные разрешения:

  • На устройстве уже установлено другое приложение, которое определяет то же пользовательское разрешение с тем же именем.
  • Приложение использует другой ключ подписи.

Когда приложение с защищённой функцией (компонентом) и приложение, использующее эту функцию, определяют пользовательские разрешения с одинаковыми именами и используют одну и ту же подпись ключа, описанный выше механизм предотвращает установку приложений с такими же именами, определённых другими компаниями. Однако, как указано в «5.2.2.3 Пользовательские подписанные разрешения должны определяться только в приложениях поставщика (обязательно)», этот механизм не подходит для проверки того, определены ли пользовательские разрешения вашей собственной компанией, поскольку разрешения могут стать недействительными, если другое приложение будет удалено без вашего ведома.

Таким образом, при определении пользовательских подписанных разрешений в вашем приложении на Android 5.0 (API Level 21) и более поздних версиях вам необходимо соблюдать два правила: «5.2.2.3 Определять пользовательские подписанные разрешения только в приложениях провайдера (обязательно)» и «5.2.2.4 Проверять, определяются ли внутренние подписанные разрешения внутренним приложением (обязательно)».

5.2.3.6 Изменения в модели разрешений Android версии 6.0 и выше

Android 6.0 (API Level 23) представил изменения в модели разрешений, влияющие на дизайн и стандарты приложений. В этом разделе мы рассмотрим модель разрешений в Android 6.0 и более поздних версиях.

Момент предоставления и отказа в разрешениях

Если приложение объявляет об использовании разрешений, требующих подтверждения пользователя (опасные разрешения) [см. раздел «5.2.2.1 Разрешения системы Android, опасные для безопасности активов пользователя (обязательно)»], Android 5.1 (уровень API 22) и предыдущие версии требуют отображать список этих разрешений при установке приложения, и пользователь должен предоставить все разрешения для продолжения установки. В этот момент все разрешения, объявленные приложением (включая разрешения, отличные от опасных разрешений), предоставляются приложению; как только эти разрешения предоставлены приложению, они остаются действительными до тех пор, пока приложение не будет удалено с устройства.

Однако в стандартах Android 6.0 и более поздних версий разрешения предоставляются во время выполнения. Разрешения не предоставляются при установке приложения. Когда приложение выполняет процесс, требующий опасных разрешений, необходимо проверить, были ли эти разрешения заранее предоставлены приложению; если нет, необходимо отобразить окно подтверждения в операционной системе Android, запрашивая согласие пользователя [25]. Если пользователь предоставляет разрешения из окна подтверждения, разрешения предоставляются приложению. Однако предоставленные пользователю разрешения (опасные разрешения) могут быть отозваны через меню настроек (рисунок 5.2–10). По этой причине необходимо реализовать соответствующий процесс, чтобы гарантировать, что приложение не ведёт себя ненадлежащим образом, даже если доступ к необходимой информации или функциям невозможен из-за отсутствия предоставленных разрешений.

[25] Поскольку обычные разрешения и подписанные разрешения автоматически предоставляются операционной системой Android, нет необходимости получать подтверждение пользователя для этих разрешений. Например, для получения доступа к чтению информации из календаря требуются следующие разрешения: android.permission.READ_CALENDAR, а для записи данных в календарь — android.permission.WRITE_CALENDAR. Оба разрешения связаны с группой разрешений android.permission-group.CALENDAR

В новой модели разрешений на Android 6.0 и более поздних версиях предоставление и отзыв разрешений можно выполнять через группы разрешений. Таким образом, если приложение во время работы запрашивает разрешение android.permission.READ_CALENDAR и пользователь соглашается на запрос, операционная система Android действует так, как если бы были предоставлены оба разрешения — android.permission.READ_CALENDAR и android.permission.WRITE_CALENDAR. Если впоследствии будет запрошено разрешение android.permission.WRITE_CALENDAR, операционная система не будет отображать диалоговое окно для пользователя, а предоставит разрешение напрямую.

Для получения дополнительной информации о классификации групп разрешений обратитесь к документации для разработчиков (http://developer.android.com/intl/ja/guide/topics/security/permissions.html#perm-groups).

Влияние изменений в стандартах на область применения

Изменения в стандартах касаются только ситуаций, когда приложения запрашивают разрешения во время выполнения на устройствах под управлением Android 6.0 или более поздней версии, и значение targetSDKVersion приложения равно 23 или выше. Если устройство работает под управлением версии Android ниже 5.1 или значение targetSDKVersion приложения меньше 22, то при установке будут полностью запрашиваться и предоставляться все разрешения, как и раньше. Однако если устройство работает под управлением Android версии 6.0 или выше, даже если значение targetSDKVersion приложения ниже 23, предоставленные пользователю разрешения могут быть отозваны в любое время. Это может привести к неожиданному завершению работы приложения. Разработчики должны следовать изменённым стандартам или установить значение maxSDKVersion равным 22 или ниже, чтобы гарантировать, что приложение не может быть установлено на устройства под управлением Android 6.0 (API Level 23) или более поздних версий (Таблица 5.2-1).

Таблица 5.2-1

Версия ОС Android Значение targetSDKVersion Момент предоставления разрешений Возможность контроля разрешений пользователем
>= 6.0 >= 23 Во время выполнения Да
>= 6.0 < 23 При установке Да (требуется быстрая реакция)
<= 5.1 >= 23 При установке Нет
<= 5.1 < 23 При установке Нет

Однако следует отметить, что влияние maxSdkVersion ограничено. Когда значение maxSdkVersion установлено равным 22 или ниже, устройства под управлением Android 6.0 (API Level 23) и более поздних версий больше не считаются подходящими устройствами для установки целевых приложений в Google Play. С другой стороны, поскольку проверка значения maxSdkVersion не проводится за пределами Google Play, целевые приложения всё ещё могут быть установлены на устройствах под управлением Android 6.0 (API Level 23) или более поздних версий. Из-за ограниченного эффекта maxSdkVersion, Google не рекомендует его использовать. Рекомендуется, чтобы разработчики немедленно следовали изменённым стандартам.

На устройствах под управлением версий Android 6.0 и выше уровень защиты следующих разрешений сетевого взаимодействия изменился с опасного на нормальный. Поэтому, даже если приложение заявляет об использовании этих разрешений, явное согласие пользователя не требуется, и изменённые стандарты не оказывают влияния в этом случае.

  • android.permission.BLUETOOTH
  • android.permission.BLUETOOTH_ADMIN
  • android.permission.CHANGE_WIFI_MULTICAST_STATE
  • android.permission.CHANGE_WIFI_STATE
  • android.permission.CHANGE_WIMAX_STATE
  • android.permission.DISABLE_KEYGUARD
  • android.permission.INTERNET
  • android.permission.NFC

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-android-app-sec-guidebook.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-android-app-sec-guidebook.git
oschina-mirror
wizardforcel-android-app-sec-guidebook
wizardforcel-android-app-sec-guidebook
master