Netzwerksicherheitskonfiguration

Mit der Netzwerksicherheitskonfiguration können Sie die Netzwerksicherheitseinstellungen Ihrer App in einer sicheren, deklarativen Konfigurationsdatei anpassen, ohne den App-Code zu ändern. Diese Einstellungen können für bestimmte Domains und für eine bestimmte App konfiguriert werden. Die wichtigsten Funktionen sind:

  • Benutzerdefinierte Trust-Anchors:Sie können festlegen, welchen Zertifizierungsstellen (Certificate Authorities, CAs) für die sicheren Verbindungen einer App vertraut wird. Sie können beispielsweise bestimmten selbst signierten Zertifikaten vertrauen oder die Anzahl der öffentlichen Zertifizierungsstellen einschränken, denen die App vertraut.
  • Nur für Debugging bestimmte Überschreibungen:Sichere Verbindungen in einer App lassen sich gefahrlos debuggen, ohne dass die installierte Basis einem zusätzlichen Risiko ausgesetzt wird.
  • Deaktivierung von Cleartext-Traffic:Schützen Sie Apps vor der versehentlichen Verwendung von Cleartext-Traffic (unverschlüsselt).
  • Zertifikatstransparenz-Opt-in:Beschränken Sie die sicheren Verbindungen einer App auf die Verwendung von nachweislich protokollierten Zertifikaten.
  • Certificate Pinning:Beschränken Sie die sichere Verbindung einer App auf bestimmte Zertifikate.

Netzwerksicherheitskonfigurationsdatei hinzufügen

Für die Netzwerksicherheitskonfiguration wird eine XML-Datei verwendet, in der Sie die Einstellungen für Ihre App angeben. Sie müssen einen Eintrag im Manifest Ihrer App einfügen, der auf diese Datei verweist. Der folgende Codeausschnitt aus einem Manifest zeigt, wie dieser Eintrag erstellt wird:

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

Vertrauenswürdige Zertifizierungsstellen anpassen

Möglicherweise soll Ihre App einer benutzerdefinierten Gruppe von Zertifizierungsstellen anstelle der Plattformstandardeinstellung vertrauen. Die häufigsten Gründe dafür sind:

  • Verbindung zu einem Host mit einer benutzerdefinierten Zertifizierungsstelle, z. B. einer selbst signierten oder intern in einem Unternehmen ausgestellten Zertifizierungsstelle.
  • Beschränken Sie die Anzahl der CAs auf die CAs, denen Sie vertrauen, anstatt alle vorinstallierten CAs zu verwenden.
  • Zusätzliche CAs, die nicht im System enthalten sind, werden als vertrauenswürdig eingestuft.

Standardmäßig vertrauen sichere Verbindungen (mit Protokollen wie TLS und HTTPS) von allen Apps den vorinstallierten System-Zertifizierungsstellen. Apps, die auf Android 6.0 (API-Level 23) und niedriger ausgerichtet sind, vertrauen standardmäßig auch dem vom Nutzer hinzugefügten Zertifizierungsstellenspeicher. Sie können die Verbindungen Ihrer App mit base-config (für die appweite Anpassung) oder domain-config (für die Anpassung pro Domain) anpassen.

Benutzerdefinierte CA konfigurieren

Möglicherweise möchten Sie eine Verbindung zu einem Host herstellen, der ein selbst signiertes SSL-Zertifikat verwendet, oder zu einem Host, dessen SSL-Zertifikat von einer nicht öffentlichen Zertifizierungsstelle ausgestellt wurde, der Sie vertrauen, z. B. der internen Zertifizierungsstelle Ihres Unternehmens. Der folgende Codeausschnitt zeigt, wie Sie Ihre App für eine benutzerdefinierte Zertifizierungsstelle in res/xml/network_security_config.xml konfigurieren:

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

Fügen Sie das selbstsignierte oder nicht öffentliche CA-Zertifikat im PEM- oder DER-Format zu res/raw/my_ca hinzu.

Satz vertrauenswürdiger CAs einschränken

Wenn Ihre App nicht allen vom System als vertrauenswürdig eingestuften Zertifizierungsstellen vertrauen soll, können Sie stattdessen eine reduzierte Gruppe von Zertifizierungsstellen angeben, denen vertraut werden soll. Dadurch wird die App vor betrügerischen Zertifikaten geschützt, die von einer der anderen Zertifizierungsstellen ausgestellt wurden.

Die Konfiguration zum Einschränken der vertrauenswürdigen Zertifizierungsstellen ähnelt dem Vertrauen einer benutzerdefinierten Zertifizierungsstelle für eine bestimmte Domain. Der Unterschied besteht darin, dass in der Ressource mehrere Zertifizierungsstellen angegeben werden. Der folgende Codeausschnitt zeigt, wie Sie die Menge der vertrauenswürdigen Zertifizierungsstellen Ihrer App in res/xml/network_security_config.xml einschränken können:

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

Fügen Sie die vertrauenswürdigen Zertifizierungsstellen im PEM- oder DER-Format zu res/raw/trusted_roots hinzu. Wenn Sie das PEM-Format verwenden, darf die Datei nur PEM-Daten und keinen zusätzlichen Text enthalten. Sie können auch mehrere <certificates>-Elemente anstelle eines einzelnen Elements angeben.

Zusätzlichen CAs vertrauen

Möglicherweise soll Ihre App zusätzlichen Zertifizierungsstellen vertrauen, die vom System nicht als vertrauenswürdig eingestuft werden. Das kann z. B. der Fall sein, wenn das System die Zertifizierungsstelle noch nicht enthält oder die Zertifizierungsstelle nicht die Anforderungen für die Aufnahme in das Android-System erfüllt. Sie können mehrere Zertifikatsquellen für eine Konfiguration in res/xml/network_security_config.xml angeben, indem Sie Code wie im folgenden Ausschnitt verwenden.

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

CAs für die Fehlerbehebung konfigurieren

Wenn Sie eine App debuggen, die über HTTPS eine Verbindung herstellt, möchten Sie möglicherweise eine Verbindung zu einem lokalen Entwicklungsserver herstellen, der nicht das SSL-Zertifikat für Ihren Produktionsserver hat. Um dies ohne Änderungen am Code Ihrer App zu unterstützen, können Sie nur für das Debugging bestimmte Zertifizierungsstellen angeben, die nur vertrauenswürdig sind, wenn android:debuggable auf true gesetzt ist. Verwenden Sie dazu debug-overrides. Normalerweise wird dieses Flag von IDEs und Build-Tools automatisch für Nicht-Release-Builds festgelegt.

Das ist sicherer als der übliche bedingte Code, da App-Shops aus Sicherheitsgründen keine Apps akzeptieren, die als debugfähig gekennzeichnet sind.

Der folgende Auszug zeigt, wie Sie nur für das Debugging verwendete Zertifizierungsstellen in res/xml/network_security_config.xml angeben:

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

Certificate Transparency aktivieren

Hinweis : Die Unterstützung für Certificate Transparency ist erst ab Android 16 (API-Level 36) verfügbar.

Certificate Transparency (CT, RFC 6962) ist ein Internetstandard, der die Sicherheit digitaler Zertifikate verbessern soll. Zertifizierungsstellen müssen alle ausgestellten Zertifikate in ein öffentliches Protokoll eintragen, wodurch die Transparenz und Rechenschaftspflicht beim Ausstellen von Zertifikaten erhöht wird.

Durch die Aufrechterhaltung eines überprüfbaren Datensatzes aller Zertifikate wird es für böswillige Akteure erheblich schwieriger, Zertifikate zu fälschen, oder für Zertifizierungsstellen, sie versehentlich auszustellen. So werden Nutzer vor Man-in-the-Middle-Angriffen und anderen Sicherheitsbedrohungen geschützt. Weitere Informationen finden Sie in der Erklärung auf transparency.dev. Weitere Informationen zur CT-Konformität unter Android finden Sie in der CT-Richtlinie für Android.

Standardmäßig werden Zertifikate unabhängig davon akzeptiert, ob sie in einem CT-Log erfasst wurden. Damit Ihre App nur Verbindungen zu Zielen mit Zertifikaten herstellt, die in einem CT-Logbuch protokolliert sind, können Sie die Funktion global oder pro Domain aktivieren.

Klartext-Traffic

Entwickler können für ihre Anwendungen die Verwendung von Cleartext-Traffic (mit dem unverschlüsselten HTTP-Protokoll anstelle von HTTPS) aktivieren oder deaktivieren. Weitere Informationen finden Sie unter NetworkSecurityPolicy.isCleartextTrafficPermitted().

Das Standardverhalten von Cleartext-Traffic hängt vom API-Level ab:

  • Bis Android 8.1 (API-Level 27) ist die Unterstützung von Klartext standardmäßig aktiviert. Anwendungen können auf die Verwendung von Klartext verzichten, um die Sicherheit zu erhöhen.
  • Ab Android 9 (API-Level 28) ist die Unterstützung von Klartext standardmäßig deaktiviert. Anwendungen, die Klartext-Traffic erfordern, können Klartext-Traffic aktivieren.

Cleartext-Traffic deaktivieren

Hinweis : Die Informationen in diesem Abschnitt gelten nur für Apps, die auf Android 8.1 (API‑Level 27) oder niedriger ausgerichtet sind.

Wenn Ihre App nur über sichere Verbindungen eine Verbindung zu Zielen herstellen soll, können Sie die Unterstützung von Klartext-Traffic zu diesen Zielen deaktivieren. Diese Option trägt dazu bei, versehentliche Regressionen in Apps aufgrund von Änderungen an URLs zu verhindern, die von externen Quellen wie Back-End-Servern bereitgestellt werden.

Ihre App soll beispielsweise dafür sorgen, dass Verbindungen zu secure.example.com immer über HTTPS erfolgen, um vertraulichen Traffic vor feindseligen Netzwerken zu schützen.

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

Cleartext-Traffic aktivieren

Hinweis : Die Anleitung in diesem Abschnitt gilt nur für Apps, die auf Android 9 (API-Level 28) oder höher ausgerichtet sind.

Wenn Ihre App eine Verbindung zu Zielen über Klartext-Traffic (HTTP) herstellen muss, können Sie die Unterstützung von Klartext für diese Ziele aktivieren.

Sie möchten beispielsweise, dass Ihre App unsichere Verbindungen zu insecure.example.com herstellen darf.

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

Wenn Ihre App Klartext-Datenverkehr für eine beliebige Domain zulassen muss, legen Sie cleartextTrafficPermitted="true" in der base-config fest. Diese unsichere Konfiguration sollte nach Möglichkeit vermieden werden.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
    </base-config>
</network-security-config>

Zertifikate anpinnen

Normalerweise vertraut eine App allen vorinstallierten CAs. Wenn eine dieser CAs ein betrügerisches Zertifikat ausstellen würde, wäre die App durch einen On-Path-Angreifer gefährdet. Einige Apps beschränken die Anzahl der Zertifikate, die sie akzeptieren, indem sie entweder die Anzahl der CAs, denen sie vertrauen, oder die Anzahl der Zertifikate einschränken.

Beim Zertifikats-Pinning wird eine Reihe von Zertifikaten nach Hash des öffentlichen Schlüssels (SubjectPublicKeyInfo des X.509-Zertifikats) bereitgestellt. Eine Zertifikatkette ist nur dann gültig, wenn sie mindestens einen der angepinnten öffentlichen Schlüssel enthält.

Wenn Sie Certificate Pinning verwenden, sollten Sie immer einen Ersatzschlüssel einfügen. So wird die Konnektivität Ihrer App nicht beeinträchtigt, wenn Sie gezwungen sind, zu neuen Schlüsseln zu wechseln oder CAs zu ändern (wenn Sie ein CA-Zertifikat oder ein Zwischenzertifikat dieser CA verwenden). Andernfalls müssen Sie ein Update für die App bereitstellen, um die Verbindung wiederherzustellen.

Außerdem kann eine Ablaufzeit für Pins festgelegt werden, nach der keine Pins mehr gesetzt werden. So lassen sich Verbindungsprobleme in Apps vermeiden, die nicht aktualisiert wurden. Wenn Sie jedoch eine Ablaufzeit für Pins festlegen, können Angreifer Ihre angepinnten Zertifikate umgehen.

Der folgende Auszug zeigt, wie Zertifikate in res/xml/network_security_config.xml angepinnt werden:

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

Verhalten bei der Konfigurationsübernahme

Werte, die in einer bestimmten Konfiguration nicht festgelegt sind, werden übernommen. Dieses Verhalten ermöglicht komplexere Konfigurationen und sorgt gleichzeitig dafür, dass die Konfigurationsdatei lesbar bleibt.

Werte, die nicht in einem domain-config festgelegt sind, werden beispielsweise aus dem übergeordneten domain-config übernommen, sofern es verschachtelt ist, oder aus dem base-config, sofern nicht. Für Werte, die nicht in base-config festgelegt sind, werden die Standardwerte der Plattform verwendet.

Angenommen, für alle Verbindungen zu Subdomains von example.com muss eine benutzerdefinierte Gruppe von Zertifizierungsstellen verwendet werden. Außerdem ist Klartext-Traffic zu diesen Domains zulässig, außer bei Verbindungen zu secure.example.com. Durch das Einbetten der Konfiguration für secure.example.com in die Konfiguration für example.com muss trust-anchors nicht dupliziert werden.

Der folgende Auszug zeigt, wie diese Verschachtelung in res/xml/network_security_config.xml aussehen würde:

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

Für die Netzwerksicherheitskonfiguration wird ein XML-Dateiformat verwendet. Die Gesamtstruktur der Datei wird im folgenden Codebeispiel dargestellt:

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

In den folgenden Abschnitten werden die Syntax und andere Details des Dateiformats beschrieben.

<network-security-config>

kann Folgendes enthalten:
0 oder 1 <base-config>
Beliebige Anzahl von <domain-config>
0 oder 1 <debug-overrides>

<base-config>

Syntax:
<base-config cleartextTrafficPermitted=["true" | "false"]>
    ...
</base-config>
kann Folgendes enthalten:
<trust-anchors> <certificateTransparency>
description:
Die Standardkonfiguration, die von allen Verbindungen verwendet wird, deren Ziel nicht von einer domain-config abgedeckt wird.

Für alle Werte, die nicht festgelegt sind, werden die Standardwerte der Plattform verwendet.

Die Standardkonfiguration für Apps, die auf Android 9 (API-Level 28) und höher ausgerichtet sind, ist wie folgt:

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

Die Standardkonfiguration für Apps, die auf Android 7.0 (API-Level 24) bis Android 8.1 (API-Level 27) ausgerichtet sind, ist wie folgt:

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

Die Standardkonfiguration für Apps, die auf Android 6.0 (API-Level 23) und niedriger ausgerichtet sind, ist wie folgt:

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

<domain-config>

Syntax:
<domain-config cleartextTrafficPermitted=["true" | "false"]>
    ...
</domain-config>
kann Folgendes enthalten:
1 oder mehr <domain>
0 oder 1 <certificateTransparency>
0 oder 1 <trust-anchors>
0 oder 1 <pin-set>
Beliebige Anzahl von verschachtelten <domain-config>
description:
-Konfiguration für Verbindungen zu bestimmten Zielen, wie durch die domain-Elemente definiert.

Wenn mehrere domain-config-Elemente ein Ziel abdecken, wird die Konfiguration mit der spezifischsten (längsten) übereinstimmenden Domainregel verwendet.

<domain>

Syntax:
<domain includeSubdomains=["true" | "false"]>example.com</domain>
Attribute:
includeSubdomains
Wenn "true", stimmt diese Domainregel mit der Domain und allen Subdomains überein, einschließlich Subdomains von Subdomains. Andernfalls gilt die Regel nur für genaue Übereinstimmungen.

<certificateTransparency>

Syntax:
<certificateTransparency enabled=["true" | "false"]/>
description:
Wenn true, verwendet die App die Certificate Transparency-Logs, um Zertifikate zu validieren. Wenn eine App ihr eigenes Zertifikat (oder den Nutzerspeicher) verwendet, ist es wahrscheinlich, dass das Zertifikat nicht öffentlich und daher nicht mithilfe von Certificate Transparency überprüfbar ist. Standardmäßig ist die Bestätigung für diese Fälle deaktiviert. Es ist weiterhin möglich, die Bestätigung mit <certificateTransparency enabled="true"/> in der Domainkonfiguration zu erzwingen. Für jede <domain-config> erfolgt die Auswertung in dieser Reihenfolge:
  1. Wenn certificateTransparency aktiviert ist, aktivieren Sie die Bestätigung.
  2. Wenn ein <trust-anchors> "user" oder inline ist (d.h. "@raw/cert.pem") deaktivieren Sie die Bestätigung.
  3. Andernfalls verwenden Sie die geerbte Konfiguration.

<debug-overrides>

Syntax:
<debug-overrides>
    ...
</debug-overrides>
kann Folgendes enthalten:
0 oder 1 <trust-anchors>
description:
Überschreibungen, die angewendet werden sollen, wenn android:debuggable auf "true" gesetzt ist. Das ist normalerweise bei Builds, die nicht für die Veröffentlichung bestimmt sind und von IDEs und Build-Tools generiert werden, der Fall. In debug-overrides angegebene Trust-Anchors werden allen anderen Konfigurationen hinzugefügt. Certificate Pinning wird nicht durchgeführt, wenn in der Zertifikatskette des Servers einer dieser Trust-Anchors verwendet wird, die nur für das Debugging vorgesehen sind. Wenn android:debuggable auf "false" gesetzt ist, wird dieser Abschnitt vollständig ignoriert.

<trust-anchors>

Syntax:
<trust-anchors>
...
</trust-anchors>
kann Folgendes enthalten:
Beliebige Anzahl von <certificates>
description:
Eine Reihe von Trust-Ankern für sichere Verbindungen.

<certificates>

Syntax:
<certificates src=["system" | "user" | "raw resource"]
              overridePins=["true" | "false"] />
description:
Satz von X.509-Zertifikaten für trust-anchors-Elemente.
Attribute:
src
Die Quelle der CA-Zertifikate. Jedes Zertifikat kann einen der folgenden Status haben:
  • Eine Rohressourcen-ID, die auf eine Datei mit X.509-Zertifikaten verweist. Zertifikate müssen im DER- oder PEM-Format codiert sein. Bei PEM-Zertifikaten darf die Datei keine zusätzlichen Nicht-PEM-Daten wie Kommentare enthalten.
  • "system" für die vorinstallierten System-CA-Zertifikate
  • "user" für vom Nutzer hinzugefügte CA-Zertifikate
overridePins

Gibt an, ob die CAs aus dieser Quelle das Certificate Pinning umgehen. Wenn "true", wird kein Pinning für Zertifikatsketten durchgeführt, die von einer der CAs aus dieser Quelle signiert sind. Dies kann beim Debuggen von Zertifizierungsstellen oder beim Testen von Man-in-the-Middle-Angriffen auf den sicheren Traffic Ihrer App nützlich sein.

Der Standardwert ist "false", sofern nicht in einem debug-overrides-Element angegeben. In diesem Fall ist der Standardwert "true".

<pin-set>

Syntax:
<pin-set expiration="date">
...
</pin-set>
kann Folgendes enthalten:
Beliebige Anzahl von <pin>
description:
Eine Reihe von Public-Key-Pins. Damit eine sichere Verbindung als vertrauenswürdig eingestuft wird, muss einer der öffentlichen Schlüssel in der Vertrauenskette in der Gruppe der Pins enthalten sein. Informationen zum Format von Pins finden Sie unter <pin>.
Attribute:
expiration
Das Datum im Format yyyy-MM-dd, an dem die Pins ablaufen und das Anpinnen deaktiviert wird. Wenn das Attribut nicht festgelegt ist, laufen die Pins nicht ab.

Das Ablaufdatum trägt dazu bei, Verbindungsprobleme in Apps zu vermeiden, deren PIN-Satz nicht aktualisiert wird, z. B. wenn der Nutzer App-Updates deaktiviert.

<pin>

Syntax:
<pin digest=["SHA-256"]>base64 encoded digest of X.509
    SubjectPublicKeyInfo (SPKI)</pin>
Attribute:
digest
Der Digest-Algorithmus, der zum Generieren der PIN verwendet wird. Derzeit wird nur "SHA-256" unterstützt.