iOS: Certificate Pinning per Konfiguration

App-Entwickler können die für TLS-Verbindungen erlaubten Schlüssel seit iOS 14 per Konfiguration einschränken.

Lesezeit: 7 Min.
In Pocket speichern
vorlesen Druckansicht Kommentare lesen 8 Beiträge
Von
  • Andreas Kurtz
Inhaltsverzeichnis

Apps schauen beim Aufbau verschlüsselter Verbindungen häufig ganz genau nach, ob sie mit dem richtigen Server sprechen – ob sich ein Server also auch tatsächlich mit dem erwarteten TLS-Zertifikat ausweist. Bislang mussten App-Entwickler für ein solches Certificate Pinning stets eigenen Code schreiben – mit iOS 14 geht das nun deutlich einfacher. Über diese bislang weitestgehend unbekannte Möglichkeit zum Certificate Pinning per Konfiguration informiert Apple die Entwickler-Gemeinde per News-Meldung; das Folgende gibt einen schnellen Einstieg in Pinning im Allgemeinen und die konkrete Umsetzung unter iOS.

Beim Aufbau einer verschlüsselten Verbindung über das Transport Layer Security (TLS) Protokoll authentifiziert sich der Server gegenüber der App mit einem Zertifikat. Der in dem Zertifikat enthaltene öffentliche Schlüssel des Servers wird verwendet, um sich auf ein gemeinsames Geheimnis für die Verschlüsselung zu verständigen. Damit die App weiß, dass sie auch wirklich mit dem angedachten Backend spricht – und nicht etwa mit einem Machine-in-the-Middle-Angreifer – muss sie erst die Vertrauenswürdigkeit des Zertifikats prüfen. Dazu ist jedes Zertifikat von einer Zertifizierungsstelle (Certificate Authority, CA) signiert.

Das Betriebssystem prüft dann bei jedem Verbindungsaufbau, dass unter anderem der in dem Zertifikat angegebene Hostname dem des angefragten Systems entspricht und dass das vom Server präsentierte Zertifikat von einer vertrauenswürdigen Zertifizierungsstelle (Trusted CA) ausgestellt und signiert wurde. Für diesen letzten Schritt hat iOS einen systemweiten Zertifikatsspeicher (Trust Store), in dem die Root-Zertifikate zahlreicher öffentlicher CAs vorinstalliert sind.

Schaut man sich die Liste der in iOS 14 vorinstallierten Root-Zertifikate aber genauer an, könnte einem angst und bange werden. Der Trust Store enthält mehr als 150 als vertrauenswürdig eingestufte Root-Zertifikate von teils mehr oder weniger bekannten, auch regierungsnahen, Zertifizierungsstellen vieler Länder.

Pinning: Bevor Daten fließen prüft die App, ob das Zertifikat die festgenagelten Kriterien erfüllt.

Im Hinblick auf die zahlreichen Vorfälle in der Vergangenheit, von der Kompromittierung ganzer CAs, bis hin zum Ausstellen gefälschter Zertifikate, ist ein gewisses Misstrauen durchaus angebracht. Um Missbrauch möglichst zu verhindern, wurden in den vergangenen Jahren Kontrollinstrumente wie Certificate Transparency (CT) eingeführt. Trotzdem stellt sich die Frage, ob man tatsächlich allen CAs im Trust Store uneingeschränkt vertrauen möchte.

Weiter besteht das Risiko, dass Benutzer per Social Engineering sogenannte Konfigurationsprofile oder Mobile-Device-Management-Profile untergejubelt bekommen und sich so unbemerkt zusätzliche CAs einfangen. Apple hat die Hürden für solche Angriffe zwar erhöht, aber ein gewisses Risiko bleibt bestehen.

Aus diesen Gründen gehen immer mehr Apps dazu über, sich nicht auf die Validierung des Betriebssystems zu verlassen, sondern ihre Zertifikate selbst unter die Lupe zu nehmen. Bei diesem sogenannten Certificate Pinning wird das erwartete TLS-Zertifikat meist schon während der Entwicklung in der App hinterlegt und später bei jedem Verbindungsaufbau geprüft, ob das Backend auch das erwartete Zertifikat präsentiert.

Auch Standards wie der OWASP Mobile Application Security Verification Standard (MASVS) fordern solche App-eigenen Zertifikatsvalidierungen in der Verifizierungsstufe L2 für alle Apps, die mit sensitiven Daten hantieren, wie beispielsweise Gesundheits- oder Finanz-Apps.

In der Praxis haben sich verschiedene Pinning-Verfahren etabliert, bei denen entweder das gesamte Zertifikat in der App hinterlegt wird oder nur der im Zertifikat enthaltene öffentliche Schlüssel (Public Key Pinning). Bislang mussten App-Entwickler dafür eigenen Code schreiben oder fertige Open-Source-Lösungen wie TrustKit in ihre App integrieren. Mit iOS 14 geht das nun deutlich einfacher, ohne den Code der App anpassen zu müssen.

Auf Apples Plattformen kümmert sich schon seit Längerem ein Mechanismus namens App Transport Security (ATS) darum, dass für alle Apps HTTPS erzwungen wird und Mindestanforderungen an eine sichere TLS-Verbindung eingehalten werden. Dieser Mechanismus wurde mit iOS 14 nun erweitert und bietet Apps fortan die Möglichkeit, die erwarteten Schlüssel ihrer Kommunikationspartner einfach in der zentralen Info.plist Konfigurationsdatei zu hinterlegen.

Für alle Verbindungen, die eine App dann über die Standard API, konkret über das URL Loading System initiiert, gleicht iOS die jeweils vom Backend gemeldeten Schlüssel mit den in der Konfiguration hinterlegten Schlüsseln ab. Stimmen die Schlüssel nicht überein, wird der Verbindungsaufbau abgebrochen und mit einer Fehlermeldung beantwortet. Auf diese Weise können Angriffe auf die Kommunikation abgewehrt werden, selbst wenn ein Angreifer im Besitz eines gefälschten Zertifikats von einer vertrauenswürdigen CA wäre.

Wichtig ist, dass dieser Schutzmechanismus tatsächlich nur für Verbindungen über das URL Loading System greift. Wenn Entwickler nicht die Standard-APIs verwenden, sondern über Low-Level-Methoden wie das Network Framework, CFNetwork oder Sockets eigene Lösungen bauen, greifen die Einschränkungen nicht.

Für Android Apps steht übrigens ein solcher Mechanismus über die Network Security Configuration schon seit Längerem zur Verfügung. Seit Android 7.0 lassen sich hier Sicherheitseinstellungen und Zertifikate beziehungsweise Schlüssel auf ähnliche Weise per Konfiguration festlegen.

Certificate oder Public Key Pinning kann auf verschiedenen Ebenen ansetzen. Eine App könnte direkt das End-Zertifikat (Leaf Certificate) beziehungsweise den Schlüssel des Servers prüfen und dann nur noch eine Verbindung aufbauen, wenn vom Server exakt der vorkonfigurierte Schlüssel zurückgemeldet wird. Das kann aber ganz schnell zu Problemen führen, wenn sich der Schlüssel des Servers nämlich mal ändern sollte, weil er beispielsweise zurückgerufen oder ausgetauscht wurde. Dann kommt die App nicht mehr zu ihrem Backend.

Deutlich weniger fehleranfällig ist es daher, anstatt einzelner Server-Zertifikate nur die Zertifizierungsstelle vorzuschreiben. Dies geschieht, indem man übergeordnete Zertifikate innerhalb der Zertifikatskette, wie bestimmte Intermediate- oder Root-Zertifikate einer CA, festnagelt. Ein solcher Ansatz zeigt sich robuster gegenüber Zertifikatswechseln und stellt trotzdem sicher, dass nur Zertifikate akzeptiert werden, die von der vorgeschriebenen Zertifizierungsstelle ausgestellt wurden. So erreicht man immerhin, nur der einen CA vertrauen zu müssen, nicht aber den Hundert anderen im Trust Store. Für Enterprise-Apps ließe sich hier auch ohne weiteres eine unternehmensinterne CA erzwingen.

Apropos Firmen-CA: In Firmen-Netzen, in denen TLS-gesicherte Verbindungen inspiziert werden, indem ein Monitoring-Gerät sich aktiv in die Verbindung einklinkt, wird es zu Problemen kommen. Auch wenn dessen CA scheinbar gültige Zertifikate ausstellt, erkennt das Pinning das untergeschobene MITM-Zertifikat und bricht die Verbindung ab.