Wie funktionieren HttpOnly-Cookies mit AJAX-Anfragen?

195

JavaScript benötigt Zugriff auf Cookies, wenn AJAX auf einer Website mit Zugriffsbeschränkungen basierend auf Cookies verwendet wird. Funktionieren HttpOnly-Cookies auf einer AJAX-Site?

Bearbeiten: Microsoft hat eine Möglichkeit geschaffen, XSS-Angriffe zu verhindern, indem der JavaScript-Zugriff auf Cookies nicht zugelassen wird, wenn HttpOnly angegeben ist. FireFox hat dies später übernommen. Meine Frage lautet also: Wenn Sie AJAX auf einer Site wie StackOverflow verwenden, sind nur HTTP-Cookies eine Option?

Bearbeiten 2: Frage 2. Wenn der Zweck von HttpOnly darin besteht, den JavaScript-Zugriff auf Cookies zu verhindern, und Sie die Cookies weiterhin über JavaScript über das XmlHttpRequest-Objekt abrufen können, wozu dient HttpOnly ?

Edit 3: Hier ist ein Zitat aus Wikipedia:

Wenn der Browser ein solches Cookie empfängt, soll er es wie gewohnt in den folgenden HTTP-Austauschen verwenden, es jedoch nicht für clientseitige Skripte sichtbar machen. [32] Das HttpOnlyFlag ist nicht Teil eines Standards und nicht in allen Browsern implementiert. Beachten Sie, dass das Lesen oder Schreiben des Sitzungscookies über eine XMLHTTPRequest derzeit nicht verhindert wird. [33].

Ich verstehe, dass dies document.cookieblockiert ist, wenn Sie HttpOnly verwenden. Es scheint jedoch, dass Sie weiterhin Cookie-Werte im XMLHttpRequest-Objekt lesen können, wobei XSS berücksichtigt wird. Wie macht HttpOnly Sie sicherer als? Indem Cookies im Wesentlichen schreibgeschützt sind?

In Ihrem Beispiel kann ich nicht an Ihre schreiben document.cookie, aber ich kann Ihr Cookie trotzdem stehlen und es mithilfe des XMLHttpRequest-Objekts in meiner Domain veröffentlichen.

<script type="text/javascript">
    var req = null;
    try { req = new XMLHttpRequest(); } catch(e) {}
    if (!req) try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {}
    if (!req) try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
    req.open('GET', 'http://stackoverflow.com/', false);
    req.send(null);
    alert(req.getAllResponseHeaders());
</script>

Bearbeiten 4: Entschuldigung, ich meinte, Sie könnten die XMLHttpRequest an die StackOverflow-Domäne senden und dann das Ergebnis von getAllResponseHeaders () in einer Zeichenfolge speichern, das Cookie neu ausdrücken und dann an eine externe Domäne senden. Es scheint, dass Wikipedia und ha.ckers mir in diesem Punkt zustimmen, aber ich würde gerne umerzogen werden ...

Letzte Änderung: Ahh, anscheinend sind beide Seiten falsch, dies ist tatsächlich ein Fehler in FireFox . IE6 & 7 sind derzeit die einzigen Browser, die HttpOnly vollständig unterstützen.

Um alles zu wiederholen, was ich gelernt habe:

  • HttpOnly beschränkt den Zugriff auf document.cookie in IE7 & und FireFox (bei anderen Browsern nicht sicher).
  • HttpOnly entfernt Cookie-Informationen aus den Antwortheadern in XMLHttpObject.getAllResponseHeaders () in IE7.
  • XMLHttpObjects dürfen nur an die Domain gesendet werden, von der sie stammen, sodass die Cookies nicht domänenübergreifend veröffentlicht werden.

Bearbeiten: Diese Informationen sind wahrscheinlich nicht mehr aktuell.

Shawn
quelle
Ich habe Ihr Beispiel in ein Greasemonkey-Skript geworfen und es sieht so aus, als würde FF keine Cookies mehr anzeigen. Hervorragende Forschung und Beispiel.
Möglicherweise können Sie mit der Richtlinie für denselben Ursprung keine http-Anforderung an eine Domäne senden, die nicht mit der Domäne übereinstimmt, in der das Skript ausgeführt wird. Ich glaube jedoch, dass Sie die Cookies leicht weitergeben können, indem Sie den Benutzer mithilfe von window.location auf eine Seite umleiten und alle Informationen über Abfragezeichenfolgenparameter weitergeben.
Luca Marzi
@LucaMarzi " Sie können keine http-Anfrage an eine Domain stellen, die nicht mit der Domäne übereinstimmt , in der das Skript ausgeführt wird. " Wollen Sie damit sagen, dass eine Site X kein Bild von Host Y enthalten kann? (Eine Funktion, die seit Mosaic von allen Browsern unterstützt wird?)
neugieriger Kerl

Antworten:

64

Ja, nur HTTP-Cookies sind für diese Funktionalität in Ordnung. Sie erhalten weiterhin die Anforderung von XmlHttpRequest an den Server.

Im Falle eines Stapelüberlaufs werden die Cookies automatisch als Teil der XmlHttpRequest-Anforderung bereitgestellt. Ich kenne die Implementierungsdetails des Stack Overflow-Authentifizierungsanbieters nicht, aber diese Cookie-Daten werden wahrscheinlich automatisch verwendet, um Ihre Identität auf einer niedrigeren Ebene als der "Vote" -Controllermethode zu überprüfen.

Im Allgemeinen sind für AJAX keine Cookies erforderlich. Die Unterstützung von XmlHttpRequest (oder sogar Iframe-Remoting in älteren Browsern) ist alles, was technisch erforderlich ist.

Wenn Sie jedoch Sicherheit für AJAX-fähige Funktionen bieten möchten, gelten dieselben Regeln wie bei herkömmlichen Websites. Sie benötigen eine Methode, um den Benutzer hinter jeder Anfrage zu identifizieren, und Cookies sind fast immer das Mittel zu diesem Zweck.

In Ihrem Beispiel kann ich nicht in Ihre document.cookie schreiben, aber ich kann Ihr Cookie trotzdem stehlen und es mithilfe des XMLHttpRequest-Objekts in meiner Domain veröffentlichen.

XmlHttpRequest stellt keine domänenübergreifenden Anforderungen (aus genau den Gründen, die Sie ansprechen).

Normalerweise können Sie ein Skript einfügen, um das Cookie mithilfe von Iframe-Remoting oder JSONP an Ihre Domain zu senden. Dann schützt HTTP-Only das Cookie erneut, da auf es nicht zugegriffen werden kann.

Wenn Sie StackOverflow.com nicht auf der Serverseite kompromittiert hätten, könnten Sie meinen Cookie nicht stehlen.

Bearbeiten 2: Frage 2. Wenn der Zweck von Http-Only darin besteht, den JavaScript-Zugriff auf Cookies zu verhindern, und Sie die Cookies weiterhin über JavaScript über das XmlHttpRequest-Objekt abrufen können, wozu dient Http-Only?

Stellen Sie sich dieses Szenario vor:

  • Ich finde eine Möglichkeit, JavaScript-Code in die Seite einzufügen.
  • Jeff lädt die Seite und mein bösartiges JavaScript ändert sein Cookie so, dass es meinem entspricht.
  • Jeff gibt eine hervorragende Antwort auf Ihre Frage.
  • Da er es mit meinen Cookie-Daten anstelle seiner sendet, wird die Antwort meine.
  • Sie stimmen "meine" herausragende Antwort ab.
  • Mein echtes Konto bekommt den Punkt.

Mit Nur-HTTP-Cookies wäre der zweite Schritt unmöglich, wodurch mein XSS-Versuch zunichte gemacht würde.

Bearbeiten 4: Entschuldigung, ich meinte, Sie könnten die XMLHttpRequest an die StackOverflow-Domäne senden und dann das Ergebnis von getAllResponseHeaders () in einer Zeichenfolge speichern, das Cookie neu ausdrücken und dann an eine externe Domäne senden. Es scheint, dass Wikipedia und ha.ckers mir in diesem Punkt zustimmen, aber ich würde gerne umerzogen werden ...

Das ist richtig. Auf diese Weise können Sie weiterhin Sitzungen entführen. Die Herde der Leute, die selbst diesen XSS-Hack gegen Sie erfolgreich ausführen können, wird dadurch erheblich dünner.

Wenn Sie jedoch zurück zu meinem Beispiel - Szenario gehen, können Sie sehen , wo HTTP-Only nicht erfolgreich von den XSS - Angriffe geschnitten , die die Client-Cookies verlassen (nicht selten) auf ändern.

Es läuft darauf hinaus, dass a) keine einzige Verbesserung alle Schwachstellen beheben wird und b) kein System jemals vollständig sicher sein wird. Nur HTTP ist ein nützliches Tool zur Sicherung gegen XSS.

Auch wenn die domänenübergreifende Einschränkung für XmlHttpRequest nicht zu 100% erfolgreich alle XSS-Exploits verhindert, würden Sie nie davon träumen, die Einschränkung aufzuheben.

Dave Ward
quelle
Viele Frameworks setzen csrf Token in Cookies . Ich nehme an, dass ein AJAX-Aufruf, der csrfüberprüft werden muss, nur funktioniert, wenn Sie das csrf-Token in ein verstecktes HTML-Element einfügen, damit der JS es abrufen kann.
Benutzer
4

Nicht unbedingt, es kommt darauf an, was Sie tun möchten. Könnten Sie etwas näher darauf eingehen? AJAX benötigt keinen Zugriff auf Cookies, um zu funktionieren. Es kann selbst Anforderungen zum Extrahieren von Informationen stellen. Die Seitenanforderung, die der AJAX-Aufruf ausführt, kann auf die Cookie-Daten zugreifen und diese an das aufrufende Skript zurückgeben, ohne dass Javascript direkt auf das zugreifen muss Kekse

Glenn Slaven
quelle
4

Ja, sie sind eine praktikable Option für eine Ajax-basierte Site. Authentifizierungscookies dienen nicht zur Manipulation durch Skripte, sondern werden vom Browser einfach in alle an den Server gesendeten HTTP-Anforderungen aufgenommen.

Skripte müssen sich keine Gedanken darüber machen, was das Sitzungscookie sagt. Solange Sie authentifiziert sind, enthalten alle Anforderungen an den Server, die entweder von einem Benutzer oder vom Skript initiiert wurden, die entsprechenden Cookies. Die Tatsache, dass die Skripte den Inhalt der Cookies nicht selbst kennen können, spielt keine Rolle.

Cookies, die für andere Zwecke als die Authentifizierung verwendet werden, können ohne das Flag "Nur HTTP" gesetzt werden, wenn das Skript diese ändern oder lesen kann. Sie können auswählen, welche Cookies nur HTTP sein sollen, damit beispielsweise alle nicht sensiblen Elemente wie Benutzeroberflächeneinstellungen (Sortierreihenfolge, Reduzieren des linken Bereichs oder nicht) in Cookies mit den Skripten geteilt werden können.

Ich mag die HTTP-Cookies nur sehr - es ist eine dieser proprietären Browser-Erweiterungen, die eine wirklich nette Idee war.

thomasrutter
quelle
3

Das ist ein bisschen mehr.

Ajax benötigt keine Cookies, aber sie können nützlich sein, wie andere Poster erwähnt haben. Das Markieren eines Cookies HTTPOnly, um es vor Skripten auszublenden, funktioniert nur teilweise, da es nicht von allen Browsern unterstützt wird, sondern auch, weil es allgemeine Problemumgehungen gibt.

Es ist seltsam, dass die XMLHTTPresponse-Header das Cookie geben. Technisch gesehen muss der Server das Cookie nicht mit der Antwort zurückgeben. Sobald es auf dem Client festgelegt ist, bleibt es festgelegt, bis es abläuft. Es gibt jedoch Schemata, bei denen das Cookie bei jeder Anforderung geändert wird, um eine Wiederverwendung zu verhindern. Sie können diese Problemumgehung möglicherweise vermeiden, indem Sie den Server so ändern, dass das Cookie für die XMLHTTP-Antworten nicht bereitgestellt wird.

Im Allgemeinen denke ich jedoch, dass HTTPOnly mit einiger Vorsicht verwendet werden sollte. Es gibt Cross-Site-Scripting-Angriffe, bei denen ein Angreifer veranlasst, dass ein Benutzer eine Ajax-ähnliche Anfrage von einer anderen Site mithilfe einfacher Postformulare ohne Verwendung von XMLHTTP sendet und das noch aktive Cookie Ihres Browsers die Anfrage authentifiziert.

Wenn Sie sicherstellen möchten, dass eine AJAX-Anforderung authentifiziert ist, müssen die Anforderung selbst UND die HTTP-Header das Cookie enthalten. ZB durch die Verwendung von Skripten oder eindeutigen versteckten Eingaben. HTTPOnly würde das verhindern.

Normalerweise besteht der interessante Grund für HTTPOnly darin, zu verhindern, dass auf Ihrer Webseite enthaltene Inhalte von Drittanbietern Cookies stehlen. Es gibt jedoch viele interessante Gründe, sehr vorsichtig mit Inhalten von Drittanbietern umzugehen und diese aggressiv zu filtern.

davenpcj
quelle
1

Cookies werden vom Browser automatisch verarbeitet, wenn Sie einen AJAX-Anruf tätigen, sodass Ihr Javascript nicht mit Cookies herumspielen muss.

pkchukiss
quelle
1

Daher gehe ich davon aus, dass JavaScript Zugriff auf Ihre Cookies benötigt.

Alle HTTP-Anfragen Ihres Browsers übertragen Ihre Cookie-Informationen für die betreffende Site. JavaScript kann Cookies sowohl setzen als auch lesen. Cookies sind per Definition nicht für Ajax-Anwendungen erforderlich, aber für die meisten Webanwendungen, um den Benutzerstatus beizubehalten.

Die formelle Antwort auf Ihre Frage lautet: "Benötigt JavaScript Zugriff auf Cookies, wenn AJAX verwendet wird?" - ist daher "nein". Stellen Sie sich erweiterte Suchfelder vor, die Ajax-Anforderungen verwenden, um beispielsweise Optionen für automatische Vorschläge bereitzustellen. In diesem Fall sind keine Cookie-Informationen erforderlich.

Polsonby
quelle
XmlHttpRequest benötigt Cookies. Die von Ihnen erwähnte erweiterte Suche befindet sich möglicherweise hinter einer Anmeldeseite. Ob Javascript in der Lage sein muss, den Cookie-Wert für die VM verfügbar zu machen, ist eine andere Frage.
Mr. Shiny und New
1

Zur Verdeutlichung: Aus Sicht des Servers unterscheidet sich die Seite, die von einer AJAX-Anforderung angefordert wird, im Wesentlichen nicht von einer Standard-HTTP-Abrufanforderung, die der Benutzer durch Klicken auf einen Link ausführt. Alle normalen Anforderungseigenschaften: Benutzeragent, IP, Sitzung, Cookies usw. werden an den Server übergeben.

Glenn Slaven
quelle
Die "Sitzung" ist kein HTTP-Konzept. Es ist ein High-Level-Konzept, das von einem Framework auf HTTP-Konzepten aufbaut.
Neugieriger
0

Nein, die Seite, die der AJAX-Anruf anfordert, hat auch Zugriff auf Cookies und prüft, ob Sie angemeldet sind.

Sie können eine andere Authentifizierung mit Javascript durchführen, aber ich würde dem nicht vertrauen. Ich bevorzuge es immer, irgendeine Art von Authentifizierungsprüfung im Back-End durchzuführen.

Glenn Slaven
quelle
0

Ja, Cookies sind für Ajax sehr nützlich.

Das Einfügen der Authentifizierung in die Anforderungs-URL ist eine schlechte Praxis. Letzte Woche gab es eine Nachricht über das Abrufen der Authentifizierungstoken in den URLs aus dem Google-Cache.

Nein, es gibt keine Möglichkeit, Angriffe zu verhindern. Ältere Browser ermöglichen weiterhin einen einfachen Zugriff auf Cookies über Javascript. Sie können nur http usw. umgehen. Was auch immer Sie sich einfallen lassen, können Sie mit genügend Aufwand umgehen. Der Trick besteht darin, sich zu viel Mühe zu geben, um sich zu lohnen.

Wenn Sie Ihre Site sicherer machen möchten (es gibt keine perfekte Sicherheit), können Sie ein Authentifizierungscookie verwenden, das abläuft. Wenn das Cookie gestohlen wird, muss der Angreifer es verwenden, bevor es abläuft. Wenn dies nicht der Fall ist, haben Sie einen guten Hinweis darauf, dass auf diesem Konto verdächtige Aktivitäten vorliegen. Je kürzer das Zeitfenster ist, desto besser ist die Sicherheit, aber desto mehr Last belastet Ihr Server beim Generieren und Verwalten von Schlüsseln.

Jay
quelle