Netzwerksicherheitskonfiguration

Mit der Funktion „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 dieser Funktion sind:

  • Benutzerdefinierte Vertrauensanker: Sie können anpassen, welche Zertifizierungsstellen (Certificate Authorities, CAs) für die sicheren Verbindungen einer App vertrauenswürdig sind. Sie können beispielsweise bestimmten selbst signierten Zertifikaten vertrauen oder die Anzahl der öffentlichen Zertifizierungsstellen einschränken, denen die App vertraut.
  • Nur zum Debuggen:Sie können sichere Verbindungen in einer App sicher debuggen, ohne dass die installierte Basis ein zusätzliches Risiko darstellt.
  • Deaktivierung von Klartext-Traffic:Schützen Sie Apps vor der versehentlichen Verwendung von Klartext-Traffic (unverschlüsselt).
  • Zertifikatstransparenz aktivieren:Beschränken Sie die sicheren Verbindungen einer App auf die Verwendung von nachweislich protokollierten Zertifikaten.
  • Zertifikats-Pinning: Die sichere Verbindung einer App auf bestimmte Zertifikate beschränken.

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 in das Manifest Ihrer App aufnehmen, der auf diese Datei verweist. Im folgenden Codeausschnitt aus einem Manifest wird gezeigt, wie dieser Eintrag erstellt wird:

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

Vertrauliche Zertifizierungsstellen anpassen

Möglicherweise möchten Sie, dass Ihre App einem benutzerdefinierten Satz von Zertifizierungsstellen vertraut, anstatt den Standardzertifizierungsstellen der Plattform. Die häufigsten Gründe dafür sind:

  • Verbindung zu einem Host mit einer benutzerdefinierten Zertifizierungsstelle, z. B. einer selbst signierten Zertifizierungsstelle oder einer Zertifizierungsstelle, die intern innerhalb eines Unternehmens ausgestellt wird.
  • Beschränken Sie die Anzahl der Zertifizierungsstellen auf die vertrauenswürdigen CAs, anstatt alle vorinstallierten CAs zu verwenden.
  • Vertrauenswürdige zusätzliche Zertifizierungsstellen, die nicht im System enthalten sind.

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

Benutzerdefinierte Zertifizierungsstelle 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. Im folgenden Codeausschnitt wird veranschaulicht, wie Sie Ihre Anwendung in res/xml/network_security_config.xml für eine benutzerdefinierte Zertifizierungsstelle 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 selbst signierte oder nicht öffentliche CA-Zertifikat im PEM- oder DER-Format zu res/raw/my_ca hinzu.

Anzahl der vertrauenswürdigen Zertifizierungsstellen begrenzen

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

Die Konfiguration zur Begrenzung der vertrauenswürdigen Zertifizierungsstellen ähnelt dem Vertrauen einer benutzerdefinierten Zertifizierungsstelle für eine bestimmte Domain, mit dem Unterschied, dass in der Ressource mehrere Zertifizierungsstellen angegeben werden. Im folgenden Codeausschnitt wird gezeigt, wie Sie die vertrauenswürdigen Zertifizierungsstellen Ihrer App in res/xml/network_security_config.xml einschränken:

<?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 res/raw/trusted_roots die vertrauenswürdigen Zertifizierungsstellen im PEM- oder DER-Format 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 angeben.

Zusätzliche Zertifizierungsstellen vertrauen

Möglicherweise möchten Sie, dass Ihre App zusätzlichen Zertifizierungsstellen vertraut, die vom System nicht als vertrauenswürdig eingestuft werden. Das ist beispielsweise der Fall, wenn die Zertifizierungsstelle noch nicht im System enthalten ist oder die Anforderungen für die Aufnahme in das Android-System nicht erfüllt. Sie können mithilfe von Code wie dem folgenden Ausschnitt mehrere Zertifikatsquellen für eine Konfiguration in res/xml/network_security_config.xml angeben.

<?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, sollten Sie eine Verbindung zu einem lokalen Entwicklungsserver herstellen, der nicht das SSL-Zertifikat für Ihren Produktionsserver hat. Um dies ohne Änderung des Codes Ihrer App zu unterstützen, können Sie mit debug-overrides nur für die Debug-Phase gültige Zertifizierungsstellen angeben, die nur dann als vertrauenswürdig eingestuft werden, wenn android:debuggable true ist. Normalerweise wird dieses Flag von IDEs und Build-Tools automatisch für Builds festgelegt, die nicht zur Veröffentlichung bestimmt sind.

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

Im folgenden Auszug wird gezeigt, wie Sie Zertifizierungsstellen nur für die Debug-Funktion 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

Die Zertifikatstransparenz (Certificate Transparency, CT, RFC 9162) ist ein Internetstandard, der die Sicherheit digitaler Zertifikate verbessern soll. Zertifizierungsstellen müssen alle ausgestellten Zertifikate in ein öffentliches Protokoll einreichen, in dem sie erfasst werden. Dadurch wird die Transparenz und Rechenschaftspflicht beim Zertifikatsausstellungsverfahren erhöht.

Durch die Aufbewahrung eines überprüfbaren Protokolls aller Zertifikate erschwert die CT es böswilligen Akteuren erheblich, Zertifikate zu fälschen oder Zertifizierungsstellen, sie irrtümlich auszustellen. So werden Nutzer vor Man-in-the-Middle-Angriffen und anderen Sicherheitsbedrohungen geschützt. Weitere Informationen finden Sie auf der offiziellen Website von Certificate Transparency.

Standardmäßig werden Zertifikate akzeptiert, unabhängig davon, ob sie in einem CT-Log protokolliert sind. Damit Ihre App nur eine Verbindung zu Zielen mit Zertifikaten herstellt, die in einem CT-Log protokolliert sind, können Sie die Funktion entweder unter <base-config> oder <domain-config> aktivieren.

Klartext-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. Ab Android 9 (API-Level 28) ist die Unterstützung von Klartext standardmäßig deaktiviert.

Wenn Ihre App nur über sichere Verbindungen mit Zielen verbunden werden soll, können Sie die Unterstützung von Klartext (Verwendung des unverschlüsselten HTTP-Protokolls anstelle von HTTPS) für diese Ziele deaktivieren. Mit dieser Option lassen sich versehentliche Rückschritte in Apps aufgrund von Änderungen an URLs verhindern, die von externen Quellen wie Backend-Servern bereitgestellt werden. Weitere Informationen finden Sie unter NetworkSecurityPolicy.isCleartextTrafficPermitted().

Beispielsweise möchten Sie vielleicht, dass Ihre App dafür sorgt, dass Verbindungen zu secure.example.com immer über HTTPS erfolgen, um vertraulichen Traffic vor feindseligen Netzwerken zu schützen.

Im folgenden Auszug wird gezeigt, wie Sie den Klartext in res/xml/network_security_config.xml deaktivieren:

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

PIN-Zertifikate

Normalerweise vertrauen Apps allen vorinstallierten Zertifizierungsstellen. Wenn eine dieser Zertifizierungsstellen ein gefälschtes Zertifikat ausstellt, ist die App einem On-Path-Angriff ausgesetzt. Einige Apps beschränken die Anzahl der akzeptierten Zertifikate, indem sie entweder die Anzahl der vertrauenswürdigen Zertifizierungsstellen oder die Zertifikatsbindung einschränken.

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

Wenn Sie die Zertifikatsbindung verwenden, sollten Sie immer einen Sicherungsschlüssel angeben. So ist die Konnektivität Ihrer App nicht beeinträchtigt, wenn Sie auf neue Schlüssel umstellen oder die Zertifizierungsstelle ändern müssen (z. B. bei der Bindung an ein CA-Zertifikat oder ein Zwischenzertifikat dieser Zertifizierungsstelle). Andernfalls müssen Sie ein Update für die App veröffentlichen, um die Verbindung wiederherzustellen.

Außerdem können Sie eine Ablaufzeit für Markierungen festlegen, nach der keine Markierungen mehr vorgenommen werden. So lassen sich Verbindungsprobleme in Apps vermeiden, die nicht aktualisiert wurden. Wenn Sie jedoch ein Ablaufdatum für die angepinnten Zertifikate festlegen, können Angreifer diese umgehen.

Im folgenden Auszug wird gezeigt, wie Sie Zertifikate in res/xml/network_security_config.xml anpinnen:

<?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 der Konfigurationsübernahme

Werte, die nicht in einer bestimmten Konfiguration festgelegt sind, werden übernommen. Dadurch sind komplexere Konfigurationen möglich, während die Konfigurationsdatei lesbar bleibt.

Werte, die beispielsweise nicht in einem domain-config festgelegt sind, werden bei verschachtelten Elementen aus dem übergeordneten domain-config und bei nicht verschachtelten Elementen aus dem base-config übernommen. 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 einer Verbindung zu secure.example.com. Wenn Sie die Konfiguration für secure.example.com in der Konfiguration für example.com verschachteln, muss trust-anchors nicht dupliziert werden.

Im folgenden Ausschnitt sehen Sie, 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

Die Funktion „Netzwerksicherheitskonfiguration“ verwendet das XML-Dateiformat. Die Gesamtstruktur der Datei ist 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 von <base-config>
Beliebig viele <domain-config>
0 oder 1 von <debug-overrides>

<base-config>

syntax:
<base-config cleartextTrafficPermitted=["true" | "false"]>
    ...
</base-config>
kann Folgendes enthalten:
<trust-anchors> <certificateTransparency>
description:
Die Standardkonfiguration, die für alle Verbindungen verwendet wird, deren Ziel nicht durch eine domain-config abgedeckt ist.

Für nicht festgelegte Werte werden die Standardwerte der Plattform verwendet.

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

<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, sieht so aus:

<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) oder niedriger ausgerichtet sind, sieht so aus:

<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>
Beliebig viele verschachtelte <domain-config>
description:
-Konfiguration, die für Verbindungen zu bestimmten Zielen verwendet wird, wie von den domain-Elementen 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>
attributes:
includeSubdomains
Wenn "true", dann entspricht diese Domainregel der Domain und allen Subdomains, einschließlich Subdomains von Subdomains. Andernfalls gilt die Regel nur für exakte Übereinstimmungen.

<certificateTransparency>

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

<debug-overrides>

syntax:
<debug-overrides>
    ...
</debug-overrides>
kann Folgendes enthalten:
0 oder 1 <trust-anchors>
description:
Überschreibungen, die angewendet werden, wenn android:debuggable "true" ist. Dies ist normalerweise der Fall bei nicht veröffentlichten Builds, die von IDEs und Build-Tools generiert werden. Die in debug-overrides angegebenen Trust-Anchors werden allen anderen Konfigurationen hinzugefügt. Die Zertifikatsbindung wird nicht durchgeführt, wenn die Zertifikatskette des Servers einen dieser nur zur Fehlerbehebung vorgesehenen Trust-Anchors verwendet. Wenn android:debuggable "false" ist, wird dieser Abschnitt vollständig ignoriert.

<trust-anchors>

syntax:
<trust-anchors>
...
</trust-anchors>
kann Folgendes enthalten:
Beliebige Anzahl von <certificates>
description:
Trust-Anchors für sichere Verbindungen.

<certificates>

syntax:
<certificates src=["system" | "user" | "raw resource"]
              overridePins=["true" | "false"] />
description:
X.509-Zertifikate für trust-anchors-Elemente.
attributes:
src
Die Quelle der CA-Zertifikate. Jedes Zertifikat kann einer der folgenden Kategorien zugeordnet sein:
  • 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 Zertifizierungsstellen aus dieser Quelle die Zertifikatsbindung umgehen. Wenn "true" festgelegt ist, wird die Pinning nicht für Zertifikatsketten durchgeführt, die von einer der Zertifizierungsstellen aus dieser Quelle signiert wurden. Dies kann nützlich sein, um CAs zu debuggen oder Man-in-the-Middle-Angriffe auf den sicheren Traffic Ihrer App zu testen.

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 öffentlichen Schlüssel-Pins. Damit eine sichere Verbindung als vertrauenswürdig eingestuft werden kann, muss einer der öffentlichen Schlüssel in der Vertrauenskette zu den angepinnten Schlüsseln gehören. Informationen zum Format von Markierungen finden Sie unter <pin>.
attributes:
expiration
Das Datum im Format yyyy-MM-dd, an dem die Markierungen ablaufen und die Markierung somit deaktiviert wird. Wenn das Attribut nicht festgelegt ist, laufen die PINs nicht ab.

Mit Ablaufdatum können Verbindungsprobleme in Apps verhindert werden, für die keine Updates für die PIN-Sätze bereitgestellt werden, z. B. wenn der Nutzer App-Updates deaktiviert.

<pin>

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

Weitere Informationen

Weitere Informationen zur Konfiguration der Netzwerksicherheit finden Sie in den folgenden Ressourcen.

Codelabs