Блог Roxie Mobile

Как разрабатывать безопасные Android-приложения

18 мая 2020 4 582
Android разработка, Безопасность

Создание безопасных мобильных приложений — это первоочередная задача для большинства разработчиков, поскольку важно сохранять доверие пользователей и целостность данных. В этой статье мы познакомимся с некоторыми рекомендациями, которые следует соблюдать при создании Android приложений, чтобы не допускать уязвимостей.

Поддерживайте безопасное взаимодействие с другими приложениями

A. Используйте неявные Intent, чтобы показывался экран, с помощью которого пользователь сможет выбрать одно из нескольких приложений для дальнейшего действия. Это позволит пользователям передавать конфиденциальную информацию тому приложению, которому они доверяют.

Б. Используйте разрешения на основе подписей при обмене данными между двумя вашими приложениями. Такие разрешения не требуют дополнительных подтверждений от пользователя. Вместо этого происходит проверка того, что приложения, которые обращаются к данным, подписаны с помощью одного и того же ключа. Следовательно, для пользователя всё выглядит проще и безопаснее.

1
2
3
4
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <permission android:name="my_custom_permission_name"
                android:protectionLevel="signature" />

C. Неэкспортируемые поставщики контента. Если вы не собираетесь делиться данными с другими приложениями, явно запретите им обращаться к вашему ContentProvider, прописав в манифесте android:exported=»false» (по умолчанию «true» для версий Android ниже 4.4).

Обезопасьте сетевые взаимодействия

Обеспечьте безопасность сетевых соединений с помощью HTTPS и SSL — для любых сетевых запросов, используйте HTTPS (вместо обычного HTTP) с правильно настроенными сертификатами. Подробнее смотрите здесь.

Безопасное соединение с сервером можно настроить следующими способами:

А. Для взаимодействия с веб-сервером, у которого настроен сертификат от известного доверенного центра, дополнительные действия при выполнении HTTP-запросов не требуются.

1
2
3
4
5
6
val url = URL("https://www.google.com")
val urlConnection = url.openConnection() as HttpsURLConnection
urlConnection.connect()
urlConnection.inputStream.use {
...
}

Б. Добавив конфигурацию сетевой безопасности: если ваше приложение использует новые или пользовательские центры сертификации, можно задать собственные настройки сетевой безопасности в конфигурационном файле. Это позволит вам создать конфигурацию не изменяя код приложения.

Чтобы добавить файл конфигурации в приложение, нужно сделать следующее:

i) Пропишите конфигурацию в манифесте приложения:

1
2
3
4
5
6
7
<manifest ... >
    <application
        android:networkSecurityConfig="@xml/network_security_config"
        ... >
        <!-- Place child elements of <application> element here. -->
    </application>
</manifest>

ii) Создайте XML-файл ресурсов res/xm/network_security_config.xml.

Укажите, что весь обмен данными с соответствующими доменами должен производиться только по HTTPS, отключив незащищённые сетевые взаимодействия:

1
2
3
4
5
6
<network-security-config>
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">secure.example.com</domain>
        ...
    </domain-config>
</network-security-config>

В процессе разработки можно использовать элемент <debug-overrides>, чтобы явно разрешить пользовательские сертификаты. Этот элемент переопределяет критически важные параметры сетевой безопасности при отладке и тестировании приложения, не влияя на релизную конфигурацию. Следующий отрывок кода показывает, как использовать этот элемент в XML-файле конфигурации сетевой безопасности:

1
2
3
4
5
6
7
<network-security-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>

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

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

Г. Привязка сертификатов. Можно настроить приложение на работу только с определённым набором сертификатов путем ограничения списка доверенных центров сертификации или же с помощью привязки сертификатов.

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

Другие сценарии: есть ещё несколько моментов, которые следует учитывать при получении вашим приложением доступа к данным через Интернет:

  1. Используйте объекты WebView осторожно: объекты WebView в вашем приложении не должны позволять пользователям переходить на сайты, которые вам неподконтрольны. Кроме того, поддержка JavaScript должна быть разрешена только в том случае, если вы полностью контролируете и доверяете содержимому в объектах WebView вашего приложения.
    Для связи между веб-сайтом и приложением используйте HTML каналы сообщений вместо evaluateJavascript(). Ознакомьтесь с документацией Android, чтобы узнать больше о безопасном использовании WebView.
  2. Используйте высокоуровневую аутентификацию. Механизмы аутентификации играют ключевую роль в безопасности мобильных приложений. Конфиденциальную информацию можно надёжно защитить при помощи многофакторной аутентификации, продуманного управления сессиями и системой отключения. Также, для большей безопасности приложений, важно настроить расширенную авторизацию с поддержкой таких инструментов как OAuth 2.0 или JSON веб-токены.

Запрашивайте правильные разрешения

Приложение должно запрашивать лишь минимум разрешений, необходимый для его корректной работы.

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

На пример, если вашему приложению нужно добавить контакт, то делегируйте это действие приложению Контакты, у которого уже есть соответствующее разрешение WRITE_CONTACTS.

Безопасность хранения данных

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

Ниже приведены рекомендации по хранению данных на устройстве.

А. Храните личные данные во внутреннем хранилище

Храните все личные данные пользователей во внутреннем хранилище устройства, которое изолировано от других приложений. Для доступа к этим файлам не нужно запрашивать разрешение, но другим приложениям такие файлы недоступны. Если пользователь удалит приложение, то все файлы, которые приложение сохраняло во внутреннее хранилище, также будут удалены. Кроме того, рассмотрите вариант использования EncryptedFile из библиотеки Security, вместо объектов File.

Б. Осторожно используйте внешнее хранилище

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

Используйте ограниченный доступ к директориям: если приложению нужно обращаться лишь к определенной директории во внешнем хранилище устройства, то используйте область видимости, тем самым ограничив вашему приложению доступ к внешнему хранилищу устройства.

Файлы, связанные с приложением: если файл не содержит персональную или конфиденциальную информацию, но является значимым для пользователя только в контексте вашего приложения, то храните файл в директории конкретного приложения во внешнем хранилище.

В. Храните неконфиденциальные данные в файлах кэша

Для предоставления быстрого доступа к неконфиденциальным данным приложения храните их в кэше устройства. Если размер кэша превышает 1 Мб, то используйте getExternalCacheDir(). В противном случае используйте getCacheDir(). Оба метода вернут вам объект File, который содержит закэшированные данные приложения.

Г. Используйте SharedPreferences в приватном режиме

Используйте MODE_PRIVATE при создании и получении объектов SharedPreferences с помощью getSharedPreferences(), чтобы ваше приложение смогло получить информацию из файла общих настроек.

Кроме того, для усиления безопасности следует использовать EncryptedSharedPreferences, который оборачивает класс SharedPreferences и автоматически шифрует ключи и значения.

Постоянно обновляйте зависимости и библиотеки, чтобы обеспечить их большую безопасность

Сжимайте, обфусцируйте и оптимизируйте код с помощью компилятора R8

Если вы собираете проект с помощью Android Gradle 3.4.0 или более поздней версии, то в данном плагине больше не используется ProGuard для оптимизации кода во время компиляции. Вместо этого задействуется компилятор R8, чтобы во время компиляции выполнить следующие задачи:

  • Сжатие кода (или перетряхивание дерева): обнаруживает и безопасно удаляет неиспользуемые классы, поля, методы и атрибуты из приложения и его зависимостей (что делает его ценным инструментом для обхода ограничения в 64k ссылок).
  • Сжатие ресурсов: удаляет неиспользуемые ресурсы из упакованного приложения, а так же из его зависимостей.
  • Обфускация: сокращает имена классов и методов, благодаря чему уменьшаются размеры DEX-файлов приложения.
  • Оптимизация: проверяет и реорганизует код так, чтобы еще больше уменьшить размер DEX-файлов приложения.

Заключение

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

Оригинал статьи: тут

Запросить консультацию