Ich habe über REST gelesen und es gibt viele Fragen zu SO darüber sowie zu vielen anderen Websites und Blogs. Obwohl ich diese spezielle Frage noch nie gestellt habe ... aus irgendeinem Grund kann ich mich nicht um dieses Konzept kümmern ...
Wenn ich eine RESTful-API erstelle und sie sichern möchte, ist eine der Methoden, die ich gesehen habe, die Verwendung eines Sicherheitstokens. Wenn ich andere APIs verwendet habe, gab es ein Token und ein gemeinsames Geheimnis ... macht Sinn. Was ich nicht verstehe ist, dass Anfragen an einen Rest-Service-Vorgang über Javascript (XHR / Ajax) gestellt werden, um zu verhindern, dass jemand dies mit etwas Einfachem wie FireBug (oder "Quelltext anzeigen" im Browser) und Kopieren Sie den API-Schlüssel und geben Sie sich dann mit dem Schlüssel und dem Geheimnis als diese Person aus?
quelle
Antworten:
Das API-Geheimnis wird nicht explizit übergeben. Das Geheimnis wird verwendet, um ein Zeichen der aktuellen Anforderung zu generieren. Auf der Serverseite generiert der Server das Zeichen nach demselben Vorgang. Wenn die beiden Zeichen übereinstimmen, wird die Anforderung erfolgreich authentifiziert - also nur das Zeichen wird durch die Anfrage geleitet, nicht das Geheimnis.
quelle
Wir stellen eine API zur Verfügung, die Partner nur für Domains verwenden können, die sie bei uns registriert haben. Der Inhalt ist teilweise öffentlich (wird aber vorzugsweise nur in den uns bekannten Domains angezeigt), ist jedoch für unsere Benutzer größtenteils privat. So:
Um festzustellen, was angezeigt wird, muss unser Benutzer bei uns angemeldet sein, dies wird jedoch separat behandelt.
Um festzustellen, wo die Daten angezeigt werden, wird ein öffentlicher API-Schlüssel verwendet, um den Zugriff auf uns bekannte Domänen zu beschränken und vor allem um sicherzustellen, dass die privaten Benutzerdaten nicht für CSRF anfällig sind .
Dieser API-Schlüssel ist in der Tat für jeden sichtbar, wir authentifizieren unseren Partner nicht auf andere Weise und benötigen keinen REFERER . Trotzdem ist es sicher:
Wenn unsere
get-csrf-token.js?apiKey=abc123
angefordert wird:Suchen Sie den Schlüssel
abc123
in der Datenbank und erhalten Sie eine Liste der gültigen Domänen für diesen Schlüssel.Suchen Sie nach dem CSRF-Validierungscookie. Wenn es nicht vorhanden ist, generieren Sie einen sicheren Zufallswert und fügen Sie ihn in ein Nur-HTTP- Sitzungscookie ein. Wenn das Cookie vorhanden war, rufen Sie den vorhandenen Zufallswert ab.
Erstellen Sie ein CSRF-Token aus dem API-Schlüssel und dem Zufallswert aus dem Cookie und signieren Sie es . (Anstatt eine Liste der Token auf dem Server zu führen, signieren wir die Werte. Beide Werte sind im signierten Token lesbar, das ist in Ordnung.)
Stellen Sie die Antwort so ein, dass sie nicht zwischengespeichert wird, fügen Sie das Cookie hinzu und geben Sie ein Skript wie folgt zurück:
Anmerkungen:
Dies verhindert nicht, dass ein serverseitiges Skript eine Anforderung vortäuscht, sondern stellt nur sicher, dass die Domäne übereinstimmt, wenn dies von einem Browser angefordert wird.
Die Same Origin Policy für JavaScript sorgt dafür , dass ein Browser nicht XHR (Ajax) verwenden können , laden und dann die JavaScript - Quelle zu überprüfen. Stattdessen kann ein normaler Browser ihn nur mit
<script src="https://our-api.com/get-csrf-token.js?apiKey=abc123">
(oder einem dynamischen Äquivalent) laden und führt dann den Code aus. Natürlich sollte der Server nicht unterstützt Cross-Origin Resource Sharing noch JSONP für den generierten JavaScript.Ein Browserskript kann den Wert von ändern,
document.domain
bevor das obige Skript geladen wird. Dieselbe Ursprungsrichtlinie ermöglicht jedoch nur die Verkürzung der Domäne durch Entfernen von Präfixen, z. B. das Umschreibensubdomain.example.com
auf nurexample.com
odermyblog.wordpress.com
aufwordpress.com
oder in einigen Browsern sogarbbc.co.uk
aufco.uk
.Wenn die JavaScript-Datei mit einem serverseitigen Skript abgerufen wird, erhält der Server auch das Cookie. Ein Server eines Drittanbieters kann den Browser eines Benutzers jedoch nicht dazu bringen, dieses Cookie unserer Domain zuzuordnen. Daher kann ein CSRF-Token und ein Validierungscookie, die mit einem serverseitigen Skript abgerufen wurden, nur von nachfolgenden serverseitigen Aufrufen verwendet werden, nicht in einem Browser. Solche serverseitigen Aufrufe enthalten jedoch niemals das Benutzer-Cookie und können daher nur öffentliche Daten abrufen. Dies sind die gleichen Daten, die ein serverseitiges Skript direkt von der Website des Partners entfernen könnte.
Wenn sich ein Benutzer anmeldet, setzen Sie ein Benutzer-Cookie nach Ihren Wünschen. (Der Benutzer hat sich möglicherweise bereits angemeldet, bevor das JavaScript angefordert wurde.)
Alle nachfolgenden API-Anforderungen an den Server (einschließlich GET- und JSONP-Anforderungen) müssen das CSRF-Token, das CSRF-Validierungscookie und (falls angemeldet) das Benutzercookie enthalten. Der Server kann nun bestimmen, ob der Anforderung vertraut werden soll:
Das Vorhandensein eines gültigen CSRF-Tokens stellt sicher, dass das JavaScript aus der erwarteten Domäne geladen wurde , wenn es von einem Browser geladen wurde.
Das Vorhandensein des CSRF-Tokens ohne das Validierungscookie weist auf eine Fälschung hin.
Das Vorhandensein sowohl des CSRF-Tokens als auch des CSRF-Validierungscookies stellt nichts sicher: Dies kann entweder eine gefälschte serverseitige Anforderung oder eine gültige Anforderung von einem Browser sein. (Es kann sich nicht um eine Anfrage eines Browsers handeln, die von einer nicht unterstützten Domain stammt.)
Das Vorhandensein des Benutzercookies stellt sicher, dass der Benutzer angemeldet ist, stellt jedoch nicht sicher, dass der Benutzer Mitglied des angegebenen Partners ist oder dass der Benutzer die richtige Website anzeigt.
Das Vorhandensein des Benutzercookies ohne das CSRF-Validierungscookie weist auf eine Fälschung hin.
Das Vorhandensein des Benutzer-Cookies stellt sicher, dass die aktuelle Anforderung über einen Browser erfolgt. (Angenommen, ein Benutzer würde seine Anmeldeinformationen nicht auf einer unbekannten Website eingeben, und vorausgesetzt, es ist uns egal, ob Benutzer ihre eigenen Anmeldeinformationen verwenden, um eine serverseitige Anfrage zu stellen.) Wenn wir auch das CSRF-Validierungscookie haben, war dies das CSRF-Validierungscookie auch über einen Browser empfangen. Als nächstes, wenn wir auch ein CSRF-Token mit einer gültigen Signatur haben, undDie Zufallszahl im CSRF-Validierungscookie stimmt mit der in diesem CSRF-Token überein. Das JavaScript für dieses Token wurde dann auch während derselben früheren Anforderung empfangen, bei der das CSRF-Cookie gesetzt wurde, und verwendet daher auch einen Browser. Dies impliziert dann auch, dass der obige JavaScript-Code ausgeführt wurde, bevor das Token gesetzt wurde, und dass zu diesem Zeitpunkt die Domäne für den angegebenen API-Schlüssel gültig war.
Also: Der Server kann jetzt den API-Schlüssel vom signierten Token sicher verwenden.
Wenn der Server der Anforderung zu irgendeinem Zeitpunkt nicht vertraut, wird ein 403 Forbidden zurückgegeben. Das Widget kann darauf reagieren, indem es dem Benutzer eine Warnung anzeigt.
Es ist nicht erforderlich, das CSRF-Validierungscookie zu signieren, da wir es mit dem signierten CSRF-Token vergleichen. Wenn Sie das Cookie nicht signieren, wird jede HTTP-Anforderung kürzer und die Serverüberprüfung etwas schneller.
Das generierte CSRF-Token ist unbegrenzt gültig, jedoch nur in Kombination mit dem Validierungscookie, also effektiv, bis der Browser geschlossen wird.
Wir könnten die Lebensdauer der Signatur des Tokens begrenzen. Wir könnten das CSRF-Validierungscookie löschen, wenn sich der Benutzer abmeldet, um die OWASP-Empfehlung zu erfüllen . Und um die Zufallszahl pro Benutzer nicht zwischen mehreren Partnern zu teilen, könnte man den API-Schlüssel zum Cookie-Namen hinzufügen. Aber selbst dann kann man das CSRF-Validierungscookie nicht einfach aktualisieren, wenn ein neues Token angefordert wird, da Benutzer möglicherweise dieselbe Site in mehreren Fenstern durchsuchen und ein einzelnes Cookie freigeben (das beim Aktualisieren in allen Fenstern aktualisiert wird, wonach das Das JavaScript-Token in den anderen Fenstern würde nicht mehr mit diesem einzelnen Cookie übereinstimmen.
Für diejenigen, die OAuth verwenden, siehe auch OAuth und clientseitige Widgets , von denen ich die JavaScript-Idee erhalten habe. Für die serverseitige Verwendung der API, bei der wir uns nicht auf den JavaScript-Code verlassen können, um die Domäne einzuschränken, verwenden wir geheime Schlüssel anstelle der öffentlichen API-Schlüssel.
quelle
OPTIONS
der Server einem Browser möglicherweise mit, welche Domänen zulässig sind (oder bricht die Anforderung ab) , wenn eine vorab geflogene Anforderung mit einem öffentlichen API-Schlüssel in der URL verarbeitet wird. Beachten Sie jedoch, dass für einige Anfragen keine vorab geflogene Anfrage erforderlich ist oder CORS überhaupt nicht verwendet wird und dass CORS IE8 + benötigt. Wenn für IE7 ein Flash-Fallback verwendet wird, kann möglicherweise eine gewisse Dynamikcrossdomain.xml
dazu beitragen, dasselbe zu erreichen. Wir haben CORS / Flash noch nicht ausprobiert.Diese Frage hat eine akzeptierte Antwort, aber nur um zu verdeutlichen, funktioniert die gemeinsame geheime Authentifizierung folgendermaßen:
quelle
Ich nehme an, Sie meinen Sitzungsschlüssel, nicht API-Schlüssel. Dieses Problem wird vom http-Protokoll geerbt und als Sitzungsentführung bezeichnet . Die normale "Problemumgehung" besteht, wie auf jeder Website, darin, zu https zu wechseln.
Um den REST-Service sicher auszuführen, müssen Sie https und wahrscheinlich die Clientauthentifizierung aktivieren. Dies geht jedoch über die REST-Idee hinaus. REST spricht nie über Sicherheit.
quelle
Auf der Serverseite möchten Sie eine ablaufende Sitzungs-ID generieren, die beim Anmelden oder Anmelden an den Client zurückgesendet wird. Der Client kann diese Sitzungs-ID dann als gemeinsames Geheimnis verwenden, um nachfolgende Anforderungen zu signieren.
Die Sitzungs-ID wird nur einmal übergeben und MUSS über SSL erfolgen.
Siehe Beispiel hier
Verwenden Sie beim Signieren der Anforderung eine Nonce und einen Zeitstempel, um die Entführung von Sitzungen zu verhindern.
quelle
Ich werde versuchen, die Frage im ursprünglichen Kontext zu beantworten. Die Frage lautet also: "Ist der geheime (API) Schlüssel sicher, in JavaScript platziert zu werden?"
Meiner Meinung nach ist es sehr unsicher, da es den Zweck der Authentifizierung zwischen den Systemen zunichte macht. Da der Schlüssel dem Benutzer zugänglich gemacht wird, kann der Benutzer Informationen abrufen, zu denen er nicht berechtigt ist. Denn in einer typischen Ruhephase basiert die Kommunikationsauthentifizierung nur auf dem API-Schlüssel.
Eine Lösung ist meiner Meinung nach, dass der JavaScript-Aufruf die Anforderung im Wesentlichen an eine interne Serverkomponente weiterleitet, die für einen Restaufruf verantwortlich ist. Angenommen, ein Servlet liest den API-Schlüssel aus einer gesicherten Quelle wie einem berechtigungsbasierten Dateisystem, fügt ihn in den HTTP-Header ein und führt den externen Restaufruf durch.
Ich hoffe das hilft.
quelle