So schützen Sie eine REST-API nur für vertrauenswürdige mobile Anwendungen

96

Wie stelle ich sicher, dass meine REST-API nur auf Anforderungen von vertrauenswürdigen Clients reagiert, in meinem Fall auf meine eigenen mobilen Anwendungen? Ich möchte unerwünschte Anfragen aus anderen Quellen verhindern. Ich möchte nicht, dass Benutzer einen Serienschlüssel oder was auch immer ausfüllen. Dies sollte hinter den Kulissen, bei der Installation und ohne Benutzereingriff geschehen.

Meines Wissens dient HTTPS nur dazu, den Server zu überprüfen, mit dem Sie kommunizieren. Ich werde natürlich HTTPS verwenden, um die Daten zu verschlüsseln.

Gibt es eine Möglichkeit, dies zu erreichen?

Update: Der Benutzer kann schreibgeschützte Aktionen ausführen, bei denen der Benutzer nicht angemeldet sein muss. Er kann jedoch auch Schreibaktionen ausführen, bei denen der Benutzer angemeldet sein muss (Authentifizierung durch Zugriffstoken). In beiden Fällen möchte ich, dass die API auf Anfragen reagiert, die nur von vertrauenswürdigen mobilen Anwendungen stammen.

Die API wird auch zum Registrieren eines neuen Kontos über die mobile Anwendung verwendet.

Update 2: Es scheint, als gäbe es mehrere Antworten darauf, aber ich weiß ehrlich gesagt nicht, welche ich als Antwort markieren soll. Einige sagen, es kann getan werden, andere sagen, es kann nicht.

Supercell
quelle
HTTPS verwendet SSL (und TLS). SSL / TLS kann mit der Clientauthentifizierung verwendet werden.
20.
Meinen Sie clientseitige SSL-Zertifikate? Ich denke, das ist, wonach ich suche, außer ich habe keine Ahnung, ob das überhaupt in mobilen Anwendungen (Android und iOS) möglich ist. Wo würde das Client-Zertifikat gespeichert werden? Gerätespeicher, Speicher?
Supercell
Das SSL zertifiziert nur das mobile Gerät, NICHT die mobile Anwendung.
Morons
@Supercell: Ich werde eine Antwort hinzufügen
atk

Antworten:

48

Das kannst du nicht.

Sie können niemals eine Entität oder eine Entität überprüfen , sei es eine Person, ein Hardware-Client oder ein Software-Client. Sie können nur überprüfen, ob das, was sie Ihnen sagen , korrekt ist, und dann von Ehrlichkeit ausgehen .

Woher weiß Google beispielsweise, dass ich mich in meinem Google Mail-Konto anmelde? Sie fragen mich einfach nach einem Benutzernamen und einem Passwort, überprüfen das und gehen dann von Ehrlichkeit aus, denn wer sonst hätte diese Informationen? Irgendwann entschied Google, dass dies nicht ausreicht, und fügte eine Verhaltensüberprüfung hinzu (auf der Suche nach ungewöhnlichem Verhalten), die sich jedoch weiterhin darauf stützt, dass die Person das Verhalten ausführt und anschließend das Verhalten validiert .

Dies ist genau das gleiche wie bei der Validierung des Clients. Sie können nur das Verhalten des Clients überprüfen, nicht jedoch den Client selbst.

Mit SSL können Sie also überprüfen, ob der Client ein gültiges Zertifikat hat oder nicht. Sie können also einfach Ihre App installieren, das Zertifikat erhalten und dann den gesamten neuen Code ausführen.

Die Frage ist also: Warum ist das so kritisch? Wenn dies ein echtes Problem ist, würde ich Ihre Wahl eines fetten Kunden in Frage stellen. Vielleicht sollten Sie eine Web-App verwenden (damit Sie Ihre API nicht offenlegen müssen).

Siehe auch: Deaktivieren der SSL-Zertifikatüberprüfung für Android-Anwendungen

und: Wie sicher sind Client-SSL-Zertifikate in einer mobilen App?

Idioten
quelle
1
Ich habe Client-Zertifikate auf Hardware verwendet, deren Zertifikat auf einem vom Betriebssystem verschlüsselten Laufwerk gespeichert war. Aber selbst dort glaubte niemand, es sei narrensicher. Das Ziel war nur, es Gelegenheitsbenutzern schwer zu machen.
Steven Burnap
1
@ Morons: Eine Web-App würde dies lösen, aber wir glauben, dass Benutzer die native App mit größerer Wahrscheinlichkeit verwenden als eine Web-App (bitte korrigieren Sie mich, wenn unsere Annahme falsch ist). Der Grund, warum dies so kritisch ist, liegt darin, dass die API dem Benutzer Zugriff auf Teile unserer Datenbank gewährt, die viele Daten enthält, die wir in monatelanger Arbeit gesammelt haben. Es sind Daten, die andere Unternehmen oder Benutzer leicht für ihre eigenen Zwecke verwenden könnten. Ohne die Kunden zu sichern, würden wir nicht wissen, wer es benutzt (gegen uns).
Supercell
6
Eine Webapp löst das Problem nicht. Es ist ziemlich trivial, jeden Webapp-Client so zu modifizieren, dass er tut, was immer Sie wollen.
Steven Burnap
5
@Supercell Sie können niemandem Daten anzeigen und ihn daran hindern, sie weiterzugeben. Wenn Sie nicht möchten, dass einige Daten haben, geben Sie sie ihnen nicht (zeigen Sie sie).
Morons
Ich bin damit einverstanden, aber aus einem anderen Grund. Sie können das, wenn Sie die Kontrolle über die Geräte haben, wie bei en.wikipedia.org/wiki/SecurID . Handys können jedoch nicht gesteuert werden (sie können Anhänge wie einen Plug-in-Schlüssel oder ähnliches akzeptieren).
imel96
31

Ich bin mir sicher, dass Sie mit dem Umgang mit Benutzeranmeldungen und der Kommunikation über SSL vertraut sind. Daher werde ich mich auf den meiner Meinung nach interessanteren Teil der Frage konzentrieren: Wie stellen Sie sicher, dass Ihre schreibgeschützten Aktionen - die Sie nicht benötigen die Benutzer authentifiziert werden - werden nur von Ihren eigenen Client - Anwendungen akzeptiert?

Vor allem gibt es den Nachteil, auf den fNek in einer früheren Antwort hingewiesen hat: Ihre Client-Apps befinden sich in den Händen potenziell feindlicher Benutzer. Sie können untersucht, ihre Kommunikation überprüft und ihr Code zerlegt werden. Mit keinem meiner Vorschläge können Sie garantieren, dass jemand Ihren Client nicht zurückentwickelt und Ihre REST-API missbraucht. Aber es sollte eine Barriere vor zufälligen Versuchen setzen.

Wie auch immer, ein gängiger Ansatz ist:

  • Der Client enthält ein Geheimnis
  • Beim Erstellen einer Anforderung werden die Anforderungsparameter mit den Geheimnissen verknüpft und das Ergebnis gehasht
  • Dieser Hash wird mit der Anfrage gesendet und vom Server überprüft

Stellen Sie sich zB eine GETAnfrage für vor/products/widgets

Angenommen, das Client-Geheimnis lautet "OH_HAI_I_IZ_SECRET".

Verketten Sie das HTTP-Verb, die URL und das Geheimnis:

GET/products/widgetsOH_HAI_I_IZ_SECRET

Und nimm einen SHA-1- Hash davon:

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Dann sende das mit, so wäre die Anfrage für:

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Um zu verhindern, dass jemand einzelne Anforderungen zumindest wiederholt, nehmen Sie auch einen Zeitstempel und fügen Sie diesen den Parametern und dem Hash hinzu. ZB ist momentan in der Unix-Zeit 1384987891. Fügen Sie dies zur Verkettung hinzu:

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

Hasch das:

2774561d4e9eb37994d6d71e4f396b85af6cacd1

Und senden:

GET /products/widgets?time=1384987891&hash=2774561d4e9eb37994d6d71e4f396b85af6cacd1

Der Server überprüft den Hash und stellt auch sicher, dass der Zeitstempel aktuell ist (z. B. innerhalb von 5 Minuten, um zu gewährleisten, dass die Uhren nicht perfekt synchron sind).

Warnung! Da es sich um mobile Apps handelt, besteht definitiv das Risiko, dass auf dem Telefon eines anderen eine falsche Uhrzeit angezeigt wird. Oder Zeitzone falsch. Oder so. Das Hinzufügen der Zeit zum Hash wird wahrscheinlich einige legitime Benutzer zum Scheitern bringen. Verwenden Sie diese Idee daher mit Vorsicht.

Carson63000
quelle
6
Dieser Hash-Mechanismus kann von jedem Programmierer verstanden werden, wenn er die apk zerlegt.
Punith Raj
8
@PunithRaj genau, ich habe das im zweiten Absatz behandelt. "Nichts, was ich vorschlagen werde, wird es Ihnen ermöglichen, zu garantieren, dass jemand Ihren Client nicht zurückentwickelt und Ihre REST-API missbraucht. Aber es sollte eine Barriere gegen gelegentliche Versuche darstellen."
Carson63000
für die Warnung, verwende ich UTC auf Server und Handy, das löst das Problem, oder?
Shareef
@ Carson63000 - gibt es also eine konkrete Lösung? Dies gilt insbesondere für die Benutzerregistrierungs-API, die öffentlich zugänglich sein muss (ein Benutzer muss sich registrieren, bevor er sich im Web oder in einer mobilen App anmelden kann) und auf die Bots abzielen können, um Tausende von gefälschten Benutzern zu erstellen.
Tohid
17

Für alle Interessierten können Sie unter Android überprüfen, ob die von Ihnen erhaltene Anfrage von Ihrer App gesendet wurde.

Kurz gesagt, wenn Sie Ihre App auf Google hochladen, signieren Sie sie mit einem eindeutigen Schlüssel, der nur Ihnen (und Google) bekannt ist.

Der Verifizierungsprozess läuft wie folgt ab:

  1. Ihre App geht zu Google und fragt nach dem Authentifizierungstoken
  2. Ihre App sendet das Token sicher an Ihr Back-End
    1. Ihr Back-End geht zu Google und überprüft das Authentifizierungs-Token, das es von Ihrer App erhalten hat.
    2. Ihr Back-End prüft dann, ob der eindeutige Schlüssel, den Ihre App signiert hat, mit dem übereinstimmt. Wenn nicht, bedeutet dies, dass dies nicht Ihre App war ...

Das vollständige Blog, in dem es erklärt und wie es implementiert wird, finden Sie hier: http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html

ndori
quelle
1
Gute Antwort, jedoch kann ein böswilliger Benutzer eine App immer noch mit genügend Aufwand fälschen. aber nichts ist wirklich sicher, es ist keine Frage von ob, nur eine Frage von wann
Mateos
1
Für iOS gibt es diese Option: link Mit den DeviceCheck-APIs können Sie auch überprüfen, ob das erhaltene Token von einem authentischen Apple-Gerät stammt, auf das Ihre App heruntergeladen wurde
Iwaz,
Es erfordert Konten (E-Mails)
user25
5

Ok, es ist also erwähnenswert, bevor ich anfange, dass dies für die meisten Anwendungen ein enormer Übermaß ist. In den meisten Fällen ist es mehr als ausreichend, nur ein einziges gültiges Zertifikat und / oder Token zu haben. Wenn es darum geht, Ihre App zu dekompilieren, werden sich selbst die meisten Hacker nicht darum kümmern, es sei denn, Sie geben einige sehr wertvolle Daten an. Aber was macht die Antwort für einen Spaß?

Sie können also eine asymmetrische Kryptographie einrichten, ähnlich wie digitale Signaturen, die zum Signieren von Programmen verwendet werden. Jede App kann dann über ein einzelnes Zertifikat verfügen, das von einer einzelnen Zertifizierungsstelle ausgestellt und überprüft wird, wenn Ihr Benutzer eine Verbindung herstellt. (entweder bei der erstmaligen Registrierung oder bei der Erstinstallation) Wenn dieses Zertifikat authentifiziert ist, können Sie Ihre Anwendung weiter sichern, indem Sie dieses Zertifikat als gültig für eine bestimmte Gerätekennung (z. B. Android-ID ) registrieren.

Tom Squires
quelle
5

Wie @ Morons in seiner Antwort erwähnt hat, ist es sehr schwierig, die Entität am anderen Ende der Verbindung zu überprüfen.

Der einfachste Weg, ein gewisses Maß an Authentizität bereitzustellen, besteht darin, den Server ein Geheimnis überprüfen zu lassen, das nur die reale Entität kennen würde. Für einen Benutzer kann dies ein Benutzername und ein Kennwort sein. Für eine Software, für die es keinen Benutzer gibt, können Sie ein Geheimnis einbetten.

Das Problem bei diesen Ansätzen ist, dass Sie dem Kunden etwas Vertrauen schenken müssen. Wenn jemand Ihre App zurückentwickelt oder Ihr Passwort stiehlt, kann er sich als Sie ausgeben.

Sie können Schritte unternehmen, um das Extrahieren der geheimen Informationen zu erschweren, indem Sie sie in der ausführbaren Datei verschleiern. Tools wie ProGuard, ein Obfuscator für Java, können dabei helfen. Ich weiß nicht so viel über die Verschleierung in anderen Sprachen, aber es gibt wahrscheinlich ähnliche Tools. Durch die Verwendung einer TLS-Verbindung können Sie verhindern, dass Personen Ihren Datenverkehr ausspähen, jedoch keinen MITM-Angriff. Das Fixieren kann dabei helfen, dieses Problem zu beheben .

Ich arbeite für ein Unternehmen namens CriticalBlue (Full Disclosure!) Mit einem Produkt namens Approov , das versucht, dieses Vertrauensproblem anzugehen. Es funktioniert derzeit für Android / iOS und bietet unseren Servern einen Mechanismus, um die Integrität der Client-App zu überprüfen. Dies geschieht, indem der Client eine Antwort auf eine zufällige Herausforderung berechnet. Der Client muss die Antwort unter Verwendung von schwer zu fälschenden Attributen des installierten App-Pakets berechnen und enthält einige ausgefeilte Manipulationsschutzmechanismen.

Es wird ein Token zurückgegeben, das Sie als Echtheitsnachweis an Ihre API senden können.

Der wichtige Unterschied bei diesem Ansatz besteht darin, dass die Authentizitätsprüfung auf dem Client zwar deaktiviert werden kann, Sie jedoch nicht das Authentifizierungstoken erhalten, das Sie zur Überprüfung Ihrer App beim Server benötigen. Die Bibliothek ist außerdem eng an die Eigenschaften der ausführbaren Datei gekoppelt, in der sie sich befindet. Daher wäre es sehr schwierig, sie in eine gefälschte App einzubetten und funktionsfähig zu machen.

Es gibt eine Kosten-Nutzen-Analyse, die jeder API-Entwickler durchführen muss, um zu entscheiden, wie wahrscheinlich es ist, dass jemand versucht, seine API zu hacken, und wie teuer dies sein könnte. Eine einfache geheime Prüfung in der Anwendung verhindert triviale Angriffe, aber sich gegen einen entschlosseneren Angreifer zu schützen, ist wahrscheinlich erheblich komplizierter und möglicherweise kostspieliger.

DerPragmatiker
quelle
0

SSL sichert den Kommunikationskanal.

Bei erfolgreicher Anmeldung wird ein Authentifizierungstoken über eine verschlüsselte Verbindung ausgegeben.

Das Authentifizierungstoken wird bei allen nachfolgenden Anforderungen an Ihre REST-API übergeben.

CodeART
quelle
1
Ich habe einige zusätzliche Informationen hinzugefügt. Ich hatte vor, die von Ihnen erwähnte Authentifizierung mit einem Zugriffstoken durchzuführen. Für die REST-API muss der Benutzer nur für bestimmte Aktionen angemeldet sein. In beiden Fällen müssen die Clients signiert / vertrauenswürdig sein.
Supercell
Ich weiß nicht viel über native mobile Entwicklung, aber kann Ihre mobile Anwendung der REST-API die Mobiltelefonnummer bereitstellen? Wenn ich Apps auf meinem Android-Handy installiere, werde ich oft gebeten, der App bestimmte Berechtigungen zu erteilen. Wenn Sie bei jeder Anfrage eine Handynummer über eine sichere Verbindung senden können, können Sie alle Anfragen mit unbekannter Handynummer ablehnen.
Ich
Das könnte funktionieren, aber es würde erfordern, dass der Benutzer angemeldet ist und die Nummer an das Benutzerkonto gebunden ist. Andernfalls hätte der Server keine Möglichkeit, die Nummer zu überprüfen.
Supercell
Wie werden Sie Ihre mobile Anwendung installieren?
CodeART
Sie werden in den App Stores (Google, Apple, Microsoft) erhältlich sein
Supercell
0

Es wäre nicht zu sicher, aber Sie könnten eine Art Geheimcode oder sogar eine digitale Signatur hinzufügen. Nachteil: Es muss in der App enthalten sein, was es einfach macht, es zu erhalten, wenn Sie wissen, was Sie tun.

fNek
quelle
0

Meines Wissens dient HTTPS nur dazu, den Server zu überprüfen, mit dem Sie kommunizieren.

Tatsächlich können Sie SSL verwenden, um sowohl den Client als auch den Server zu authentifizieren. Oder anders ausgedrückt: "Ja, Sie können Client-Zertifikate verwenden".

Sie müssen ...

  • Sehen Sie sich die von Ihnen verwendete SSL-Bibliothek an, um zu bestimmen, wie Client-Zertifikate auf dem mobilen Gerät angegeben werden sollen.
  • Schreiben Sie Code oder konfigurieren Sie Ihren HTTPS-Server so, dass er nur Verbindungen von vertrauenswürdigen, registrierten Clients akzeptiert.
  • Überlegen Sie, wie Sie Ihrem Server vertrauenswürdige Client-Zertifikate hinzufügen können
  • Überlegen Sie, wie Sie nicht mehr vertrauenswürdige Client-Zertifikate von Ihrem Server entfernen können

Sie können die mobile Anwendung das Zertifikat speichern lassen, wo immer Sie möchten. Da Sie eine anwendungsspezifische Authentifizierung wünschen, sollten Sie erwägen, das Zertifikat an einem geschützten Speicherort auf der Festplatte zu speichern (unter Android können Sie eine "config" -Tabelle in Ihrer SQLite-Datenbank und eine Zeile für Ihr Zertifikat und eine andere für Ihren privaten Schlüssel erstellen). .

atk
quelle