Perché non esiste una politica della stessa origine per WebSocket? Perché posso connettermi a ws: // localhost?


86

Vorrei utilizzare WebSocket per la comunicazione tra processi per la mia applicazione (Daemon <-> WebGUI e Daemon <-> FatClient, ecc.). Durante il test, ho provato a connettermi al mio server web socket in esecuzione in locale (ws: // localhost: 1234) tramite il client WebSocket JavaScript su websocket.org ( http://www.websocket.org/echo.html ).

La mia domanda ora è:
perché è possibile? Non esiste una policy cross-origin implementata nei browser (qui: FF29 su Linux)?

Sto chiedendo perché se websocket.org fosse malvagio, potrebbe provare a comunicare con il mio server WS locale e reindirizzare ogni messaggio che riceve da localhost a qualsiasi altro server:

WebSocket Server Locale Browser Evil Web Server
all'indirizzo ws: // localhost: 1234 all'indirizzo http: //evil.tld
        | | |
        | | ------ [GET /] ---------> |
        | | <----- [HTML + EvilJS] ---- |
        | <------ [connect ws: // ..] ---- | |
        | <---- [alcune comunicazioni] -> | |
        | | ---- [avanti malvagio] ----> |
        | | |

Non ho testato l'intero caso d'uso, ma la connessione a ws: // localhost dal JS fornito da websocket.org funziona sicuramente.


2
websocket.org non dovrebbe essere malvagio, i socket Web possono esserlo;)
kuldeep.kamboj

Risposte:


52

Per affrontare il "Perché?" parte, il motivo per cui i browser non applicano la politica della stessa origine (di cui CORS è un allentamento) per WebSocket rispetto alle chiamate AJAX, è perché i WebSocket sono stati introdotti dopo che è stato stabilito il valore delle richieste cross-origin e perché " non sono soggetti a SOP per cominciare, il motivo storico per i controlli lato client CORS non si applica.

Per AJAX, ai tempi di una politica di origine singola globale, i server non si aspettavano mai che un browser autenticato inviasse una richiesta da un dominio diverso 1 , quindi non era necessario assicurarsi che la richiesta provenisse da una posizione attendibile 2 , basta controllare il cookie di sessione. Successivi allentamenti come CORS dovettero avere controlli lato client per evitare di esporre le applicazioni esistenti ad abusi violando questo presupposto (eseguendo effettivamente un attacco CSRF ).

Se il Web venisse inventato oggi, sapendo quello che sappiamo ora, per AJAX non sarebbero necessari né SOP né CORS ed è possibile che tutta la convalida sarebbe lasciata al server.

I WebSocket, essendo una tecnologia più recente, sono progettati per supportare scenari interdominio sin dall'inizio. Chiunque scriva la logica del server dovrebbe essere consapevole della possibilità di richieste cross-origin ed eseguire la convalida necessaria, senza la necessità di pesanti precauzioni lato browser alla CORS.


1 Questa è una semplificazione. Le richieste GET cross-origin per le risorse (inclusi i tag <img>, <link> e <script>) e le richieste POST per l'invio di moduli erano sempre consentite come caratteristica fondamentale del Web. Al giorno d'oggi, le chiamate AJAX cross-origin le cui richieste hanno le stesse proprietà sono anche consentite e note come richieste cross-origin semplici . Tuttavia, l'accesso ai dati restituiti da tali richieste nel codice non è consentito a meno che non sia esplicitamente consentito dalle intestazioni CORS del server. Inoltre, sono queste "semplici" richieste POST la ragione principale per cui i token anti-CSRF sono necessari affinché i server si proteggano da siti Web dannosi.

2 In effetti, un modo sicuro per controllare l'origine della richiesta non era nemmeno disponibile poiché l' Refererintestazione può essere falsificata, ad esempio utilizzando una vulnerabilità di reindirizzamento aperta. Ciò mostra anche come allora le vulnerabilità CSRF fossero comprese male.


6
Questo in effetti risponde alla domanda, quindi +1. Ma, per la cronaca, sono fortemente in disaccordo con questo ragionamento. Prevedo che, come risultato di questa decisione di progettazione, un numero significativo di siti che utilizzano WebSocket non riuscirà a convalidare l' Originintestazione e di conseguenza a divulgare i dati degli utenti privati ​​a siti di terze parti. I client che controllano l' Access-Control-Allow-Originintestazione, come fanno prima di consentire a JS l'accesso alle risposte a qualsiasi altra richiesta HTTP cross-origin sul web, sarebbe stato un modo semplice per prevenire questa intera classe di attacco (Cross-Site WebSocket Hijacking). Troppo tardi adesso.
Ajedi32

3
Sono propenso ad essere d'accordo, il cambiamento di design si sta essenzialmente spostando da un approccio basato sulla whitelist a uno sulla lista nera, il che è rischioso. Punto valido.
staafl

43

oberstet ha risposto alla domanda . Grazie! Purtroppo non posso contrassegnarlo come "corretto" perché era un commento. Il browser invia l'intestazione "origine" che può essere controllata dall'applicazione.

In Java [1]:

@Oltrepassare
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, "Il client non ha inviato l'intestazione di origine corretta:" + clientOrigin);        

        clientSocket.close ();
        ritorno;
    }

    // ...
}

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


1
OWASP menziona il controllo dell'intestazione Origin (e potenzialmente il Referer) nel loro cheat sheet CSRF come primo e più importante passaggio, ma consiglia anche di fare un ulteriore passo avanti e implementare una difesa specifica CSRF. Nel caso di WebSocket, potrebbe essere l'aggiunta di un token antifalsificazione XSRF all'URI WS come parametro di query e la convalida sul lato server dopo il controllo dell'origine.
Kevin Secrist

19

I WebSocket possono comunicare tra domini e non sono limitati dalla SOP (Same Origin Policy).

Lo stesso problema di sicurezza che hai descritto può verificarsi senza WebSocket.

Il malvagio JS può:

  • Crea un tag script / immagine con un URL a evil.tld e inserisci i dati nella stringa di query.
  • Crea un tag form, inserisci i dati nei campi e invoca l'azione "submit" del form, eseguendo un HTTP POST, che può essere cross domain. AJAX è limitato dal SOP, ma il normale HTTP POST non lo è. Controlla il problema di sicurezza web XSRF.

Se qualcosa inietta javascript nella tua pagina, o ottieni javascript dannoso, la tua sicurezza è già rotta.


1
Non sono preoccupato per il malvagio JS. So che questo è sempre possibile. Quello che mi preoccupa veramente è il breakout del browser: qualsiasi sito web può ora comunicare con un socket WS associato localmente e rubare dati da lì.
binwiederhier

54
SOP / CORS non si applica a WebSocket, ma i browser invieranno originun'intestazione che contiene il nome host del server che ha servito l'HTML con il JS che ha aperto la connessione WebSocket. Un server WebSocket può quindi limitare l'accesso controllando origin.
oberstet

Questo non risponde alla domanda. La domanda era perché una pagina Web di un dominio diverso può accedere a un WebSocket locale. Nello scenario OP non c'è nulla che "inietti javascript nella tua pagina" - questo è uno scenario diverso. Senza WebSocket, una pagina web remota non sarebbe in grado di leggere le risorse su localhost, perché questo è esattamente ciò che impedisce il SOP.
sleske
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.