Die Secure Sockets Layer (SSL)—jetzt technisch als Transport Layer Security(TLS) bekannt-ist eingemeinsamer Baustein für verschlüsselte Kommunikation zwischen Clients und Servern. Es ist möglich, dass eine Anwendung SSL falsch verwendet, sodass böswillige Entitäten möglicherweise die Daten einer App über das Netzwerk abfangen können., Um sicherzustellen, dass dies in Ihrer App nicht der Fall ist, werden in diesem Artikel die häufigsten Fallstricke bei der Verwendung sicherer Netzwerkprotokolle hervorgehoben und einige größere Bedenken hinsichtlich der Verwendung von Public-Key-Infrastruktur (PKI) angesprochen.
Sie sollten auch AndroidSecurity Übersicht sowie PermissionsOverview lesen.
>
In einem typischen SSL-Nutzungsszenario wird ein Server mit einem Zertifikat konfiguriert, das einen öffentlichen Schlüssel sowie einen passenden privaten Schlüssel enthält., Im Rahmen des Handshakes zwischen einem SSL-Clientund Server beweist der Server, dass er über den privaten Schlüssel verfügt, indem er sein Zertifikat mit Public-Key-Kryptographie signiert.
Jeder kann jedoch sein eigenes Zertifikat und seinen privaten Schlüssel generieren, sodass ein einfacher Handshakedoesn nichts über den Server beweisen kann, außer dass der Server den privaten Schlüssel kennt, der dem öffentlichen Schlüssel des Zertifikats entspricht. Eine Möglichkeit, dieses Problem zu lösen, besteht darin, dass der Client einen Satz von einem oder mehreren Zertifikaten hat, denen er vertraut. Wenn das Zertifikat nicht im Set enthalten ist, ist theserver nicht vertrauenswürdig.,
Dieser einfache Ansatz hat mehrere Nachteile. Server sollten in der Lage sein, im Laufe der Zeit auf stärkere Schlüssel umzusteigen („Schlüsselrotation“), wodurch der öffentliche Schlüssel im Zertifikat durch einen neuen ersetzt wird. Leider muss jetzt die Client-App aktualisiert werden, da es sich im Wesentlichen um eine Serverkonfigurationsänderung handelt. Dies ist besonders problematisch, wenn der Serverist nicht unter der Kontrolle des App-Entwicklers, zum Beispiel wenn es sich um einen Webdienst eines Drittanbieters handelt. Diese App hat auch Probleme, wenn die App mit beliebigen Servern wie einem Webbrowser oder einer Mail-App sprechen muss.,
Um diese Nachteile zu beheben, werden Server normalerweise mit Zertifikaten konfiguriertvon bekannten Emittenten namens Certificate Authorities (CAs).Die Host-Plattform enthält im Allgemeinen eine Liste bekannter CAs, die sie trusts.As von Android 4.2 (Jelly Bean) enthält Android derzeit über 100 CAs, die in jeder Version aktualisiert werden. Ähnlich wie bei einem Server verfügt eine CA über ein Zertifikat und einen privaten Schlüssel. Bei der Ausgabe eines Zertifikats für einen Server signiert die Zertifizierungsstelle das Serverzertifikat mit seinem privaten Schlüssel. Theclient kann dann überprüfen, ob der Server über ein Zertifikat verfügt, das von einer der Plattform bekannten Zertifizierungsstelle ausgestellt wurde.,
Bei der Lösung einiger Probleme führt die Verwendung von CAs jedoch zu einem anderen. Da die CA issuescertificates für viele Server ausgibt, benötigen Sie noch eine Möglichkeit, um sicherzustellen, dass Sie mit dem gewünschten Server sprechen. Um dies zu beheben, identifiziert das von der CA ausgestellte Zertifikat den Servereither mit einem bestimmten Namen wie gmail.com oder ein Wildcard-Satz von Hosts wie *.google.com.
Das folgende Beispiel wird diese Konzepte etwas konkreter machen., Im folgenden Snippetaus einer Befehlszeile betrachtet der Befehl openssl
des Tools s_client
die Serverzertifikatinformationen von Wikipedia. Es spezifiziert Port 443, da dies der Standard für HTTPS ist. Der Befehl sendet die Ausgabe von openssl s_client
an openssl x509
, wodurch Informationen über Zertifikate gemäß dem X. 509-Standard formatiert werden. Insbesondere fragt der Befehl nach dem Betreff, der die Servernameninformationen enthält, und dem Aussteller, der die CA identifiziert.,
Sie können sehen,dass das Zertifikat für Server ausgestellt wurde, die * entsprechen. wikipedia.org von der RapidSSL CA.
Ein HTTPS-Beispiel
Angenommen, Sie haben einen Webserver mit acertificate, der von einer bekannten Zertifizierungsstelle ausgegeben wird, und können eine sichere Anforderung mit dem folgenden Code stellen:
Ja, es kann wirklich so einfach sein. Wenn Sie die HTTP-Anforderung anpassen möchten, können Sie toan HttpURLConnection
., Die Android-Dokumentation fürHttpURLConnection
enthält weitere Beispiele für den Umgang mit Anforderungs-und Antwortheadern, das Posten von Inhalten, das Verwalten von Cookies, die Verwendung von Proxys, das Zwischenspeichern von Antworten usw. In Bezug auf die Details zum Überprüfen von Zertifikaten und Hostnamen kümmert sich das Androidframework jedoch über diese APIs für Sie.Dies ist, wo Sie sein wollen, wenn überhaupt möglich. Das heißt, unten sind einige andere überlegungen.,
Häufige Probleme bei der Überprüfung von Serverzertifikaten
Angenommen, anstatt den Inhalt von zu empfangen, wird eine Ausnahme ausgelöst:
Dies kann aus mehreren Gründen geschehen, darunter:
- Die CA, die das Serverzertifikat ausgestellt hat, war unbekannt
- Das Serverzertifikat wurde nicht von einer CA signiert, sondern selbst signiert
- Der Serverkonfiguration fehlt eine Zwischen-CA
In den folgenden Abschnitten wird erläutert, wie Sie diese Probleme beheben und gleichzeitig Ihre Verbindung zum Server sichern können.,
Unbekannte Zertifizierungsstelle
In diesem Fall tritt die SSLHandshakeException
aufweil Sie eine CA haben, der das System nicht vertraut. Dies kann daran liegen, dass Sie ein Zertifikat von einer neuen Zertifizierungsstelle haben, der Android noch nicht vertraut, oder dass Ihre App auf einer älteren Version ohne Zertifizierungsstelle ausgeführt wird. Häufiger ist eine CA unbekannt, da es sich nicht um eine öffentliche CA handelt, sondern um eine private, die von einer Organisation wie einer Regierung,einem Unternehmen oder einer Bildungseinrichtung für den eigenen Gebrauch herausgegeben wird.
Glücklicherweise können Sie HttpsURLConnection
beibringen, einem bestimmten CAs-Satz zu vertrauen., Das Prozedurekann ein wenig verworren sein, also unten ist ein Beispiel, das eine bestimmte CA von nimmt InputStream
, verwendet es, um eine KeyStore
zu erstellen, die dann verwendet wird, um eineTrustManager
zu erstellen und zu initialisieren. A TrustManager
ist das, was das systemverwendet, um Zertifikate vom Server zu validierenund—durch Erstellen eines von a KeyStore
mit einem oder mehreren CAs—thosewill der einzige CAs sein, dem diese TrustManager
.,
In Anbetracht der neuen TrustManager
initialisiert das Beispiel eine neue SSLContext
, die SSLSocketFactory
Sie können die StandardeinstellungSSLSocketFactory
vonHttpsURLConnection
überschreiben. Auf diese Weise verwendet theconnection Ihren CAs zur Zertifikatsvalidierung.
Hier ist das Beispiel für die Verwendung einer Organisations-Zertifizierungsstelle der University of Washington:
Mit einer benutzerdefinierten TrustManager
, die Ihr CAs kennt, kann das System validierendass Ihr Serverzertifikat von einem vertrauenswürdigen Aussteller stammt.,
Achtung: Viele Websites beschreiben eine schlechte alternative Lösung, die darin besteht, eineTrustManager
zu installieren, die nichts bewirkt. Wenn Sie dies tun, können Sie Ihre Kommunikation genauso gut nicht verschlüsseln, da jeder Ihre Benutzer an einem öffentlichen Wi-Fi-Hotspotby mit DNS-Tricks angreifen kann, um Ihre Benutzer zu sendentraffic über einen eigenen Proxy, der vorgibt, Ihr Server zu sein. Der Angreifer kann dann Passwörter und andere persönliche Daten aufzeichnen., Dies funktioniert, da der Angreifer acertificate generieren kann und-ohne eine TrustManager
, die tatsächlich validiert, dass das Zertifikat von einer trustedsource stammt—Ihre App mit jedem sprechen könnte. Also tu das nicht, nicht einmal vorübergehend. Sie können Ihre App immer dem Aussteller des Serverzertifikats vertrauen lassen, also tun Sie es einfach.
selbstsigniertes Serverzertifikat
Der zweite Fall von SSLHandshakeException
istaufgrund eines selbstsignierten Zertifikats, was bedeutet, dass sich der Server als eigene CA verhält.,Dies ähnelt einer unbekannten Zertifizierungsstelle, sodass Sie den gleichen Ansatz aus dem vorherigen Abschnitt verwenden können.
Sie können Ihre eigene TrustManager
erstellen,wobei Sie diesmal dem Serverzertifikat direkt vertrauen. Dies hat alle oben diskutierten Nachteile, Ihre App direkt an ein Zertifikat zu binden, kann jedoch vorzeitig durchgeführt werden. Sie sollten jedoch vorsichtig sein, um sicherzustellen, dass Ihr selbstsigniertes Zertifikat über einen unangemessen starken Schlüssel verfügt. Ab 2012 ist eine 2048-Bit-RSA-Signatur mit einem Exponenten von 65537 expiringyearly akzeptabel., Wenn Sie Schlüssel drehen, sollten Sie nach Empfehlungen von anauthority (wie NIST) suchen, was akzeptabel ist.
Fehlende Zwischenzertifikatsbehörde
Der dritte Fall von SSLHandshakeException
tritt aufgrund einer fehlenden Zwischenzertifikatsbehörde auf. Die meisten publicCAs signieren Serverzertifikate nicht direkt. Stattdessen verwenden sie ihr Haupt-CA-Zertifikat,das als Root-CA bezeichnet wird, um Zwischenzertifikate zu signieren. Sie tun dies, damit die Wurzel CA kann storedoffline Risiko von Kompromissen zu reduzieren., Betriebssysteme wie Android vertragen jedoch typischerweise nur Root-CAs direkt, was eine kurze Vertrauenslücke zwischen dem Servercertificate—signiert von der Zwischen—CA-und dem Certificate Verifier,der die Stamm-CA kennt, hinterlässt. Um dies zu lösen, sendet der Server dem Client nicht nur sein Zertifikat während des SSL-Handshakes, sondern eine Kette von Zertifikaten von der Server-CA über alle Zwischenprodukte, die erforderlich sind, um eine vertrauenswürdige Stamm-CA zu erreichen.
Um zu sehen, wie das in der Praxis aussieht, hier ist die Mail.Google.,com certificatechain wie von der openssl
s_client
Befehl angezeigt:
Dies zeigt, dass der Server ein Zertifikat für E-Mails sendet.Google.comissued durch die Thawte SGC CA, die ist eine zwischen CA, und eine zweite certificatefor die Thawte SGC CA ausgestellt durch eine Verisign CA, die ist die primäre CA, dass ‚ strusted durch Android.
Es ist jedoch nicht ungewöhnlich, dass ein Server so konfiguriert wird, dass er nicht die erforderliche Intermediate-CA enthält., Zum Beispiel ist hier ein Server, der einen Fehler in Android-Browsern undexceptions in Android-Apps verursachen kann:
Interessant ist hier, dass der Besuch dieses Servers in den meisten Desktop-Browsern keinen Fehler verursacht, wie es eine völlig unbekannte CA oder ein selbstsigniertes Serverzertifikat tun würde. Dies liegt daran, dass die meisten Desktop-Browser im Laufe der Zeit vertrauenswürdige Zwischenspeicher zwischenspeichern. Sobald ein Browser von einer Site aus eine Zwischen-CA besucht und von ihr erfahren hat, muss die Zwischen-CA beim nächsten Mal nicht mehr in der Zertifikatskette enthalten sein.,
Einige Websites tun dies absichtlich für sekundäre Webserver, die zum Bereitstellen von Ressourcen verwendet werden. Zum Beispiel könnten Sie in Ihrer Haupt-HTML-Seite diente, die von einem server mit einem vollen certificatechain, aber haben Server für Ressourcen wie Bilder, CSS oder JavaScript nicht enthalten theCA, vermutlich, um Bandbreite zu sparen. Leider bieten diese Server manchmal anein Webdienst, den Sie von Ihrer Android-App aus anrufen möchten, was nicht so verzeihend ist.
Es gibt zwei Ansätze, um dieses Problem zu lösen:
- Konfigurieren Sie den Server so, dass er die Zwischen-CA in die Serverkette einschließt., Die meisten CAs bieten Dokumentation darüber, wie dies für alle gängigen Webserver zu tun. Dies ist der einzige Ansatz, wenn Sie die Site benötigen, um mit Standard-Android-Browsern zumindest über Android 4.2 zu arbeiten.
- Oder behandeln Sie die Zwischen-CA wie jede andere unbekannte CA und erstellen Sie eine
TrustManager
, um ihr direkt zu vertrauen, wie in den beiden vorherigen Abschnitten.
Häufige Probleme bei der Überprüfung des Hostnamens
Wie am Anfang dieses Artikels erwähnt,gibt es zwei wichtige Teile zum Überprüfen einer SSL-Verbindung., Die erste Möglichkeit, das Zertifikat zu überprüfen, ist von einer vertrauenswürdigen Quelle, die der Fokus der previoussection war. Der Schwerpunkt dieses Abschnitts liegt auf dem zweiten Teil: Stellen Sie sicher, dass der Server, auf dem Sie unterwegs sind, das richtige Zertifikat hat. Wenn dies nicht der Fall ist, wird normalerweise ein Fehler wie dieser angezeigt:
Ein Grund, warum dies passieren kann, ist ein Serverkonfigurationsfehler. Der Server ist mit einem Zertifikat konfiguriert, das kein Subject-oder Subject-alternatives Namensfeld hat, das mit dem Server übereinstimmt, den Sie erreichen möchten. Es ist möglich, ein Zertifikat zu verwendenmit vielen verschiedenen Servern., Zum Beispiel mit Blick auf die google.com zertifikat mitopenssl
s_client -connect google.com:443 | openssl x509 -text
Sie können sehen, dass ein subjectthat unterstützt *.google.com aber auch andere alternative Namen für *.youtube.com,*.android.com, und andere. Der Fehler tritt nur auf, wenn der Servername, mit dem Sie eine Verbindung herstellen, vom Zertifikat nicht als akzeptabel aufgeführt wird.
Leider kann dies auch aus einem anderen Grund passieren: virtuelles Hosting. Wenn Sie aserver für mehr als einen Hostnamen mit HTTP freigeben, kann der Webserver anhand der HTTP/1.1-Anforderung feststellen, nach welchem Zielhostnamen der Client sucht., Leider ist dies mithttps kompliziert, da der Server wissen muss, welches Zertifikat zurückgegeben werden soll, bevor er die HttpRequest sieht. Um dieses Problem zu beheben, neuere Versionen von SSL, insbesondere TLSv.1.0 und höher,Support Server Name Indication (SNI), mit dem der SSL-Client den Intendedhostname für den Server angeben kann, damit das richtige Zertifikat zurückgegeben werden kann.
GlücklicherweiseHttpsURLConnection
UNTERSTÜTZTSSNI seit Android 2.3. Ein workaroundif Sie Android 2 unterstützen müssen.,2 (und älter) besteht darin, einen alternativen Host auf einem eindeutigen Port einzurichten, damit eindeutig ist, welches Serverzertifikat zurückgegeben werden soll.
Die drastischere Alternative besteht darin, HostnameVerifier
durch eine zu ersetzen, die nicht den Hostnamen Ihres virtuellen Hosts verwendet, sondern standardmäßig den vom Server zurückgegebenen.
Achtung: Das Ersetzen von HostnameVerifier
kann sehr gefährlich sein, wenn der andere virtuelle Host nicht unter Ihrer Kontrolle steht, da anon-pathattacker ohne Ihr Wissen den Datenverkehr zu einem anderen Server leiten kann.,
Wenn Sie immer noch sicher sind, dass Sie die Hostnamenüberprüfung überschreiben möchten, ist hier ein Beispieldas ersetzt den Verifikator für eine einzelne URLConnection
durch eine, die immer noch überprüft, ob der Hostname zumindest von der App erwartet wird:
Aber denken Sie daran, wenn Sie die Hostnamenüberprüfung ersetzen, insbesondere Aufgrund des virtuellen Hostings, ist es immer noch sehr gefährlich, wenn der andere virtuelle Host nicht unter Ihrer Kontrolle ist und Sie eine alternative Hosting-Arrangementthat vermeidet dieses Problem.,
Warnungen zur direkten Verwendung von SSLSocket
Bisher konzentrierten sich die Beispiele auf HTTPS mit HttpsURLConnection
.Manchmal müssen Apps SSL getrennt von HTTP verwenden. Beispielsweise kann eine E-Mail-App SSL-variantsof SMTP, POP3 oder IMAP verwenden. In diesen Fällen möchte die App SSLSocket
direkt verwenden, ähnlich wie HttpsURLConnection
intern.
Die beschriebenen Techniken zur Behandlung von Zertifikatsprüfungsproblemen gelten auch für SSLSocket
.,Wenn Sie eine benutzerdefinierte TrustManager
, wird anHttpsURLConnection
eine SSLSocketFactory
.Wenn Sie also eine benutzerdefinierte TrustManager
mit einerSSLSocket
, befolgen Sie die gleichen Schritte und verwenden Sie diese SSLSocketFactory
um IhreSSLSocket
zu erstellen.
Achtung:SSLSocket
führt keine Überprüfung des Hostnamens durch. Ihre App muss ihren eigenen Hostnamen überprüfen, vorzugsweise indem Sie getDefaultHostnameVerifier()
mit dem erwarteten Hostnamen aufrufen., Furtherbeware, dass HostnameVerifier.verify()
nicht eine Ausnahme auf Fehler, sondern gibt einen booleschen Wert zurück, so dass Sie sich mustexplicitly überprüfen.
Hier ist ein Beispiel, wie Sie dies tun können. Es zeigt, dass beim Verbinden togmail.com port 443 ohne SNI-Unterstützung erhalten Sie ein Zertifikat formail.google.com. Dies wird in diesem Fall erwartet, überprüfen Sie also, ob das Zertifikat tatsächlich für mail.google.com:
Denylisting
SSL ist stark auf CAs angewiesen, um Zertifikate nur an die ordnungsgemäß verifizierten Ownersof-Server und-Domänen auszustellen., In seltenen Fällen werden CAs entweder ausgetrickst oder, im Fall von Comodo oder DigiNotar,verletzt, was dazu führt, dass Zertifikate für einen Hostnamen ausgestellt werdenein anderer als der Eigentümer des Servers oder der Domäne.
Um dieses Risiko zu mindern, hat Android die Möglichkeit, bestimmte Zertifikate oder evenwole CAs zu einer Denylist hinzuzufügen. Während diese Liste historisch in das Betriebssystem integriert war, startin Android 4.2 kann diese Liste remote aktualisiert werden, um zukünftige Kompromisse zu bewältigen.,
Pinning
Eine App kann sich weiter vor betrügerisch ausgestellten Zertifikaten von atechnique schützen, die als Pinning bekannt sind. Dies verwendet im Grunde das Beispiel in der unbekannten CA caseabove, um die vertrauenswürdige CAs einer App auf einen kleinen Satz zu beschränken, von dem bekannt ist, dass er von den Servern der App verwendet wird. Dies verhindert, dass der Kompromiss eines der anderen über 100 CAs im System zu einem Verstoß gegen den sicheren Kanal von Apps führt.
Client-Zertifikate
Dieser Artikel hat sich auf den Benutzer von SSL konzentriert, um die Kommunikation mit Servern zu sichern., SSL unterstützt auch den Begriff Clientzertifikate, mit denen der Server die Identität von aclient überprüfen kann. Über den Rahmen dieses Artikels hinaus ähneln die beteiligten Techniken specifyinga custom TrustManager
.
Nogotofail: A Network traffic Security testing Tool
Nogotofail ist ein Tool, mit dem Sie auf einfache Weise bestätigen können, dass Ihre Apps vor bekannten TLS / SSL-Schwachstellen und Fehlkonfigurationen sicher sind. Es ist ein automatisiertes, leistungsstarkes und skalierbares Tool zum Testen von Netzwerksicherheitsproblemen auf jedem Gerät, dessen Netzwerkverkehr durchlaufen werden kann.,
Nogotofail ist nützlich für drei Hauptanwendungsfälle:
- Fehler und Schwachstellen finden.
- Korrekturen überprüfen und auf Regressionen achten.
- Verstehen, welche Anwendungen und Geräte welchen Datenverkehr erzeugen.
Nogotofail funktioniert für Android, iOS, Linux, Windows, Chrome OS, OSX, in der Tat jedes Gerät, das Sie mit dem Internet verbinden. Es gibt einen benutzerfreundlichen Client zum Konfigurieren der Einstellungen und zum Abrufen von Benachrichtigungen unter Android und Linux sowie die Angriffs-Engine selbst, die als Router, VPN-Server oder Proxy bereitgestellt werden kann.