Советы по безопасности

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

Некоторые основные функции безопасности, которые помогут вам создавать безопасные приложения, включают в себя:

  • Песочница приложений Android, которая изолирует ваши данные приложения и выполнение кода от других приложений.
  • Библиотеки приложений с надежными реализациями общей функциональности безопасности, таких как шифрование, разрешения, и безопасное IPC.
  • Такие технологии, как ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD calloc и Linux mmap_min_addr для смягчения рисков, связанных с ошибками управления общей памятью.
  • Зашифрованная файловая система, которая может быть включена для защиты данных на потерянных или украденных устройствах.
  • Пользовательские разрешения для ограничения доступа к функциям системы и пользовательским данным.
  • Разрешения определяемые приложением для управления данными приложения отдельно для каждого приложения.

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

Хранение данных

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

Использование внутреннего хранилища

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

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

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

Использование внешнего хранилища

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

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

Использование поставщика контента

Поставщики контента предлагают структурированный механизм хранения, который может быть ограничен своим собственным приложением или быть экспортированным, разрешая доступ другими приложениями. Если вы не намерены предоставлять доступ другим приложениям к вашему ContentProvider, пометьте его как android:exported=false в манифесте приложения. В противном случае, установите android:exported атрибут "true" , чтобы дать доступ другим приложениям к хранимым данным.

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

Если вы используете поставщик контента для обмена данными между только своими приложениями, то предпочтительнее использовать android:protectionLevel атрибут установлен в "signature" . Разрешение с использованием подписи не требуют подтверждения пользователя, поэтому они обеспечивают лучший пользовательский опыт и более контролируемый доступ к данным поставщика контента, когда приложения доступа к данным подписанные тем же ключом.

Поставщики контента могут также обеспечить более гибкий контроль доступа, объявив android:grantUriPermissions атрибут и используя FLAG_GRANT_READ_URI_PERMISSION и FLAG_GRANT_WRITE_URI_PERMISSION флаги в Intent объекте, который активирует компонент. Объем этих разрешений может быть дополнительно ограничен <grant-uri-permission element>.

При доступе к поставщику контента, используйте параметризованные методы запросов, такие как query(), update(), и delete() чтобы избежать возможных внедрений SQL от ненадежных источников. Заметим, что использование параметризованных методов недостаточно, если selection аргумент построен путем объединения пользовательских данных передаваемых в метод.

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

Использование разрешений

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

Запрос разрешений

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

Если возможно разработать приложение таким образом, что оно не требует никаких разрешений, то это является предпочтительным. Например, вместо запроса доступа к информации об устройстве, чтобы создать уникальный идентификатор, создайте GUID для вашего приложения (см. раздел Обработка данных пользователя). Или, вместо использовании внешних накопителей (которые требуют разрешения), храните данные во внутренней памяти.

В дополнение к запросу разрешений, приложение может использовать <permissions> для защиты IPC, которое чувствительно к безопасности и будет уязвимо из других приложений, таких как ContentProvider. В целом, мы рекомендуем использовать контроль доступа, где это возможно, отличный от того, где пользователь подтверждает разрешения, потому что разрешения могут ввести в заблуждение пользователей. Например, рассмотрите вариант, когда используется уровень защиты signature для разрешения работы с IPC между приложений, предоставляемых одним разработчиком.

Не допускайте утечки данных защищенных разрешениями. Это происходит, когда ваше приложение предоставляет данные через IPC, которое доступно только потому, что имеет специальное разрешение, но не требует наличия этого разрешения у клиентов этого IPC интерфейса. Более подробная информацию о потенциальных последствиях и частоте этого типа проблем описывается в этой исследовательской работе, опубликованной в USENIX: http://www.cs.be rkeley.edu/~afelt/felt_usenixsec2011.pdf

Создание разрешений

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

Если необходимо создать новое разрешение, подумайте, можно ли выполнить вашу задачу с уровнем защиты "signature". Разрешения с использованием подписи прозрачны для пользователей, и разрешает доступ только приложениям подписанным одним и тем же разработчиком при выполнении проверки разрешений.

Если вы создаете разрешение с уровнем защиты "dangerous", Есть целый ряд сложностей, которые необходимо рассмотреть:

  • Разрешение должно иметь строку, лаконично выражающее пользователю решение безопасности, которое они должны принять.
  • Строка разрешения должна быть локализована для разных языков.
  • Пользователи могут отказаться установить приложение, потому что разрешение сбивают с толку или воспринимаются как рискованные.
  • Приложения могут запросить разрешение, когда приложение создающее разрешение ещё не было установлено.

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

Использование сетей

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

Использование IP-сетей

Сеть на Android существенно не отличается от других Linux систем. Ключевым моментом является использование соответствующих протоколов для конфиденциальных данных, таких как HttpsURLConnection для безопасного веб-трафика. Мы предпочитаем использовать HTTPS вместо HTTP во всех случаях, когда HTTPS поддерживается сервером, так как мобильные устройства часто подключаться к небезопасным сетям, таким как общественные Wi-Fi.

Прошедшая проверку, зашифрованная связь на уровне сокетов может быть легко реализована с помощью SSLSocket класса. Учитывая то, как часто устройства Android подключаются к незащищенным беспроводным сетям с использованием Wi-Fi, использование безопасной работы в сети настоятельно рекомендуется для всех приложений, взаимодействующих по сети.

Мы видели некоторые приложения использующие localhost сетевые порты для обработки конфиденциального IPC. Мы не одобряем такой подход, так как эти интерфейсы доступны в других приложениях на устройстве. Вместо этого вы должны использовать Android IPC механизм, где аутентификацию можно выполнить, например, с Service. (Еще хуже, чем использование обратной петли, это привязка к INADDR_ANY, т.к. после этого ваше приложение может получать запросы откуда угодно.)

Кроме того, одна общая проблема, требующая повторения, это необходимость убедиться в том, что вы не доверяете данным, загруженным из HTTP или других небезопасных протоколов. Это включает в себя проверку ввода в WebView и любых ответах на намерения, полученных через HTTP.

Использование сетей телефонии

SMS протокол был в первую очередь предназначен для общения между пользователями и не очень хорошо подходит для передачи данных приложений. Из-за ограничений SMS, мы настоятельно рекомендуем использовать Google Cloud Messaging (GCM) и IP-сети для передачи сообщений с данными с веб-сервера на ваше приложение на устройстве пользователя.

Помните, что SMS не являются зашифрованными, а так же не выполняется сильная проверка подлинности по обе стороны сети или устройства. В частности, любой получатель SMS должен ожидать, что возможно злоумышленник отправил SMS в приложение — Не полагайтесь на не прошедшие подлинность данные из SMS для выполнения чувствительные команд. Кроме того, вы должны знать, что SMS может быть предметом подмены и/или перехвата в сети. На Android устройствах, SMS сообщения передаются как широковещательные намерения, поэтому они могут быть прочитаны или захвачены другими приложениями, которые имеют READ_SMS разрешение.

Выполнение проверки входных данных

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

Если вы используете платформо-зависимый машинный код, то любые данные считанные из файлов, полученные по сети, или полученные через IPC могут потенциально привести к проблемам безопасности. Наиболее распространенные проблемы переполнение буфера, использование после освобождения, и ошибка на единицу. Android предоставляет ряд технологий, таких как ASLR и DEP что уменьшают подобные ошибки, но они не решают основной проблемы. Вы можете предотвратить эти уязвимости аккуратной обработкой указателей и с помощью управляемых буферов.

Динамические языки на основе строк, такие как JavaScript и SQL, также являются предметом обсуждения проблем проверки входных данных, связанных с экранированием символов и внедрения сценариев.

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

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

Обработка данных пользователя

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

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

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

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

Кроме того, убедитесь, что вы случайно не передаете пользовательские данных в другое приложение на устройстве через чрезмерно разрешительное IPC, открытые для записи файлы, или сетевые сокеты. Этот особый случай утечки данных разрешений, обсуждается в разделе Запрос разрешений.

Если GUID необходим, создайте большой, уникальный номер и сохраните его. Не используйте идентификаторы телефона, такие как номер телефона или IMEI, которые могут быть связаны с личной информацией. Более подробное обсуждение читайте в Блоге Android разработчиков.

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

Использование WebView

Т.к. WebView потребляет веб-контент, который может включать HTML и JavaScript, неправильное использование может привести к общим вопросам веб-безопасности, таким как межсайтовый скриптинг (внедрение JavaScript). Android включает в себя ряд механизмов для уменьшения масштабов этих потенциальных проблем, ограничивая возможности WebView до минимальной функциональности, необходимой для приложения.

Если ваше приложение не использует напрямую JavaScript в WebView не вызывайте setJavaScriptEnabled(). Некоторые примеры кода используют этот метод, который вы могли бы перенести в своё приложение, поэтому удалите этот вызов метода, если он вам не требуется. По умолчанию, WebView не выполняет JavaScript, поэтому межсайтовый сценарий не возможен.

Использование addJavaScriptInterface() необходимо делать с особой осторожностью, поскольку он позволяет использовать JavaScript для вызова операций, которые обычно зарезервированы для приложений Android. Если вы используете его, вызывайте addJavaScriptInterface() только для веб-страниц, с которых все входные данные заслуживают доверие. Если возможен ненадежный ввод данных, ненадежный JavaScript сможет вызывать методы Android в вашем приложении. В целом, мы рекомендуем вызывать addJavaScriptInterface() только для JavaScript, который содержится в вашем APK приложения.

Если ваше приложение получает доступ конфиденциальным данным из WebView, вы можете использовать clearCache() метод для удаления любых файлов хранящихся локально. Серверные заголовки, такие как no-cache также могут быть использованы, чтобы указать приложению, что оно не должно кэшировать конкретное содержимое.

Обработка полномочий

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

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

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

После использования AccountManager для получения Account, CREATOR перед передачей любых учетных данных, так что вы случайно не передадите данные неправильному применению.

Если учетные данные будут использоваться только приложениями, которые вы создаете, то вы можете проверить приложение, которое обращается к AccountManager используя checkSignature(). В качестве альтернативы, если только одно приложение будет использовать учетные данные, вы можете использовать KeyStore для хранения.

Использование криптографии

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

В общем, попробуйте использовать самый высокий уровень уже существующей реализации библиотек, которые могут поддерживать ваш вариант использования. Если вам нужно безопасно получать файл с известным местоположением, простой HTTPS URI может быть достаточным и не требует знания криптографии. Если вам нужен защищенный туннель, рассмотрите возможность использования HttpsURLConnection или SSLSocket, а не пишите свой собственный протокол.

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

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

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

Использование межпроцессного взаимодействия

Некоторые приложения пытаются реализовать IPC с использованием традиционных методов Linux, таких как сетевые сокеты и общие файлы. Мы настоятельно рекомендуем вам использовать вместо этого функциональность Android системы для IPC, такие как Intent, Binder или Messenger с Service, и BroadcastReceiver. Механизмы для Android IPC позволяют проверить идентичность приложения, подключаемого к IPC, и установить политику безопасности для каждого механизма IPC.

Многие элементы безопасности являются общими для всех механизмов IPC. Если ваш механизм IPC не предназначен для использования в других приложениях, установите android:exported атрибут в "false" для элемента в манифесте компонента, такого как <service> элемент. Это полезно для приложений, которые состоят из нескольких процессов в том же UID, или если вы решили на поздних стадиях разработки, что вы на самом деле не хотите раскрывать функциональность IPC, но вы не хотите переписывать код.

Если ваш IPC предназначен для доступа из других приложений, можно применить политику безопасности с помощью <permission> элемента. Если IPC используется между своими отдельными приложениями, которые подписаны с тем же ключом, предпочтительно использовать "signature" уровень разрешений в android:protectionLevel.

Использование намерений

Намерения это предпочтительный механизм для асинхронного IPC в Android. В зависимости от требований приложения, вы можете использовать sendBroadcast(), sendOrderedBroadcast(), или явное намерение конкретного компонента приложения.

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

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

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

Использование служб

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

По умолчанию, службы не экспортируются и не могут быть вызваны любым другим приложением. Однако, если вы хотите задать фильтры намерении для объявления службы, то она экспортируются по умолчанию. Лучше всего, если вы явно объявите android:exported атрибут, чтобы убедиться, что он ведет себя как вы хотите. Услуги также могут быть защищены с помощью android:permission атрибута. Поступая таким образом, другие приложения должны будут объявить соответствующие <uses-permission> элементы в своем собственном манифесте, чтобы иметь возможность запускать, останавливать, или выполнить привязку к службе.

Служба может защитить отдельные IPC вызовы при помощи разрешений, вызвав checkCallingPermission() перед выполнением реализации этого вызова. Как правило, мы рекомендуем использовать декларативные разрешения в манифесте, так как те, в меньшей степени подвержены недосмотру.

Использование binder и messenger интерфейсов

Использование Binder или Messenger является предпочтительным механизмом в RPC-стиле IPC в Android. Они обеспечивают четко определенный интерфейс, который позволяет взаимную аутентификацию конечных точек при необходимости.

Мы настоятельно рекомендуем проектирования интерфейсов в манере, которая не требует проверки специфичных разрешений для интерфейса. Binder и Messenger объекты не объявляются в манифесте приложения, и, следовательно, вы не можете применить декларативные разрешения непосредственно к ним. Как правило, они наследуют разрешения, объявленные в манифесте приложения для Service или Activity , в котором они реализованы. Если вы создаете интерфейс, который требует контроля подлинности и/или доступа, эти элементы управления должны быть явно добавлены в качестве кода в Binder или Messenger интерфейс.

Если предоставляется интерфейс, который требует контроля доступа, используйте checkCallingPermission() для проверки, имеет ли вызывающий код необходимые разрешение. Это особенно важно перед доступом к службе от имени вызывающего приложения, как идентификация вашего приложения передаваемая другим интерфейсами. Если запускать интерфейс, предоставляемый Service bindService() вызов может завершиться неудачей, если вы не имеете доступа к данной службе. Если вызывать интерфейс предоставляемый локально вашим собственным приложением, то может быть полезно использовать clearCallingIdentity() для удовлетворения внутренней проверки безопасности.

Для получения дополнительной информации о выполнении IPC со службой, см. Службы связывания.

Использование получателей широковещательных рассылок

BroadcastReceiver обрабатывает асинхронные запросы, инициированные Intent.

По умолчанию, получатели экспортируется и могут быть вызваны любым другим приложением. Если ваш BroadcastReceiver предназначен для использования другими приложениями, вы можете применить разрешения для получателей с помощью <receiver> элемента в манифесте приложения. Это предотвратит приложений без соответствующих разрешений от посылки намерений в BroadcastReceiver.

Динамическая загрузка кода

Мы настоятельно не рекомендуем загрузки кода вне вашего APK приложения. Это значительно увеличивает вероятность компрометирования приложения из-за внедрения кода или кода фальсификации. Это также добавляет сложности вокруг управления версиями и тестированием приложения. Наконец, это может сделать невозможным проверить поведение приложения, а так же это может быть запрещено в некоторых средах.

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

Основной риск безопасности, связанный с динамической загрузкой кода это то, что код должен исходить от проверенного источника. Если модули включены непосредственно в ваш APK, то они не могут быть изменены другими приложениями. Это верно как для машинного кода библиотеки, так и для классов загружаемых с помощью DexClassLoader. Мы видели много примеров приложений, пытающихся загрузить код из небезопасных мест, таких как загрузка из сети через не зашифрованные протоколы, или перезаписываемых местах, такие как внешние накопители. Такие места могут позволить кому-то в сети изменить содержание по пути, или другому приложению на устройстве пользователя изменять содержимое на устройстве, соответственно.

Безопасность в виртуальной машине

Dalvik это среда выполнения виртуальной машины(VM) Android. Dalvik был построен специально для Android, но многие из проблем, связанных безопасного кода в других виртуальных машин применимы также к Android. В общем, вы не должны беспокоиться о вопросах безопасности, связанных с виртуальной машиной. Ваша приложение выполняется в безопасной среде песочницы, так что другие процессы в системе не могут получить доступ к вашему коду или личным данным.

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

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

  • Некоторые виртуальные машины, такие как JVM или среда выполнения .net, выступают в качестве границы безопасности, изолируя код от основных возможностей операционной системы. На платформе Android, Dalvik VM не является границей безопасности — песочница приложений реализована на уровне операционной системы, так что Dalvik может взаимодействовать с машинным кодом в одном приложении без каких-либо ограничений безопасности.
  • Учитывая ограниченное хранилище на мобильных устройствах, обычно разработчики хотят построить модульное приложение и использовать динамическую загрузку классов. При этом, необходимо учитывать как источник, откуда вы получаете логику приложения, так и то, где вы храните это локально. Не используйте динамическую загрузку классов из источников, которые не проверены, таких как небезопасные сетевые источники или внешние накопители, потому что код может быть изменен для добавления вредоносного поведения.

Безопасность в машинном коде

В общем, мы рекомендуем разработчикам использовать Android SDK для разработки приложений, а не с помощью машинного кода с Android NDK. Приложения, созданные на основе машинного кода являются более сложными, менее портативными, и более подвержены распространенным ошибкам повреждения памяти, таким как переполнение буфера.

Android построен с использованием ядра Linux, и быть знакомым с практиками разработки безопасности под Linux особенно полезно, если вы собираетесь использовать машинный код. Методы обеспечения безопасности Linux выходят за рамки этого документа, но один из самых популярных ресурсов "Безопасное программирование для Linux и Unix", доступно по ссылке http://www.dwheeler.com/secure-programs.

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