CORS: illustrazione del Cross-Origin Resource Sharing
Severamente vietato: chiunque visiti un sito web non deve assolutamente caricare ulteriori dati da server esterni! Ma ci possono essere delle eccezioni. Se entrambi i gestori di siti web concordano sulla cooperazione nulla impedisce un accordo. Il Cross-Origin Resource Sharing (CORS) regolamenta tale cooperazione. Ma come funziona?
Come funziona il CORS?
La same origin policy (SOP) vieta il ricaricamento da altri server quando si visita un sito web. Tutti i dati devono provenire dalla stessa origine, quindi scaturire dallo stesso server. Questa è una misura di sicurezza in quanto JavaScript e CSS possono caricare contenuti di altri server, anche contenuti dannosi, all’insaputa degli utenti. Tale tentativo di accesso viene definito Cross-origin request. Tuttavia, se entrambi gli operatori del sito web sono a conoscenza dello scambio di dati e anzi lo richiedono, la procedura può essere consentita. Il server interpellato ovvero quello da cui ricaricare i contenuti, consente l’accesso tramite il Cross-Origin Resource Sharing.
Tuttavia ciò accade sempre e solo per determinati client. In altre parole CORS non è un lasciapassare per qualsiasi Cross-origin request. Anzi, il secondo server consente al primo l’accesso esclusivo tramite intestazione HTTP. Nell’intestazione della risposta HTTP è riportato con precisione quali server sono autorizzati a ricaricare i dati e infine a renderli disponibili per l’utente. Soltanto tramite l’integrazione di caratteri jolly è consentita un’autorizzazione generale all’accesso da parte di tutti i client. Tuttavia ciò ha senso soltanto per i server che offrono quelle informazioni che dovrebbero essere disponibili al grande pubblico, ad esempio i font per il web.
L’utente, nel migliore dei casi, non ottiene nulla dallo scambio dei due server interessati. Tutti i browser attuali supportano CORS e l’invio di richieste e risposte avviene in background, in brevissimo tempo, quando viene richiamato un sito web.
Struttura delle intestazioni CORS
In base alla same origin policy, le informazioni sull’origine di una connessione al server sono costituite da tre elementi: host, porta e protocollo. La direttiva impedisce pertanto che nell’esempio sopra riportato ’https://example.com’ acceda a ’http://example.com’ oppure a ’https://example.org’. Nel primo caso il protocollo non è lo stesso, nel secondo i due dettagli relativi all’host non sono identici.
Una Cross-origin request è essenzialmente una richiesta HTTP. Alcuni metodi non costituiscono sostanzialmente un problema. GET e HEAD non possono modificare i dati e pertanto non sono generalmente percepiti come una minaccia alla sicurezza. La situazione è diversa per quanto riguarda PATCH, PUT o DELETE, che rendono possibile l’esecuzione di procedure dannose. È quindi necessario attivare in questo caso il Cross-Origin Resource Sharing. CORS può dunque contenere non solo informazioni sull'origine consentita, ma anche informazioni su quali richieste HTTP sono consentite dall’origine.
Nel caso di metodi HTTP inerenti alla sicurezza il client inoltra innanzitutto una preflight request, in cui in realtà si specifica solo quale metodo HTTP verrà poi inviato al server e ci si domanda se la richiesta è considerata sicura. Per questo viene utilizzata l’intestazione OPTIONS. Solo dopo una risposta positiva sarà possibile effettuare la richiesta effettiva.
Esistono diverse intestazioni CORS che si occupano rispettivamente di aspetti diversi. Sono già state citate le due importanti intestazioni per la determinazione di origini sicure e metodi consentiti. Ma ce ne sono altre:
- Access-Control-Allow-Origin: quale origine è consentita?
- Access-Control-Allow-Credentials: le richieste sono consentite anche se la modalità credenziali è impostata su include?
- Access-Control-Allow-Headers: quali intestazioni possono essere utilizzate?
- Access-Control-Allow-Methods: quali metodi di richiesta HTTP sono consentiti?
- Access-Control-Expose-Headers: quali intestazioni possono essere visualizzate?
- Access-Control-Max-Age: qual è il tempo massimo della preflight request prima che scada?
- Access-Control-Request-Headers: quale intestazione HTTP è specificata nella preflight request?
- Access-Control-Request-Method: quale metodo HTTP è specificato nella preflight request?
- Origin: qual è l’origine della richiesta?
Esempio di Cross-Origin Resource Sharing
Nel seguente esempio supponiamo che l’host A (example.com) voglia inviare una DELETE request all’host B (example.org). A tal fine il server originale invia prima una preflight request:
/OPTIONS
Origin: http://example.com
Access-Control-Request-Method: DELETE
Se l’host B non ha problemi con questa Cross-origin request risponde con le intestazioni CORS appropriate:
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: PUT, POST, DELETE
Se le intestazioni nella risposta non corrispondono alle specifiche della richiesta o se il server interpellato non risponde, nessuna Cross-origin request potrà essere eseguita.
Vantaggi e svantaggi di CORS
In realtà CORS serve a eludere un’impostazione di base intrinsecamente sicura, ovvero la same origin policy. La SOP è anche un mezzo efficace per impedire connessioni potenzialmente pericolose. Tuttavia Internet si basa spesso proprio su tali Cross-origin requests poiché molte connessioni da un host all’altro sono piuttosto desiderate.
CORS offre quindi un percorso intermedio: per le situazioni in cui le Cross-origin requests sono esplicitamente richieste, CORS può creare eccezioni. Esiste tuttavia il rischio che i gestori di siti web utilizzino solo i caratteri jolly per motivi di praticità. Ciò significherebbe negare qualsiasi protezione da parte della SOP. È pertanto importante utilizzare CORS solo in casi speciali selezionati e configurarlo nel modo più restrittivo possibile.