Функция «Настройка сетевой безопасности» позволяет настраивать параметры сетевой безопасности вашего приложения в безопасном декларативном конфигурационном файле без изменения кода приложения. Эти параметры можно настроить для конкретных доменов и для конкретного приложения. Ключевые возможности этой функции:
- Настраиваемые доверенные якоря: Настройте, каким центрам сертификации (ЦС) доверяют для безопасных соединений приложения. Например, можно доверять определенным самоподписанным сертификатам или ограничить набор общедоступных ЦС, которым доверяет приложение.
- Переопределение только для отладки: Безопасная отладка защищенных соединений в приложении без дополнительного риска для установленной базы пользователей.
- Отказ от использования незашифрованного трафика: защита приложений от случайного использования незашифрованного трафика.
- Включение прозрачности сертификатов: ограничьте использование приложением защищенных соединений только сертификатами с подтвержденной регистрацией.
- Привязка сертификатов: позволяет ограничить защищенное соединение приложения определенными сертификатами.
Добавьте файл конфигурации сетевой безопасности.
Функция настройки сетевой безопасности использует 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 (для настройки для каждого домена).
Настройте собственный центр сертификации.
Возможно, вам потребуется подключиться к хосту, использующему самоподписанный 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>
Добавьте самоподписанный или непубличный сертификат центра сертификации в формате 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>
Настройка центров сертификации для отладки
При отладке приложения, подключающегося по 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).
Стандарт прозрачности сертификатов (CT, RFC 6962 ) — это интернет-стандарт, разработанный для повышения безопасности цифровых сертификатов. Он требует от центров сертификации (ЦС) публиковать все выданные сертификаты в общедоступном журнале, который их регистрирует, повышая прозрачность и подотчетность в процессе выдачи сертификатов.
Благодаря поддержанию проверяемой записи всех сертификатов, CT значительно затрудняет подделку сертификатов злоумышленниками или их ошибочную выдачу центрами сертификации. Это помогает защитить пользователей от атак типа «человек посередине» и других угроз безопасности. Для получения дополнительной информации см. пояснение на transparency.dev . Для получения дополнительной информации о соответствии CT в Android см. политику CT Android .
По умолчанию сертификаты принимаются независимо от того, зарегистрированы ли они в журнале 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>
Пин-сертификаты
Обычно приложение доверяет всем предустановленным центрам сертификации. Если какой-либо из этих центров выдаст поддельный сертификат, приложение окажется под угрозой со стороны злоумышленника, осуществляющего атаку по пути следования сертификата. Некоторые приложения ограничивают набор принимаемых сертификатов, либо ограничивая круг центров сертификации, которым они доверяют, либо используя привязку сертификатов.
Привязка сертификата осуществляется путем предоставления набора сертификатов на основе хеша открытого ключа ( SubjectPublicKeyInfo сертификата X.509). Цепочка сертификатов считается действительной только в том случае, если она содержит хотя бы один из привязанных открытых ключей.
Обратите внимание, что при использовании привязки сертификата всегда следует включать резервный ключ, чтобы в случае необходимости переключения на новые ключи или смены центра сертификации (при привязке к сертификату центра сертификации или промежуточному сертификату этого центра сертификации) подключение вашего приложения не пострадало. В противном случае для восстановления подключения необходимо выпустить обновление приложения.
Кроме того, можно установить время истечения срока действия для закрепленных сертификатов, после которого закрепление не выполняется. Это помогает предотвратить проблемы с подключением в приложениях, которые не были обновлены. Однако установка времени истечения срока действия для закрепленных сертификатов может позволить злоумышленникам обойти ваши закрепленные сертификаты.
Приведённый ниже фрагмент кода показывает, как закрепить сертификаты в файле 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>
конфигурация локального хоста
Как правило, принудительное включение функций сетевой безопасности для подключений к локальному хосту не требуется. Например, прозрачность сертификатов для подключений к локальному хосту требуется крайне редко.
Начиная с Android 17 (уровень API 37) и выше, если для localhost не задана конфигурация, включается неявная конфигурация. По умолчанию эта конфигурация выполняет следующие действия:
- Разрешает передачу данных в открытом виде.
- Не обеспечивает прозрачность сертификатов (CT).
- Не обеспечивает обязательное закрепление сертификата.
- Передает доверенные привязки в
<base-config>.
Конфигурация считается ориентированной на localhost, если доменное имя следующее:
-
localhost -
ip6-localhostили - числовой IP-адрес, и
InetAddress.isLoopback()имеетtrue(например,127.0.0.1или[::1]).
Формат файла конфигурации
Функция настройки сетевой безопасности использует 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>
В следующих разделах описывается синтаксис и другие детали формата файла.
<network-security-config>
- может содержать:
- 0 или 1 из
<base-config>
Любое количество<domain-config>
0 или 1 из<debug-overrides>
<base-config>
- синтаксис:
<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, то приложение будет использовать журналы прозрачности сертификатов для проверки сертификатов. Когда приложение использует собственный сертификат (или хранилище пользователей), вероятно, что сертификат не является общедоступным и, следовательно, не может быть проверен с помощью прозрачности сертификатов. По умолчанию проверка в таких случаях отключена. Тем не менее, можно принудительно включить проверку, используя<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"для сертификатов CA, добавляемых пользователем.
-
overridePins Указывает, обходят ли центры сертификации из этого источника привязку сертификатов. Если
"true", то привязка не выполняется для цепочек сертификатов, подписанных одним из центров сертификации из этого источника. Это может быть полезно для отладки центров сертификации или для тестирования атак типа "человек посередине" на защищенный трафик вашего приложения.Значение по умолчанию —
"false"если иное не указано в элементеdebug-overrides, в этом случае значение по умолчанию —"true".
-
<набор контактов>
- синтаксис:
<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 - Алгоритм хеширования, используемый для генерации пин-кода. В настоящее время поддерживается только
"SHA-256".
-