Erste Schritte mit der React-Native-Sicherheit
Kingsley Ubah
7. April 2022
0 Min. LesezeitReact bietet eine einfache und intuitive Möglichkeit, interaktive Benutzeroberflächen zu erstellen. Damit können Sie komplexe Anwendungen aus kleinen, isolierten Code-Bausteinen, sogenannten Komponenten, entwickeln. React Native ist eine Erweiterung von React, mit der Entwickler Techniken für Webtechnologien wie JavaScript mit React kombinieren können, um plattformübergreifende mobile Apps zu erstellen.
So können Entwickler Code einmal schreiben und auf mehreren Plattformen nutzen, was die Entwicklungszeit verkürzt. React Native verwendet ein virtuelles DOM, um Anwendungskomponenten und Code auf Geräten mit Android, Android TV, iOS, macOS, tvOS, Web, Windows und UWP auszuführen.
Diese breite Akzeptanz ist für React von Vorteil, denn mobile Technologien entwickeln sich in beispiellosem Tempo weiter. Bis 2025 wird es weltweit voraussichtlich 7,49 Milliarden Nutzer mobiler Geräte geben. Mobile Apps sind inzwischen allgegenwärtig und werden immer ausgefeilter darin, Nutzerdaten zu teilen, zu verarbeiten und zu schützen.
Wenn Sie eine nutzerorientierte Anwendung entwickeln, sind Sie dafür verantwortlich, die Informationen der App-Nutzer und andere vertrauliche Serverinformationen zu schützen. Sie müssen also sicherstellen, dass jeder nur auf die Inhalte zugreifen kann, für die er autorisiert ist, und dass die in der Datenbank gespeicherten Nutzerinformationen sicher bleiben.
Zum Schutz von Endnutzerinformationen dürfen Apps keine privaten Schlüssel, Datenbankinformationen, vertraulichen Dateien oder Seitenbereiche offenlegen, die die Struktur oder Funktionsweise des Backends zeigen. Sehen wir uns daher einige Sicherheitsherausforderungen an, mit denen React-Native-Entwickler bei der Entwicklung mobiler Apps konfrontiert sind, etwa sichere Datenübertragung, Authentifizierungsprotokolle und Sicherheitslücken in Abhängigkeiten. Außerdem zeigen wir Ihnen, wie Sie die einzelnen Herausforderungen bewältigen können.
Sichere Datenübertragung
Es ist schwer, sich eine mobile App vorzustellen, die keine Daten von einem Remote-Server benötigt. Standardmäßig verwendet React Native für API-Aufrufe und Datenübertragungen ausschließlich HTTPS.
Es gibt zwar Möglichkeiten, diese Standardeinstellung zu überschreiben, doch die Verwendung eines anderen Protokolls als HTTPS führt bei der Veröffentlichung im App Store zu Problemen mit Ihrem Anbieter. Noch schwerwiegender ist, dass Ihre mobile App dadurch verschiedenen Arten von Datenschutzverletzungen ausgesetzt sein kann.
Sie können das vertrauenswürdige Zertifikat bzw. die vertrauenswürdigen Zertifikate des Remote-Hosts manuell in einer mobilen Anwendung hinterlegen, um Man-in-the-Middle-Angriffe (MITM) zu verhindern und die App-Sicherheit zu erhöhen. Es gibt verschiedene geeignete Open-Source-Bibliotheken für Certificate Pinning in React Native, zum Beispiel react-native-ssl-pinning von MaxToyberman oder react-native-cert-pinner von Approov.
Pinning mit der React-Native-SSL-Pinning-Bibliothek
React Native SSL pinning wandelt Zertifikate in .cer-Dateien um, die Sie als Assets zu Ihrem Mobile-App-Bundle hinzufügen können – genau wie eine Bilddatei oder eine benutzerdefinierte Schriftart.
Das Tool bietet einen Ersatz für fetch, den wir für unsere HTTP-Anfragen verwenden können.
Verwenden Sie zum Pinnen eines Zertifikats diesen Code:
Verwenden Sie zum Pinnen eines öffentlichen Schlüssels diesen Code:
Die Bibliothek verwendet im Hintergrund zwei native Module: AFNetworking für iOS und okhttp3 für Android. Das AFNetworking-Modul verwendet automatisch .cer-Dateien in den Assets. OkHttp3 ordnet die JavaScript-Eigenschaft sslPinning dem Format .cer zu.
Pinning mit react-native-cert-pinner
react-native-cert-pinner ist eine weitere Bibliothek, mit der Sie Zertifikate in Ihrer mobilen App pinnen können. Als Pins dienen entweder der Base64-SHA256-Hash des öffentlichen Schlüssels des Zertifikats oder der Base64-SHA1-Hash des Zertifikats.
Die Bibliothek bietet ein Dienstprogramm namens pinset, das unter iOS eine info.plist-Datei und unter Android eine GeneratedCertificatePinner.java-Datei erstellt. Der native Code verweist anschließend auf diese Datei.
Im Hintergrund verwendet die Bibliothek TrustKit unter iOS und okhttp3 unter Android.
Um mit react-native-cert-pinner Pins einzurichten, erstellen Sie zunächst mit diesem Befehl eine erste Konfiguration:
Legen Sie nach der Initialisierung fest, welche URLs gepinnt werden sollen, und ermitteln Sie den Hash des öffentlichen Schlüssels für jedes Zertifikat.
Tragen Sie anschließend die gewünschten Hashes der öffentlichen Schlüssel Ihrer Domain in die Datei pinset.json ein:
Hinweis: Domains, die mit einem Sternchen (*) beginnen, schließen alle Subdomains ein.
Erstellen Sie nun mit dem folgenden Befehl die Quelldateien des nativen Projekts:
Dabei sollten die folgenden Dateien erstellt werden:
Wir empfehlen, eine Bibliothek zu verwenden, mit der Sie den öffentlichen Schlüssel des Zertifikats pinnen können, denn ein Pin, der anhand eines Zertifikats erstellt wurde, funktioniert nach Ablauf des Zertifikats nicht mehr. Beide in diesem Abschnitt vorgestellten Bibliotheken unterstützen das Pinning öffentlicher Schlüssel.
Generell empfiehlt es sich, Zertifikate nur dann in einer mobilen App zu pinnen, wenn Sie sich der Identität eines Remote-Hosts weitgehend sicher sein möchten.
Authentifizierungsprotokolle
Authentifizierung schafft Vertrauen, indem sie den jeweiligen Nutzer oder das System hinter einer Netzwerkanfrage identifiziert. Anhand dieser Identität kann der Server entscheiden, ob der Nutzer auf eine bestimmte Ressource zugreifen darf.
Die meisten mobilen Apps müssen dem Nutzer personalisierte Daten anzeigen. Denken Sie etwa an ein Facebook-Profil oder eine WhatsApp-Kontaktliste. Das Authentifizierungssystem hilft dem Server, den Nutzer zu identifizieren und ihm in diesen Apps die passenden Daten bereitzustellen.
Eine typische Methode zur Einrichtung der Nutzerauthentifizierung in React Native besteht darin, verschiedene Bildschirmgruppen zu erstellen. Entwickler setzen dies häufig mithilfe einer Router-Bibliothek wie Stack Navigator um.
Eine Gruppe verwaltet die Bildschirme, die nicht authentifizierte Nutzer sehen können. Dazu gehören beispielsweise Bildschirme für die Anmeldung, Registrierung und das Zurücksetzen des Passworts. Über diese Bildschirme authentifiziert die App den Nutzer.
Eine zweite Gruppe ist für authentifizierte Nutzer vorgesehen. Dieser Stack umfasst Dashboard, Einstellungen, Konto, Feed und alle weiteren Bildschirme mit Nutzerinhalten.
Dieser Beispielcode unterteilt die Bildschirme in zwei Gruppen: AppStack für authentifizierte Nutzer und AuthStack für nicht authentifizierte Nutzer:
Erstellen Sie nach dem Anlegen beider Bildschirmgruppen eine Router-Komponente. Sie entscheidet anhand des Authentifizierungsstatus des Nutzers, welcher Stack angezeigt wird.
Verwenden Sie anschließend beide Stacks innerhalb des NavigationContainer. Eine Komponente aus react-navigation umschließt in React Native sämtliche Routennavigationen.
authData steht für die Daten, die der Nutzer auf dem Authentifizierungsbildschirm eingibt – zum Beispiel auf dem Bildschirm SignInScreen. Mit diesem Code wird der Nutzer authentifiziert:
Die Funktion signIn stellt eine Verbindung zur API her und aktualisiert authData entsprechend der Antwort. Dort können Sie Profildaten des Nutzers aus der API speichern. Die Funktion signOut löscht die Daten. In manchen Fällen stellt sie eine Verbindung zur API her, um ein Token ungültig zu machen.
Ein Ladezustand ist erforderlich, da die Authentifizierung asynchron abläuft und Zeit benötigt. Sie können diesen Zustand überwachen, um in der Benutzeroberfläche (UI) Ihrer App eine Ladeanimation anzuzeigen, während der Server die Anfrage verarbeitet.
Stellen Sie abschließend sicher, dass alle Komponenten auf den Context zugreifen können, indem Sie sie in AuthContext.Provider einschließen.
Das OAuth-2.0-Protokoll
Mobile React-Native-Anwendungen verwenden häufig das Authentifizierungsprotokoll OAuth 2.0, um Nutzer zu authentifizieren. OAuth ist aufgrund seiner strengen Sicherheitsvorkehrungen eine beliebte Wahl für Web- und Mobile-Apps.
An einem OAuth-Ablauf sind vier Akteure beteiligt:
Ressourcenbesitzer: Besitzt die Daten auf dem Ressourcenserver. Ein Facebook-Nutzer ist beispielsweise der Ressourcenbesitzer seiner Facebook-Profildaten.
Client-App: Die Anwendung, die auf diese Daten zugreifen möchte (z. B. die mobile Facebook-App).
Ressourcenserver: Die API, die die Daten speichert, auf die die mobile Anwendung zugreifen möchte (z. B. die Facebook-API).
Autorisierungsserver: Die zentrale Instanz von OAuth.
OAuth fordert Nutzer auf, sich über einen Drittanbieter wie Google, Facebook oder GitHub zu authentifizieren. Sobald die Authentifizierung abgeschlossen ist, leitet der Drittanbieter den Nutzer mit einem Bestätigungscode zurück zur Anwendung. Die Anwendung kann diesen Code gegen ein JSON Web Token (JWT) oder eine andere Art von Token eintauschen.
Diese Weiterleitungen sind bei Web-Apps sicher, da URLs im Web garantiert eindeutig sind. Bei mobilen Apps gibt es jedoch keine zentrale Methode zur Registrierung von URL-Schemas.
Um diesem Sicherheitsrisiko zu begegnen, müssen wir eine Prüfung mit PKCE (ausgesprochen „Pixie“) ergänzen, einer Erweiterung der OAuth-2.0-Spezifikation. PKCE verwendet den kryptografischen Hash-Algorithmus SHA 256, um zu überprüfen, ob die Authentifizierungs- und Token-Austauschanfragen vom selben Client stammen.
Dadurch wird sichergestellt, dass nur die Anwendung, die für den Autorisierungsablauf zuständig ist, den Bestätigungscode erfolgreich gegen ein JWT eintauschen kann.
Eine einfache Möglichkeit, OAuth in React Native sicher nativ zu implementieren, ist ein Paket wie react-native-app-auth. Es dient als React-Native-Bridge für die AppAuth-SDKs für iOS und Android, die mit OAuth-2.0- und OpenID-Connect-Anbietern kommunizieren.
Das Paket unterstützt PKCE sowie zahlreiche OpenID- und OAuth-2.0-Anbieter, darunter Google, Okta, GitHub, Coinbase und FusionAuth.
Nach Sicherheitslücken in Abhängigkeiten suchen
Entwickler erstellen mit React Native allein keine vollständig funktionsfähige native Anwendung. Häufig nutzen wir Tools von Drittanbietern, um Probleme zu lösen und unsere Produktivität zu steigern.
Eine Anwendung enthält mehrere Abhängigkeiten von Drittanbietern, die dazu beitragen, sie vollständig und funktionsfähig zu machen. Das Problem: Diese Abhängigkeiten können Sicherheitslücken in unsere Anwendung einführen, selbst wenn unser eigener Code sicher ist.
Es gibt mehrere Möglichkeiten, mit Snyk nach Sicherheitslücken in Open-Source-Paketen zu suchen. Sehen wir uns ein Beispiel mit der beliebten Open-Source-Kunst-App Eigen für React Native an: Eigen.
Eine Möglichkeit ist die Snyk CLI: Installieren Sie das CLI-Tool und registrieren Sie sich für ein kostenloses Snyk-Konto. Sobald Sie registriert und das Tool installiert sind, führen Sie snyk auth aus, um die CLI mit Ihrem Konto zu verbinden.
Klonen Sie das Repository in Ihre Entwicklungsumgebung und führen Sie anschließend im Stammverzeichnis des geklonten Projekts snyk test aus. Dadurch wird das Paketmanifest im Stammverzeichnis gescannt und nach Problemen mit den Paketversionen gesucht.
Praktischer Tipp: Sie können auch snyk monitor ausführen, um über Probleme informiert zu werden, die nach dem ersten Scan im Projekt erkannt werden.

In unserem Beispiel wurden im Paketmanifest der React-Native-App mehrere potenzielle Probleme erkannt. Besonders hilfreich ist hier, dass Sie die erkannten Sicherheitslücken untersuchen und weitere Informationen dazu finden können.
Wie die Liste zeigt, weist Hermes-engine 0.5.1 eine bekannte Sicherheitslücke auf, die Cross-Site-Scripting-Angriffe (XSS) ermöglichen kann. Das lässt sich durch ein Upgrade auf eine Version nach 0.7.2 beheben, in der diese Sicherheitslücke geschlossen wurde.

Eine weitere Möglichkeit, React-Native-Projekte zu scannen, ist der direkte Scan eines Repositorys, indem Sie Ihr Snyk-Konto mit einem Code-Repository Ihrer Wahl verbinden. Der Vorteil: Snyk kann das Projekt fortlaufend auf Probleme überprüfen, auch wenn mehrere Personen daran mitarbeiten, da bei jedem Commit oder Merge ein Scan ausgeführt wird.
Um Ihr Repository zu verbinden, registrieren Sie sich für ein Snyk-Konto. Klicken Sie dann im Snyk-Dashboard auf die Repository-Plattform, auf der Ihr Code gespeichert ist. Wenn Ihre bevorzugte Plattform nicht im Schnellmenü angezeigt wird, klicken Sie auf Other und suchen Sie unter den Plattformintegrationen von Snyk danach.

Folgen Sie den Schritten zum Verbinden. Wählen Sie anschließend auf der Seite zur Repository-Verbindung das Repository aus, das Sie scannen möchten.

Klicken Sie auf die Schaltfläche Add selected repositories und warten Sie, bis der Scan abgeschlossen ist. Besonders praktisch: Sie können die gescannten Elemente und die Ergebnisse anzeigen.

Wie beim Scan mit der Snyk CLI können Sie weitere Details zu den erkannten Sicherheitslücken aufrufen und im Repository automatisch eine Korrektur erstellen lassen.

Sie können Snyk auch integrierenin Ihren bevorzugten Code-Editor, um Ihre Abhängigkeiten während der App-Entwicklung automatisch auf Schwachstellen zu scannen. Die Snyk-Erweiterung für Visual Studio Codeerkennt beispielsweise potenzielle Schwachstellen nicht nur im Paketmanifest, sondern auch an den Stellen im Code, an denen das Paket verwendet wird.
Zusammenfassung
Da mobile Apps Daten immer ausgefeilter nutzen, ist es wichtiger denn je, Nutzerinformationen wirksam zu schützen und Endnutzer abzusichern. Wie Webanwendungen stehen auch React-Native-Apps vor denselben Sicherheitsherausforderungen, etwa bei der sicheren Datenübertragung, Authentifizierungsprotokollen und Schwachstellen in Abhängigkeiten.
Diese Checkliste mit bewährten Sicherheitspraktiken für React hilft Ihnen und Ihrem Team dabei, Sicherheitsprobleme in Ihren React-Anwendungen zu finden und zu beheben.
Starten Sie mit Capture the Flag
Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Herausforderungen lösen.
Kingsley Ubah ist ein erfahrener Full-Stack-Webentwickler und technischer Redakteur.



