Configuration de la sécurité réseau

La fonctionnalité Configuration de la sécurité réseau vous permet de personnaliser les paramètres de sécurité réseau de votre application dans un fichier de configuration déclaratif et sécurisé, sans modifier le code de l'application. Ces paramètres peuvent être configurés pour des domaines spécifiques et une application spécifique. Voici les principales caractéristiques de cette fonctionnalité :

  • Ancres de confiance personnalisées : définissez les autorités de certification approuvées pour les connexions sécurisées d'une application. Par exemple, vous pouvez approuver des certificats autosignés spécifiques ou restreindre l'ensemble d'autorités de certification publiques approuvées par l'application.
  • Forçages réservés au débogage : déboguez les connexions sécurisées dans une application sans risque supplémentaire pour la base installée.
  • Désactivation du trafic en texte clair : protégez les applications contre l'utilisation accidentelle de trafic en texte clair (non chiffré).
  • Épinglage de certificats : limitez la connexion sécurisée d'une application à des certificats spécifiques.

Ajouter un fichier de configuration de la sécurité réseau

La fonctionnalité Configuration de la sécurité réseau utilise un fichier XML dans lequel vous spécifiez les paramètres de votre application. Vous devez inclure une entrée dans le fichier manifeste de votre application pour qu'elle pointe vers ce fichier. L'extrait de code suivant d'un fichier manifeste montre comment créer cette entrée :

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:networkSecurityConfig="@xml/network_security_config"
                    ... >
        ...
    </application>
</manifest>

Personnaliser les autorités de certification approuvées

Vous pouvez souhaiter que votre application fasse confiance à un ensemble personnalisé d'autorités de certification plutôt qu'à celles approuvées par défaut par la plate-forme. Voici les raisons les plus courantes de ce choix :

  • Connexion à un hôte avec une autorité de certification personnalisée, telle qu'une autorité de certification autosignée ou émise en interne au sein d'une entreprise
  • Limitation de l'ensemble d'autorités de certification aux seules autorités de certification dans lesquelles vous avez confiance, plutôt qu'à chaque autorité de certification préinstallée
  • Approbation d'autres autorités de certification non incluses dans le système

Par défaut, les connexions sécurisées (utilisant des protocoles tels que TLS et HTTPS) de toutes les applications font confiance aux autorités de certification système préinstallées, tandis que les applications ciblant Android 6.0 (niveau d'API 23) ou version antérieure font également confiance au magasin d'autorités de certification ajouté par l'utilisateur par défaut. Vous pouvez personnaliser les connexions de votre application à l'aide de base-config (pour une personnalisation à l'échelle de l'application) ou de domain-config (pour une personnalisation par domaine).

Configurer une autorité de certification personnalisée

Vous souhaitez peut-être vous connecter à un hôte qui utilise un certificat SSL autosigné ou dont le certificat SSL est délivré par une autorité de certification non publique dans laquelle vous avez confiance, telle que l'autorité de certification interne de votre entreprise. L'extrait de code suivant montre comment configurer votre application pour une autorité de certification personnalisée dans 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>

Ajoutez le certificat CA autosigné ou non public, au format PEM ou DER, à res/raw/my_ca.

Limiter l'ensemble d'autorités de certification approuvées

Si vous ne souhaitez pas que votre application fasse confiance à toutes les autorités de certification approuvées par le système, vous pouvez spécifier un ensemble réduit d'autorités de certification de confiance. Cela protège l'application contre les certificats frauduleux émis par l'une des autres autorités de certification.

La configuration permettant de limiter l'ensemble d'autorités de certification approuvées est semblable à l'approbation d'une autorité de certification personnalisée pour un domaine spécifique, sauf que plusieurs autorités de certification sont fournies dans la ressource. L'extrait de code suivant montre comment limiter l'ensemble d'autorités de certification approuvées de votre application dans 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>

Ajoutez les autorités de certification approuvées, au format PEM ou DER, à res/raw/trusted_roots. Notez que si vous utilisez le format PEM, le fichier doit contenir uniquement des données PEM, sans texte supplémentaire. Vous pouvez également fournir plusieurs éléments <certificates> au lieu d'un seul.

Approuver des autorités de certification supplémentaires

Vous pouvez souhaiter que votre application fasse confiance à d'autres autorités de certification qui ne sont pas approuvées par le système. Par exemple, si le système n'inclut pas encore l'autorité de certification ou si celle-ci ne remplit pas les conditions requises pour être incluse dans le système Android. Vous pouvez spécifier plusieurs sources de certification pour une configuration dans res/xml/network_security_config.xml à l'aide d'un code semblable à l'extrait suivant.

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

Configurer des autorités de certification pour le débogage

Lors du débogage d'une application qui se connecte via HTTPS, il se peut que vous souhaitiez vous connecter à un serveur de développement local qui ne possède pas le certificat SSL de votre serveur de production. Pour y parvenir sans modifier le code de votre application, vous pouvez spécifier des autorités de certification réservées au débogage, qui ne sont approuvées que lorsque android:debuggable est associé à la valeur true, en utilisant debug-overrides. Normalement, les IDE et les outils de compilation définissent automatiquement cet indicateur pour les builds non publiés.

Cette méthode est plus sûre que le code conditionnel habituel, car, par mesure de sécurité, les plates-formes de téléchargement d'applications n'acceptent pas les applications marquées comme débogables.

L'extrait ci-dessous montre comment spécifier des autorités de certification réservées au débogage dans 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>

Désactiver le trafic en texte clair

Remarque : Les conseils de cette section ne s'appliquent qu'aux applications qui ciblent Android 8.1 (niveau d'API 27) ou version antérieure. À partir d'Android 9 (niveau d'API 28), la prise en charge du texte clair est désactivée par défaut.

Si vous souhaitez que votre application se connecte à des destinations à l'aide de connexions sécurisées uniquement, vous pouvez désactiver la prise en charge du texte clair (via le protocole HTTP non chiffré au lieu de HTTPS) vers ces destinations. Cette option permet d'éviter les régressions accidentelles dans les applications en raison de modifications des URL fournies par des sources externes telles que des serveurs backend. Pour en savoir plus, consultez NetworkSecurityPolicy.isCleartextTrafficPermitted().

Par exemple, vous souhaitez peut-être que votre application s'assure que les connexions à secure.example.com sont toujours effectuées via HTTPS afin de protéger le trafic sensible des réseaux hostiles.

L'extrait ci-dessous montre comment désactiver le texte clair dans 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>

Épingler des certificats

Normalement, une application approuve toutes les autorités de certification préinstallées. Si l'une de ces autorités de certification délivre un certificat frauduleux, l'application serait vulnérable à une attaque sur le chemin. Certaines applications choisissent de limiter l'ensemble de certificats qu'elles acceptent soit en limitant l'ensemble d'autorités de certification approuvées, soit en épinglant des certificats.

Pour épingler des certificats, vous devez fournir un ensemble de certificats par hachage de la clé publique (SubjectPublicKeyInfo du certificat X.509). Une chaîne de certificats n'est alors valide que si elle contient au moins une des clés publiques épinglées.

Notez que lorsque vous épinglez des certificats, vous devez toujours inclure une clé de secours. Ainsi, si vous êtes obligé d'utiliser de nouvelles clés ou de changer d'autorités de certification (lors de l'épinglage à un certificat CA ou un intermédiaire de cette autorité de certification), la connectivité de votre application n'est pas affectée. Sinon, vous devez déployer une mise à jour de l'application pour rétablir la connectivité.

De plus, il est possible de définir un délai d'expiration pour les épingles, au bout duquel l'épinglage n'est pas effectué. Cela permet d'éviter les problèmes de connectivité dans les applications qui n'ont pas été mises à jour. Toutefois, la définition d'un délai d'expiration pour les épingles peut permettre aux pirates informatiques de contourner vos certificats épinglés.

L'extrait ci-dessous montre comment épingler des certificats dans 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>

Comportement d'héritage de la configuration

Les valeurs qui ne sont pas définies dans une configuration spécifique sont héritées. Ce comportement permet des configurations plus complexes tout en préservant la lisibilité du fichier de configuration.

Par exemple, les valeurs qui ne sont pas définies dans un élément domain-config sont extraites de l'élément domain-config parent si elles sont imbriquées, ou de l'élément base-config dans le cas contraire. Les valeurs non définies dans l'élément base-config utilisent les valeurs par défaut de la plate-forme.

Prenons un exemple où toutes les connexions aux sous-domaines de example.com doivent utiliser un ensemble personnalisé d'autorités de certification. De plus, le trafic en texte clair vers ces domaines est autorisé sauf lors de la connexion à secure.example.com. En imbriquant la configuration de secure.example.com dans la configuration de example.com, il n'est pas nécessaire de dupliquer trust-anchors.

L'extrait ci-dessous montre à quoi ressemblerait cette imbrication dans 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>

Format du fichier de configuration

La fonctionnalité Configuration de la sécurité réseau utilise un format de fichier XML. La structure globale du fichier est illustrée dans l'exemple de code suivant :

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

Les sections suivantes décrivent la syntaxe et d'autres détails concernant le format de fichier.

<network-security-config>

Peut contenir :
0 ou 1 <base-config>
N'importe quel nombre de <domain-config>
0 ou 1 <debug-overrides>

<base-config>

Syntaxe :
<base-config cleartextTrafficPermitted=["true" | "false"]>
    ...
</base-config>
Peut contenir :
<trust-anchors>
Description :
Configuration par défaut utilisée par toutes les connexions dont la destination n'est pas couverte par un élément domain-config.

Toutes les valeurs non définies utilisent les valeurs par défaut de la plate-forme.

La configuration par défaut pour les applications ciblant Android 9 (niveau d'API 28) ou version ultérieure est la suivante :

<base-config cleartextTrafficPermitted="false">
    <trust-anchors>
        <certificates src="system" />
    </trust-anchors>
</base-config>

La configuration par défaut pour les applications ciblant Android 7.0 (niveau d'API 24) à Android 8.1 (niveau d'API 27) est la suivante :

<base-config cleartextTrafficPermitted="true">
    <trust-anchors>
        <certificates src="system" />
    </trust-anchors>
</base-config>

La configuration par défaut pour les applications ciblant Android 6.0 (niveau d'API 23) ou version antérieure est la suivante :

<base-config cleartextTrafficPermitted="true">
    <trust-anchors>
        <certificates src="system" />
        <certificates src="user" />
    </trust-anchors>
</base-config>

<domain-config>

Syntaxe :
<domain-config cleartextTrafficPermitted=["true" | "false"]>
    ...
</domain-config>
Peut contenir :
1 ou plusieurs <domain>
0 ou 1 <trust-anchors>
0 ou 1 <pin-set>
N'importe quel nombre de <domain-config> imbriqués
Description :
Configuration utilisée pour les connexions à des destinations spécifiques, telles que définies par les éléments domain.

Notez que si plusieurs éléments domain-config couvrent une destination, la configuration avec la règle de domaine correspondante la plus spécifique (la plus longue) est utilisée.

<domain>

Syntaxe :
<domain includeSubdomains=["true" | "false"]>example.com</domain>
Attributs :
includeSubdomains
Si la valeur est "true", alors cette règle de domaine correspond au domaine et à tous les sous-domaines, y compris les sous-domaines des sous-domaines. Sinon, la règle ne s'applique qu'aux correspondances exactes.

<debug-overrides>

Syntaxe :
<debug-overrides>
    ...
</debug-overrides>
Peut contenir :
0 ou 1 <trust-anchors>
Description :
Forçages à appliquer lorsque android:debuggable est associé à la valeur "true", ce qui est normalement le cas pour les builds non publiés générés par des IDE et des outils de compilation. Les ancres de confiance spécifiées dans debug-overrides sont ajoutées à toutes les autres configurations, et l'épinglage des certificats n'est pas effectué lorsque la chaîne de certificats du serveur utilise l'une de ces ancres de confiance réservées au débogage. Si android:debuggable est associé à la valeur "false", cette section est complètement ignorée.

<trust-anchors>

Syntaxe :
<trust-anchors>
...
</trust-anchors>
Peut contenir :
N'importe quel nombre de <certificates>
Description :
Ensemble d'ancres de confiance pour les connexions sécurisées.

<certificates>

Syntaxe :
<certificates src=["system" | "user" | "raw resource"]
              overridePins=["true" | "false"] />
Description :
Ensemble de certificats X.509 pour les éléments trust-anchors.
Attributs :
src
Source de certificats CA. Chaque certificat peut être l'un des suivants :
  • Un ID de ressource brute pointant vers un fichier contenant des certificats X.509. Les certificats doivent être encodés au format DER ou PEM. Dans le cas des certificats PEM, le fichier ne doit pas contenir de données autres que des données PEM, telles que des commentaires.
  • "system" pour les certificats CA du système préinstallés.
  • "user" pour les certificats CA ajoutés par l'utilisateur.
overridePins

Indique si les autorités de certification de cette source contournent l'épinglage des certificats. Si la valeur est "true", l'épinglage n'est pas effectué sur les chaînes de certificats signées par l'une des autorités de certification de cette source. Cela peut être utile pour déboguer les autorités de certification ou pour tester des attaques MITM ("man in the middle") sur le trafic sécurisé de votre application.

La valeur par défaut est "false", sauf si elle est spécifiée dans un élément debug-overrides. Dans ce cas, la valeur par défaut est "true".

<pin-set>

Syntaxe :
<pin-set expiration="date">
...
</pin-set>
Peut contenir :
N'importe quel nombre de <pin>
Description :
Ensemble d'épingles de clés publiques. Pour qu'une connexion sécurisée soit approuvée, l'une des clés publiques de la chaîne de confiance doit se trouver dans l'ensemble d'épingles. Consultez <pin> pour connaître le format des épinglages.
Attributs :
expiration
Date, au format yyyy-MM-dd, à laquelle les épingles expirent, désactivant alors l'épinglage. Si l'attribut n'est pas défini, les épingles n'expirent pas.

L'expiration permet d'éviter les problèmes de connectivité dans les applications qui ne reçoivent pas de mises à jour de leur ensemble d'épingles, par exemple lorsque l'utilisateur désactive les mises à jour d'application.

<pin>

Syntaxe :
<pin digest=["SHA-256"]>base64 encoded digest of X.509
    SubjectPublicKeyInfo (SPKI)</pin>
Attributs :
digest
Algorithme condensé utilisé pour générer l'épingle. Pour le moment, seul "SHA-256" est pris en charge.

Ressources supplémentaires

Pour en savoir plus sur la fonctionnalité Configuration de la sécurité réseau, consultez les ressources suivantes.

Ateliers de programmation