Android-Updates und TLS-Verbindungen
Posted on 2020-05-29 by
Android-Gerätehersteller sind bekannt für ihre kurzen Support-Zeiträume. Sie bieten nur für eine begrenzte Zeit Updates an oder liefern sogar Geräte mit alten Android-Versionen aus. Entwickler haben sich so mit einer zersplitterten Verteilung von Android-Versionen auseinanderzusetzen. Android 4.x wird noch immer von ungefähr 2% der auf Google Play aktiven Geräte verwendet. Alte Telefone haben für gewöhnlich noch ordentliche Leistungsreserven und nach einem Update auf ein Custom-ROM sind sie sogar bis zum heutigen Tag bestens ausgestattet. Unglücklicherweise gibt es nicht für alle Geräte Custom-ROMs und nicht alle Anwender wollen sich mit den möglichen Schwierigkeiten beschäftigen, die deren Installation mit sich bringen kann.
AntennaPod ist ein, von mir betriebener,
quelloffener Podcast-Manager für Android. AntennaPod hängt nicht von einem
zentralen Server ab, sondern holt sich die Podcast-Quellen direkt über das
Gerät. Zum Schutz der Nutzerdaten ziemlich nett, weil niemand eine komplette
Liste der Abos erhält. Leider stoßen mehr und mehr Nutzer alter
Android-Versionen auf Probleme mit bestimmten Podcast-Feeds. Der Grund dafür
ist, dass Server Updates auf aktuellere TLS-Versionen erhielten, die auf den
Geräten nicht zur Verfügung stehen. Eine Aktualisierung der TLS-Version auf
Servern ist definitiv etwas Gutes, da es die Kommunikation sicherer
macht. Die meisten Browser bringen deshalb ihren eigenen Stack mit, der
ihnen ein Update unabhängig vom Gerätehersteller ermöglicht. Leider kommt es
bei allen anderen Apps, wie AntennaPod, die von Verbindungen zu mehreren
Servern außerhalb ihrer Kontrolle abhängen, zu Problemen. Anwender finden
dann Download-Fehler wie folgenden: Failure in SSL Library, usually a
protocol error
. Das ist ziemlich schlecht, da sie Nutzer daran hindern,
Podcasts zu hören. Obwohl dies im Grunde ein Versagen der Gerätehersteller
ist, fällt es letztlich auf die App-Entwickler zurück.
Die Unterstützung von TLSv1.1
und TLSv1.2
begann mit Android 4.1 und
wurde Standard in Android 5.0. Es gibt auch eine Anzahl von Cipher-Suites
und Zertifikaten, die in Android 4.x nicht unterstützt werden. Auch wenn
dieses Problem momentan nur Android-4.x-Nutzer betrifft, werden in Zukunft
weitere folgen, nachdem Server auf TLSv1.3
aktualisiert wurden. TLSv1.3
wurde zum ersten Mal mit Android 10 ausgeliefert, das auf ungefähr 8% der
auf Google Play angemeldeten Geräte läuft. Einzelheiten zur
SSL-Unterstützung in Android findet man auf der SSLSocket reference
page. Die
Entwickler haben sich nun mit der Tatsache auseinanderzusetzen, dass
Hersteller Software-Updates vernachlässigen.
Dies ist ein bekanntes Problem, also hat Google eine mit
ProviderInstaller
benannte Bibliothek veröffentlicht. Sie ist wirklich
einfach anzuwenden (ProviderInstaller.installIfNeeded(context);
) und
behebt all diese Probleme augenblicklich. Weil der Provider mittels der
Google Play Services unabhängig von der App auf dem neuesten Stand bleibt,
müssen sich App-Entwickler darum nicht mehr kümmern.
Das klingt zu schön um wahr zu sein, oder? Schön, Googles
ProviderInstaller
hat einen gewichtigen Nachteil. Die Bibliothek ist nicht
quelloffen, also kann sie nicht für Apps genutzt werden, die auf F-Droid
veröffentlicht werden. AntennaPod wird momentan in zwei verschiedenen
Varianten hergestellt: eine ist 100% freie Software für F-Droid und eine mit
der ProviderInstaller
-Bibliothek für den Google Play Store. Dies bedeutet,
dass F-Droid-Nutzer außen vor bleiben. Sie erleben weiterhin
Verbindungsprobleme bei manchen Servern und betrachten diese als einen Bug
in AntennaPod.
Eine Alternative, die in F-Droid funktioniert, ist die Aufnahme der
Open-Source-Bibliothek
Conscrypt
. Die Einbindung der
Bibliothek in AntennaPod wurde erstmalig von @Slinger in einem Pull Request
für AntennaPod
vorgeschlagen. Wenngleich die Einbindung von Conscrypt
in eine App genauso
einfach ist wie die Verwendung von Google’s ProviderInstaller
, hat sie
zwei Hauptnachteile:
- App-Entwickler sind gezwungen, regelmäßig den Provider zu aktualisieren. Das bedeutet zusätzliche Arbeit für die Betreiber und kann bei Apps, die einen langsamen Entwicklungszyklus haben, Ärger machen.
- Die Einbindung von
Conscrypt
erhöht die APK-Größe. Im Fall von AntennaPod bedeutet das, dass die App ungefähr 4 MB größer wird, was eine Zunahme von 40% bedeutet, für eine weitestgehend unsichtbare Änderung. Zu berücksichtigen ist, dass jede App dies tun müsste, um einen aktualisierten TLS-Stack zu erhalten. Wenn jede App auf F-Droid, die Verbindungen ins Netz herstellt, zusätzlich 4 MB TLS-Bibliotheken einbinden müsste, würde dies zu einer beachtlichen Erhöhung der Speicherauslastung führen.
Glücklicherweise gibt es dafür eine Lösung! Der Plan ist, eine quelloffene
Provider-Anwendung zu schreiben (so wie eben Googles Provider), die nichts
anderes tut, als Conscrypt
einzubinden und eine stabile API
bereitzustellen, die es anderen Apps ermöglicht es zu laden. Sie kann dann
unabhängig von Apps wie AntennaPod oder F-Droid aktualisiert werden. Die
Provider-App könnte einfach eine Klasse besitzen, in etwa so wie hier:
public static void install() {
Security.insertProviderAt(Conscrypt.newProvider(), 1);
Log.d(TAG, "Provider installed.");
}
Wir könnten dann eine quelloffene Bibliothek entwickeln, die den
ClassLoader
nutzt, um die Conscrypt
-Bibliothek aus der Provider-App
einzuschließen.
Context targetContext = context.createPackageContext("com.bytehamster.providerinstaller",
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
ClassLoader classLoader = targetContext.getClassLoader();
Class installClass = classLoader.loadClass("com.bytehamster.providerinstaller.ProviderInstallerImpl");
Method installMethod = installClass.getMethod("install", new Class[]{ });
installMethod.invoke(null);
installed = true;
Programmtextbeispiele sind (etwas detaillierter) auf GitHub Gist abrufbar.
Klar, einfach Code aus einer anderen App einschließen, stellt ein Sicherheitsrisiko dar. Durch Einschluss des Providers führt man fremden Code im eigenen App-Kontext aus. Wie kann man nachweisen, dass der Provider nicht böswillig ist? Es gibt ein paar Verfahren, um zu überprüfen, dass dem Provider vertraut werden kann:
- Eine vertrauenswürdige App kann der Provider sein. Die F-Droid-App selbst könnte den Provider einbinden, ihn auf dem neusten Stand halten und die stabile API bereitstellen. Apps könnten dann den Paketnamen von F-Droid fest programmieren und dessen Signatur überprüfen. Das Problem bei diesem Ansatz ist, dass Anwender, die F-Droid selbst kompilieren oder Alternativen wie G-Droid verwenden, nicht die aktualisierten Bibliotheken nutzen könnten.
- Die Programmbibliothek könnte das Android-System nach kompatiblen
Conscrypt
-Provider-Apps durchsuchen und eine von ihnen einschließen. Um sicherzustellen, dass dies sicher ist, wäre es möglich den Provider nur einzuschließen, wenn es sich um eine System-App handelt. So könnte die F-Droid-RechteerweiterungConscrypt
einbinden und bereitstellen. Viele F-Droid-Anwender nutzen allerdings die Rechteerweiterung nicht, somit würden wir immer noch nicht alle Anwender erreichen. - Für mich scheint die beste Lösung, eine eigenständige App (wie
org.fdroid.securityprovider
) zu sein, dieConscrypt
bereitstellt. Das wurde auch im F-Droid-Forum so diskutiert und ursprünglich von@bubu
vorgeschlagen. Eine vertrauenswürdige Entität wie F-Droid könnte den Provider herstellen und mit ihren Schlüsseln signieren. Diese könnten dann durch die aufrufenden Apps, dieConscrypt
einbinden möchten, verifiziert werden.
Ich sähe es sehr gerne, wenn es sich in diese Richtung bewegen würde. Wir sollten unbedingt die Möglichkeiten einer vollständig quelloffenen, sicheren Provider-App ausloten. Leider bin ich mit dem Betrieb von AntennaPod ziemlich beschäftigt. Daher kann ich mich nicht um die Programmbibiothek und Installationsanwendung kümmern. Auf GitHub Gist liegt eine Machbarkeitsstudie vor, der aber Sicherheitsprüfungen fehlen. Es wäre wahrscheinlich auch gut, einige einfache Verfahren zu ergänzen, die Anwender darauf hinweisen, den Provider bei TLS-Fehlern zu installieren. Wer Interesse an der Erstellung eines quelloffenen Providers hat, sollte einen Blick ins F-Droid Forum werfen.
Einige Anmerkungen:
- Dieser Post wurde aus der Sicht eines App-Entwicklers geschrieben. Ich versuche, AntennaPod so zu gestalten, dass es für alle Anwender optimal funktioniert, einschließlich derjenigen mit Android 4.x. Aus der Anwenderperspektive sollte man darüber nachdenken, ob man alte Android-Versionen wie 4.x noch verwenden will. Android 4.4 wurde 2014 veröffentlicht, was 6 Jahre her ist. Viele kritische Sicherheitslücken wurden seither geschlossen. Ein so altes Gerät ins Internet zu lassen, kann ein ziemlich großes Sicherheitsrisiko sein, unabhängig davon, welche TLS-Bibliotheken in den Apps eingebunden sind.
- Bevor ich mich hiermit beschäftigt habe, wusste ich nicht, dass man
ClassLoader
nutzen kann, um den Code einer anderen App auszuführen. Das ist ziemlich nett und kann für Dinge wie Plugins verwendet werden. Ich würde gerne erfahren, was andere Entwickler damit erstellen.