Конфигурация сетевой безопасности

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

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

Добавьте файл конфигурации сетевой безопасности

Функция конфигурации сетевой безопасности использует 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 8.1 (уровень API 27) или ниже. Начиная с Android 9 (уровень API 28), поддержка открытого текста отключена по умолчанию.

Если вы хотите, чтобы ваше приложение подключалось к местам назначения, используя только безопасные соединения, вы можете отказаться от поддержки открытого текста (с использованием незашифрованного протокола HTTP вместо HTTPS) для этих мест назначения. Этот параметр помогает предотвратить случайные регрессии в приложениях из-за изменений URL-адресов, предоставленных внешними источниками, такими как внутренние серверы. Дополнительные сведения см. NetworkSecurityPolicy.isCleartextTrafficPermitted() .

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

В приведенном ниже отрывке показано, как отказаться от открытого текста в res/xml/network_security_config.xml :

<?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>

ПИН-сертификаты

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

Закрепление сертификата осуществляется путем предоставления набора сертификатов по хешу открытого ключа ( 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>

Формат файла конфигурации

Функция конфигурации сетевой безопасности использует формат файла 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>
описание:
Конфигурация по умолчанию, используемая всеми соединениями, назначение которых не указано в 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 cleartextTrafficPermitted=["true" | "false"]>
    ...
</domain-config>
может содержать:
1 или более <domain>
0 или 1 <trust-anchors>
0 или 1 <pin-set>
Любое количество вложенных <domain-config>
описание:
Конфигурация, используемая для подключений к определенным местам назначения, как определено элементами domain .

Обратите внимание: если несколько элементов domain-config охватывают пункт назначения, используется конфигурация с наиболее конкретным (самым длинным) соответствующим правилом домена.

<домен>

синтаксис:
<domain includeSubdomains=["true" | "false"]>example.com</domain>
атрибуты:
includeSubdomains
Если "true" , то это правило домена соответствует домену и всем субдоменам, включая субдомены субдоменов. В противном случае правило применяется только к точным совпадениям.

<переопределения-отладки>

синтаксис:
<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
Источник сертификатов CA. Каждый сертификат может быть одним из следующих:
  • необработанный идентификатор ресурса, указывающий на файл, содержащий сертификаты X.509. Сертификаты должны быть закодированы в формате DER или PEM. В случае сертификатов PEM файл не должен содержать дополнительных данных, отличных от PEM, таких как комментарии.
  • "system" для предустановленных системных сертификатов CA.
  • "user" для сертификатов CA, добавленных пользователем.
overridePins

Указывает, обходят ли центры сертификации из этого источника закрепление сертификата. Если "true" , то закрепление не выполняется для цепочек сертификатов, подписанных одним из центров сертификации из этого источника. Это может быть полезно для отладки центров сертификации или для тестирования атак «человек посередине» на безопасный трафик вашего приложения.

Значение по умолчанию — "false" если не указано в элементе debug-overrides ; в этом случае значение по умолчанию — "true" .

<набор контактов>

синтаксис:
<pin-set expiration="date">
...
</pin-set>
может содержать:
Любое количество <pin>
описание:
Набор контактов открытого ключа. Чтобы безопасное соединение было надежным, один из открытых ключей в цепочке доверия должен находиться в наборе контактов. См. <pin> для получения информации о формате выводов.
атрибуты:
expiration
Дата в формате yyyy-MM-dd , когда истекает срок действия закреплений, что позволяет отключить закрепление. Если атрибут не установлен, срок действия контактов не истекает.

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

<булавка>

синтаксис:
<pin digest=["SHA-256"]>base64 encoded digest of X.509
    SubjectPublicKeyInfo (SPKI)</pin>
атрибуты:
digest
Алгоритм дайджеста, используемый для генерации вывода. В настоящее время поддерживается только "SHA-256" .

Дополнительные ресурсы

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

Кодлабы