Функция настройки сетевой безопасности позволяет настраивать параметры сетевой безопасности вашего приложения в безопасном декларативном файле конфигурации без изменения кода приложения. Эти параметры можно настроить для конкретных доменов и конкретного приложения. Ключевые возможности этой функции:
- Настраиваемые якоря доверия: настройте, каким центрам сертификации (ЦС) приложение доверяет для безопасных подключений. Например, можно доверять определённым самоподписанным сертификатам или ограничить набор публичных ЦС, которым доверяет приложение.
- Переопределения, предназначенные только для отладки: безопасная отладка защищенных соединений в приложении без дополнительного риска для установленной базы.
- Отказ от открытого текстового трафика: защита приложений от случайного использования открытого текстового (незашифрованного) трафика.
- Включение прозрачности сертификатов: ограничение защищенных соединений приложения с использованием доказуемо зарегистрированных сертификатов.
- Закрепление сертификатов: ограничение безопасного соединения приложения определенными сертификатами.
Добавить файл конфигурации сетевой безопасности
Функция настройки сетевой безопасности использует XML-файл, в котором вы указываете параметры своего приложения. Необходимо включить запись в манифест приложения, указывающую на этот файл. Следующий фрагмент кода из манифеста демонстрирует, как создать эту запись:
<?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:networkSecurityConfig="@xml/network_security_config" ... > ... </application> </manifest>
Настройте доверенные центры сертификации
Возможно, вам захочется, чтобы ваше приложение доверяло пользовательскому набору центров сертификации вместо набора, установленного на платформе по умолчанию. Наиболее распространённые причины для этого:
- Подключение к хосту с помощью пользовательского центра сертификации, например центра сертификации, который является самоподписанным или выпущен внутри компании.
- Ограничение набора центров сертификации только теми, которым вы доверяете, а не всеми предустановленными центрами сертификации.
- Доверие дополнительным центрам сертификации, не включенным в систему.
По умолчанию защищённые соединения (использующие такие протоколы, как TLS и HTTPS) всех приложений доверяют предустановленным системным центрам сертификации, а приложения для Android 6.0 (уровень API 23) и ниже также по умолчанию доверяют хранилищу центров сертификации, добавленному пользователем. Вы можете настроить соединения своего приложения с помощью base-config
(для настройки всего приложения) или domain-config
(для настройки на уровне домена).
Настройте пользовательский CA
Возможно, вам потребуется подключиться к хосту, использующему самоподписанный SSL-сертификат, или к хосту, SSL-сертификат которого выдан непубличным центром сертификации, которому вы доверяете, например, внутренним центром сертификации вашей компании. Следующий фрагмент кода демонстрирует, как настроить приложение для использования пользовательского центра сертификации в файле res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </domain-config> </network-security-config>
Добавьте самоподписанный или непубличный сертификат CA в формате PEM или DER в res/raw/my_ca
.
Ограничить набор доверенных центров сертификации
Если вы не хотите, чтобы ваше приложение доверяло всем центрам сертификации, которым доверяет система, вы можете указать ограниченный набор центров сертификации. Это защитит приложение от мошеннических сертификатов, выданных другими центрами сертификации.
Настройка ограничения набора доверенных центров сертификации аналогична настройке доверия к пользовательскому центру сертификации для конкретного домена, за исключением того, что в ресурсе указано несколько центров сертификации. Следующий фрагмент кода демонстрирует, как ограничить набор доверенных центров сертификации вашего приложения в файле res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/> </trust-anchors> </domain-config> </network-security-config>
Добавьте доверенные центры сертификации в формате PEM или DER в res/raw/trusted_roots
. Обратите внимание: при использовании формата PEM файл должен содержать только данные PEM без дополнительного текста. Вы также можете указать несколько элементов <certificates>
вместо одного.
Доверять дополнительным центрам сертификации
Возможно, вам потребуется, чтобы ваше приложение доверяло дополнительным центрам сертификации, которым система не доверяет, например, если в системе ещё нет центра сертификации или центр сертификации не соответствует требованиям для включения в систему Android. Вы можете указать несколько источников сертификатов для конфигурации в файле res/xml/network_security_config.xml
используя код, подобный следующему.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="@raw/extracas"/> <certificates src="system"/> </trust-anchors> </base-config> </network-security-config>
Настройка CA для отладки
При отладке приложения, подключающегося по HTTPS, может потребоваться подключение к локальному серверу разработки, у которого нет SSL-сертификата для вашего производственного сервера. Чтобы обеспечить это без внесения изменений в код приложения, вы можете указать центры сертификации, предназначенные только для отладки и доверенные только при значении android:debuggable равном true
, с помощью debug-overrides
. Обычно IDE и инструменты сборки автоматически устанавливают этот флаг для сборок, не предназначенных для релиза.
Это безопаснее, чем обычный условный код, поскольку в качестве меры предосторожности магазины приложений не принимают приложения, помеченные как отлаживаемые.
В приведенном ниже отрывке показано, как указать центры сертификации, предназначенные только для отладки, в res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors> <certificates src="@raw/debug_cas"/> </trust-anchors> </debug-overrides> </network-security-config>
Подтвердите прозрачность сертификата
Примечание: поддержка прозрачности сертификатов доступна только в Android 16 (уровень API 36).
Certificate Transparency (CT, RFC 6962 ) — интернет-стандарт, разработанный для повышения безопасности цифровых сертификатов. Он требует от центров сертификации предоставлять все выданные сертификаты в общедоступный журнал, что повышает прозрачность и подотчётность процесса выдачи сертификатов.
Ведя проверяемую запись всех сертификатов, CT значительно затрудняет подделку сертификатов злоумышленниками или их ошибочную выдачу центрами сертификации. Это помогает защитить пользователей от атак типа «человек посередине» и других угроз безопасности. Подробнее см. объяснение на сайте transparent.dev . Подробнее о соответствии требованиям CT на Android см. в политике Android в отношении CT .
По умолчанию сертификаты принимаются независимо от того, зарегистрированы ли они в журнале CT. Чтобы ваше приложение подключалось только к тем пунктам назначения, сертификаты которых зарегистрированы в журнале CT, вы можете включить эту функцию глобально или для каждого домена .
Открытый текстовый трафик
Разработчики могут включить или отключить открытый текстовый трафик (используя незашифрованный протокол HTTP вместо HTTPS) для своих приложений. Подробнее см. в описании NetworkSecurityPolicy.isCleartextTrafficPermitted()
.
Поведение текстового трафика по умолчанию зависит от уровня API:
- До Android 8.1 (уровень API 27) поддержка открытого текста включена по умолчанию. Приложения могут отказаться от открытого текста для дополнительной безопасности.
- Начиная с Android 9 (уровень API 28), поддержка открытого текста по умолчанию отключена. Приложения, которым требуется открытый текстовый трафик, могут включить его .
Отказаться от открытого текстового трафика
Примечание: рекомендации в этом разделе применимы только к приложениям, предназначенным для Android 8.1 (уровень API 27) или ниже.
Если вы планируете, что ваше приложение будет подключаться к пунктам назначения только по защищённым соединениям, вы можете отключить поддержку открытого текстового трафика к этим пунктам назначения. Эта опция помогает предотвратить случайные сбои в работе приложений из-за изменений в URL-адресах, предоставляемых внешними источниками, такими как внутренние серверы.
Например, вы можете захотеть, чтобы ваше приложение гарантировало, что соединения с secure.example.com
всегда осуществляются по протоколу HTTPS, чтобы защитить конфиденциальный трафик от враждебных сетей.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </network-security-config>
Подключиться к открытому текстовому трафику
Примечание: рекомендации в этом разделе применимы только к приложениям, предназначенным для Android 9 (уровень API 28) или выше.
Если вашему приложению необходимо подключаться к пунктам назначения с использованием открытого текста (HTTP), вы можете включить поддержку открытого текста для этих пунктов назначения.
Например, вы можете разрешить своему приложению устанавливать небезопасные соединения с insecure.example.com
.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">insecure.example.com</domain> </domain-config> </network-security-config>
Если вашему приложению необходимо разрешить отправку открытого текста на любой домен, установите cleartextTrafficPermitted="true"
в base-config
. Обратите внимание, что такой небезопасной конфигурации следует по возможности избегать.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true"> </base-config> </network-security-config>
Сертификаты PIN-кода
Обычно приложение доверяет всем предустановленным центрам сертификации (CA). Если какой-либо из этих центров выдаст мошеннический сертификат, приложение подвергнется риску со стороны злоумышленника. Некоторые приложения ограничивают набор принимаемых сертификатов, либо ограничивая список доверенных центров сертификации, либо закрепляя сертификаты.
Закрепление сертификатов осуществляется путём предоставления набора сертификатов по хэшу открытого ключа ( SubjectPublicKeyInfo
сертификата X.509). В этом случае цепочка сертификатов действительна только в том случае, если она содержит хотя бы один из закреплённых открытых ключей.
Обратите внимание, что при использовании закрепления сертификата всегда следует включать резервный ключ, чтобы в случае необходимости перехода на новые ключи или смены центра сертификации (при закреплении за сертификатом центра сертификации или промежуточным сертификатом этого центра сертификации) подключение вашего приложения не пострадало. В противном случае для восстановления подключения необходимо установить обновление приложения.
Кроме того, можно установить срок действия PIN-кодов, по истечении которого закрепление не выполняется. Это помогает предотвратить проблемы с подключением в приложениях, которые не были обновлены. Однако установка срока действия PIN-кодов может позволить злоумышленникам обойти ваши закреплённые сертификаты.
В приведенном ниже отрывке показано, как закрепить сертификаты в res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <pin-set expiration="2018-01-01"> <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin> <!-- backup pin --> <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin> </pin-set> </domain-config> </network-security-config>
Поведение наследования конфигурации
Значения, не заданные в конкретной конфигурации, наследуются. Это позволяет создавать более сложные конфигурации, сохраняя при этом читаемость файла конфигурации.
Например, значения, не заданные в domain-config
берутся из родительской domain-config
, если она вложена, или из base-config
, если нет. Значения, не заданные в base-config
используют значения платформы по умолчанию.
Например, рассмотрим случай, когда все подключения к поддоменам example.com
должны использовать специальный набор центров сертификации. Кроме того, открытый трафик к этим доменам разрешён, за исключением случаев подключения к secure.example.com
. Благодаря вложению конфигурации для secure.example.com
в конфигурацию для example.com
, trust-anchors
не нужно дублировать.
В приведенном ниже отрывке показано, как это вложение будет выглядеть в res/xml/network_security_config.xml
:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> </domain-config> </domain-config> </network-security-config>
Формат файла конфигурации
Функция настройки сетевой безопасности использует формат XML-файла. Общая структура файла показана в следующем примере кода:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </base-config> <domain-config> <domain>android.com</domain> ... <trust-anchors> <certificates src="..."/> ... </trust-anchors> <pin-set> <pin digest="...">...</pin> ... </pin-set> </domain-config> ... <debug-overrides> <trust-anchors> <certificates src="..."/> ... </trust-anchors> </debug-overrides> </network-security-config>
В следующих разделах описывается синтаксис и другие детали формата файла.
<сетевая-безопасность-конфигурация>
- может содержать:
- 0 или 1 из
<base-config>
Любое количество<domain-config>
0 или 1 из<debug-overrides>
<базовая-конфигурация>
- синтаксис:
<base-config cleartextTrafficPermitted=["true" | "false"]> ... </base-config>
- может содержать:
-
<trust-anchors>
<certificateTransparency>
- описание:
- Конфигурация по умолчанию, используемая всеми соединениями, назначение которых не охвачено
domain-config
.Любые неустановленные значения используют значения платформы по умолчанию.
Конфигурация по умолчанию для приложений, ориентированных на Android 9 (уровень API 28) и выше, следующая:
<base-config cleartextTrafficPermitted="false"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
Конфигурация по умолчанию для приложений, ориентированных на Android 7.0 (уровень API 24) – Android 8.1 (уровень API 27), выглядит следующим образом:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config>
Конфигурация по умолчанию для приложений, ориентированных на Android 6.0 (уровень API 23) и ниже, следующая:
<base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </base-config>
<domain-config>
- синтаксис:
<domain-config cleartextTrafficPermitted=["true" | "false"]> ... </domain-config>
- может содержать:
- 1 или более
<domain>
0 или 1<certificateTransparency>
0 или 1<trust-anchors>
>
0 или 1<pin-set>
>
Любое количество вложенных<domain-config>
- описание:
- Конфигурация, используемая для подключений к определенным пунктам назначения, как определено элементами
domain
.Обратите внимание, что если несколько элементов
domain-config
охватывают назначение, используется конфигурация с наиболее конкретным (самым длинным) соответствующим правилом домена.
<домен>
- синтаксис:
<domain includeSubdomains=["true" | "false"]>example.com</domain>
- атрибуты:
-
includeSubdomains
- Если
"true"
, то это правило домена соответствует домену и всем поддоменам, включая поддомены поддоменов. В противном случае правило применяется только к точным совпадениям.
-
<certificateTransparency>
- синтаксис:
<certificateTransparency enabled=["true" | "false"]/>
- описание:
- Если
true
, приложение будет использовать журналы Certificate Transparency для проверки сертификатов. Когда приложение использует собственный сертификат (или хранилище пользователя), вероятно, сертификат не является публичным и, следовательно, не может быть проверен с помощью Certificate Transparency. По умолчанию проверка в таких случаях отключена. Однако принудительную проверку можно включить с помощью<certificateTransparency enabled="true"/>
в конфигурации домена. Для каждого<domain-config>
проверка выполняется в следующем порядке:- Если включена
certificateTransparency
, включите проверку. - Если какой-либо
<trust-anchors>
является"user"
или встроенным (например,"@raw/cert.pem"
), отключите проверку. - В противном случае полагайтесь на унаследованную конфигурацию .
- Если включена
<debug-overrides>
- синтаксис:
<debug-overrides> ... </debug-overrides>
- может содержать:
- 0 или 1
<trust-anchors>
> - описание:
- Переопределения, применяемые, когда android:debuggable имеет значение
"true"
, что обычно характерно для сборок, не предназначенных для релиза, созданных IDE и инструментами сборки. Якоря доверия, указанные вdebug-overrides
добавляются ко всем остальным конфигурациям, и закрепление сертификатов не выполняется, если цепочка сертификатов сервера использует один из этих якорей доверия, предназначенных только для отладки. Если android:debuggable имеет значение"false"
, этот раздел полностью игнорируется.
<якоря доверия>
- синтаксис:
<trust-anchors> ... </trust-anchors>
- может содержать:
- Любое количество
<certificates>
- описание:
- Набор якорей доверия для безопасных соединений.
<сертификаты>
- синтаксис:
<certificates src=["system" | "user" | "raw resource"] overridePins=["true" | "false"] />
- описание:
- Набор сертификатов X.509 для элементов
trust-anchors
. - атрибуты:
-
src
- Источник сертификатов УЦ. Каждый сертификат может быть одним из следующих:
- Необработанный идентификатор ресурса, указывающий на файл, содержащий сертификаты X.509. Сертификаты должны быть закодированы в формате DER или PEM. В случае сертификатов PEM файл не должен содержать дополнительных данных, не относящихся к PEM, например комментариев.
-
"system"
для предустановленных системных сертификатов CA -
"user"
для сертификатов ЦС, добавленных пользователем
-
overridePins
Указывает, обходят ли центры сертификации из этого источника закрепление сертификатов. Если
"true"
, закрепление не применяется к цепочкам сертификатов, подписанным одним из центров сертификации из этого источника. Это может быть полезно для отладки центров сертификации или тестирования атак типа «человек посередине» на защищённый трафик вашего приложения.Значение по умолчанию —
"false"
если не указано иное в элементеdebug-overrides
; в этом случае значение по умолчанию —"true"
.
-
<набор-pin>
- синтаксис:
<pin-set expiration="date"> ... </pin-set>
- может содержать:
- Любое количество
<pin>
- описание:
- Набор PIN-кодов открытого ключа. Для того чтобы защищённое соединение было доверенным, один из открытых ключей в цепочке доверия должен входить в набор PIN-кодов. Формат PIN-кодов см. в разделе
<pin>
. - атрибуты:
-
expiration
- Дата в формате
yyyy-MM-dd
, по истечении которой действие пинов прекращается, что отключает закрепление. Если атрибут не установлен, пины не сгорают.Истечение срока действия помогает предотвратить проблемы с подключением в приложениях, которые не получают обновления своего набора PIN-кодов, например, когда пользователь отключает обновления приложений.
-
<pin>
- синтаксис:
<pin digest=["SHA-256"]>base64 encoded digest of X.509 SubjectPublicKeyInfo (SPKI)</pin>
- атрибуты:
-
digest
- Алгоритм дайджеста, используемый для генерации PIN-кода. В настоящее время поддерживается только
"SHA-256"
.
-