Warum gibt es für WebSockets keine Richtlinie mit demselben Ursprung? Warum kann ich eine Verbindung zu ws: // localhost herstellen?

82

Ich möchte WebSockets für die prozessübergreifende Kommunikation für meine Anwendung verwenden (Daemon <-> WebGUI und Daemon <-> FatClient usw.). Während des Tests habe ich versucht, über den JavaScript-WebSocket-Client auf websocket.org ( http://www.websocket.org/echo.html ) eine Verbindung zu meinem lokal ausgeführten Web-Socket-Server (ws: // localhost: 1234) herzustellen .

Meine Frage ist jetzt:
Warum ist das möglich? Ist in den Browsern keine Cross-Origin-Richtlinie implementiert (hier: FF29 unter Linux)?

Ich frage, weil websocket.org, wenn es böse wäre, versuchen könnte, mit meinem lokalen WS-Server zu kommunizieren und jede Nachricht, die es von localhost empfängt, auf einen anderen Server umzuleiten:

Lokaler WebSocket Server Browser Böser Webserver
at ws: // localhost: 1234 at http: //evil.tld
        | | |
        | | ------ [GET /] ---------> |
        | | <----- [HTML + EvilJS] ---- |
        | <------ [connect ws: // ..] ---- | |
        | <---- [etwas Kommunikation] -> | |
        | | ---- [böser Vorwärts] ----> |
        | | |

Ich habe nicht den gesamten Anwendungsfall getestet, aber die Verbindung zu ws: // localhost aus dem von websocket.org bereitgestellten JS funktioniert definitiv.

binwiederhier
quelle
2
websocket.org sollte nicht böse sein, Web-Sockets können sein;)
kuldeep.kamboj

Antworten:

48

Um das "Warum?" Der Grund, warum Browser im Gegensatz zu AJAX-Aufrufen nicht die gleiche Ursprungsrichtlinie (von der CORS eine Lockerung darstellt) für WebSockets erzwingen, liegt darin, dass WebSockets eingeführt wurden, nachdem der Wert von Ursprungsübergreifenden Anforderungen festgelegt wurde, und weil sie Da die SOP zunächst nicht der SOP unterliegt, gilt der historische Grund für die clientseitigen CORS-Überprüfungen nicht.

Für AJAX haben Server in den Tagen einer umfassenden Single Origin-Richtlinie nie erwartet, dass ein authentifizierter Browser eine Anfrage von einer anderen Domäne 1 sendet , und mussten daher nicht sicherstellen, dass die Anfrage von einem vertrauenswürdigen Speicherort 2 stammt . Überprüfen Sie einfach die Sitzungscookie. Spätere Lockerungen wie CORS mussten clientseitig überprüft werden, um zu vermeiden, dass vorhandene Anwendungen durch Verletzung dieser Annahme einem Missbrauch ausgesetzt werden (was effektiv zu einem CSRF-Angriff führt ).

Wenn das Web heute erfunden würde und wüsste, was wir jetzt wissen, wären für AJAX weder SOP noch CORS erforderlich, und es ist möglich, dass die gesamte Validierung dem Server überlassen bleibt.

WebSockets ist eine neuere Technologie und unterstützt domänenübergreifende Szenarien von Anfang an. Jeder, der eine Serverlogik schreibt, sollte sich der Möglichkeit von Ursprungsübergreifenden Anforderungen bewusst sein und die erforderliche Validierung durchführen, ohne dass umfangreiche Browser-Vorsichtsmaßnahmen à la CORS erforderlich sind.


1 Dies ist eine Vereinfachung. Ursprungsübergreifende GET-Anforderungen für Ressourcen (einschließlich <img> -, <link> - und <script> -Tags) und POST-Anforderungen für die Formularübermittlung waren als grundlegendes Merkmal des Webs immer zulässig. Heutzutage sind auch Cross-Origin-AJAX-Aufrufe mit denselben Eigenschaften zulässig und werden als einfache Cross-Origin-Anforderungen bezeichnet . Der Zugriff auf die zurückgegebenen Daten aus solchen Anforderungen im Code ist jedoch nur zulässig, wenn dies in den CORS-Headern des Servers ausdrücklich gestattet ist. Es sind auch diese "einfachen" POST-Anfragen, die den Hauptgrund dafür darstellen, dass Anti-CSRF-Token erforderlich sind, damit sich Server vor bösartigen Websites schützen können.

2 Tatsächlich war nicht einmal eine sichere Möglichkeit zum Überprüfen der Anforderungsquelle verfügbar, da der RefererHeader gefälscht werden kann, z. B. mithilfe einer Sicherheitsanfälligkeit bezüglich offener Umleitung. Dies zeigt auch, wie schlecht CSRF-Schwachstellen damals verstanden wurden.

staafl
quelle
6
Dies beantwortet in der Tat die Frage, also +1. Aber fürs Protokoll, ich bin mit dieser Argumentation überhaupt nicht einverstanden. Ich gehe davon aus, dass aufgrund dieser Entwurfsentscheidung eine erhebliche Anzahl von Websites, die WebSockets verwenden, den OriginHeader nicht validieren und daher private Benutzerdaten an Websites von Drittanbietern weitergeben können. Clients, die den Access-Control-Allow-OriginHeader überprüfen , bevor sie JS Zugriff auf die Antworten auf andere originensübergreifende HTTP-Anforderungen im Web gewähren, wären eine einfache Möglichkeit gewesen, diese gesamte Angriffsklasse zu verhindern (Cross-Site WebSocket Hijacking). Jetzt ist es zu spät.
Ajedi32
3
Ich bin geneigt zuzustimmen, dass die Designänderung im Wesentlichen von einem Whitelist-basierten Ansatz zu einem Blacklist-Ansatz übergeht, was riskant ist. Gutes Argument.
Staafl
42

oberstet beantwortete die frage . Danke dir! Leider kann ich es nicht als "richtig" markieren, da es ein Kommentar war. Der Browser sendet den "Origin" -Header, der von der Anwendung überprüft werden kann.

In Java [1]:

@Override
public void onOpen (WebSocket clientSocket, ClientHandshake-Handshake) {
    String clientOrigin = handshake.getFieldValue ("origin");

    if (clientOrigin == null ||! clientOrigin.equals (WEBSOCKET_ALLOWED_ORIGIN_HEADER)) {
        logger.log (Level.WARNING, "Client hat nicht den richtigen Ursprungsheader gesendet:" + clientOrigin);        

        clientSocket.close ();
        Rückkehr;
    }}

    // ...
}}

[1] Verwenden von https://github.com/TooTallNate/Java-WebSocket

binwiederhier
quelle
OWASP erwähnt als ersten und wichtigsten Schritt die Überprüfung des Origin-Headers (und möglicherweise des Referers) in seinem CSRF-Spickzettel , empfiehlt jedoch auch, einen Schritt weiter zu gehen und eine CSRF-spezifische Verteidigung zu implementieren. Bei WebSockets wird möglicherweise ein XSRF-Antiforgery-Token als Abfrageparameter an den WS-URI angehängt und nach der Ursprungsprüfung serverseitig überprüft.
Kevin Secrist
17

WebSockets können domänenübergreifende Kommunikation ermöglichen und sind nicht durch die SOP (Same Origin Policy) beschränkt.

Das gleiche Sicherheitsproblem, das Sie beschrieben haben, kann auch ohne WebSockets auftreten.

Der böse JS kann:

  • Erstellen Sie ein Skript- / Bild-Tag mit einer URL zu evil.tld und fügen Sie Daten in die Abfragezeichenfolge ein.
  • Erstellen Sie ein Formular-Tag, fügen Sie die Daten in die Felder ein und rufen Sie die Aktion "Senden" des Formulars auf, indem Sie einen HTTP-POST ausführen, der domänenübergreifend sein kann. AJAX ist durch die SOP begrenzt, normaler HTTP-POST jedoch nicht. Überprüfen Sie das XSRF-Web-Sicherheitsproblem.

Wenn etwas Javascript in Ihre Seite einfügt oder Sie böswilliges Javascript erhalten, ist Ihre Sicherheit bereits verletzt.

vtortola
quelle
1
Ich mache mir keine Sorgen um den bösen JS. Ich weiß, dass das immer möglich ist. Was mich wirklich beunruhigt, ist der Browser-Ausbruch: Jede Website kann jetzt mit einem lokal gebundenen WS-Socket kommunizieren und Daten von dort stehlen.
Binwiederhier
52
SOP / CORS gilt nicht für WebSocket, aber Browser senden einen originHeader, der den Hostnamen des Servers enthält, der den HTML-Code mit dem JS bereitgestellt hat, der die WebSocket-Verbindung geöffnet hat. Ein WebSocket-Server kann dann den Zugriff durch Überprüfen einschränkenorigin .
Oberstet
Dies beantwortet die Frage nicht. Die Frage war, warum eine Webseite aus einer anderen Domäne auf ein lokales WebSocket zugreifen kann. Im OP-Szenario gibt es nichts, was "Javascript in Ihre Seite einfügt" - das ist ein anderes Szenario. Ohne WebSocket könnte eine Remote-Webseite keine Ressourcen auf localhost lesen, da genau dies durch die SOP verhindert wird.
Sleske