Proteggi le tue risorse dagli attacchi web con i metadati di recupero

Evita CSRF, XSSI e fughe di informazioni cross-origin.

Lukas Weichselbaum
Lukas Weichselbaum

Molte applicazioni web sono vulnerabili ad attacchi cross-origin come cross-site request forgery (CSRF), cross-site script inclusion (XSSI), attacchi di temporizzazione, fughe di informazioni cross-origin o attacchi di side-channel di esecuzione speculativa (Spectre).

Le intestazioni di richiesta Fetch Metadata ti consentono di implementare un solido meccanismo di difesa in profondità, un criterio di isolamento delle risorse, per proteggere la tua applicazione da questi comuni attacchi cross-origin.

È normale che le risorse esposte da una determinata applicazione web vengano caricate solo dall'applicazione stessa e non da altri siti web. In questi casi, il deployment di un criterio di isolamento delle risorse basato sugli intestazioni delle richieste di recupero dei metadati richiede poco impegno e, allo stesso tempo, protegge l'applicazione dagli attacchi cross-site.

Compatibilità del browser

Le intestazioni delle richieste di recupero dei metadati sono supportate in tutti i motori dei browser moderni.

Supporto dei browser

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4.

Origine

Sfondo

Sono possibili molti attacchi cross-site perché il web è aperto per impostazione predefinita e il server delle applicazioni non può proteggersi facilmente dalle comunicazioni provenienti da applicazioni esterne. Un tipico attacco cross-origin è la falsificazione delle richieste cross-site (CSRF), in cui un malintenzionato attira un utente su un sito che controlla e poi invia un modulo al server su cui l'utente ha eseguito l'accesso. Poiché il server non può sapere se la richiesta ha avuto origine da un altro dominio (cross-site) e il browser allega automaticamente i cookie alle richieste cross-site, il server eseguirà l'azione richiesta dall'aggressore per conto dell'utente.

Altri attacchi cross-site come l'inclusione di script cross-site (XSSI) o le fughe di informazioni cross-origin sono simili in natura al CSRF e si basano sul caricamento di risorse da un'applicazione vittima in un documento controllato dall'aggressore e sulla fuga di informazioni sulle applicazioni vittima. Poiché le applicazioni non sono in grado di distinguere facilmente le richieste attendibili da quelle non attendibili, non possono eliminare il traffico cross-site dannoso.

Introduzione a Recupera metadati

Le intestazioni delle richieste di recupero dei metadati sono una nuova funzionalità di sicurezza della piattaforma web progettata per aiutare i server a difendersi dagli attacchi cross-origin. Fornendo informazioni sul contesto di una richiesta HTTP in un insieme di intestazioni Sec-Fetch-*, consentono al server che risponde di applicare i criteri di sicurezza prima di elaborare la richiesta. In questo modo, gli sviluppatori possono decidere se accettare o rifiutare una richiesta in base al modo in cui è stata effettuata e al contesto in cui verrà utilizzata, il che consente di rispondere solo alle richieste legittime effettuate dalla propria applicazione.

Same-Origin
Le richieste provenienti da siti pubblicati dal tuo server (stessa origine) continueranno a funzionare. Una richiesta di recupero da https://site.example per la risorsa https://site.example/foo.json in JavaScript fa sì che il browser invii l'intestazione della richiesta HTTP "Sec Fetch-Site: same-origin".
Tra siti
Le richieste cross-site dannose possono essere rifiutate dal server a causa del contesto aggiuntivo nella richiesta HTTP fornito dalle intestazioni Sec-Fetch-*. Un'immagine su https://evil.example in cui è impostato l'attributo src di un elemento img su "https://site.example/foo.json" fa sì che il browser invii l'intestazione della richiesta HTTP "Sec-Fetch-Site: cross-site".

Sec-Fetch-Site

Supporto dei browser

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4.

Origine

Sec-Fetch-Site indica al server quale sito ha inviato la richiesta. Il browser imposta questo valore su uno dei seguenti:

  • same-origin, se la richiesta è stata effettuata dalla tua applicazione (ad es. site.example)
  • same-site, se la richiesta è stata effettuata da un sottodominio del tuo sito (ad es. bar.site.example)
  • none, se la richiesta è stata causata esplicitamente dall'interazione di un utente con lo user agent (ad es. facendo clic su un preferito)
  • cross-site, se la richiesta è stata inviata da un altro sito web (ad es. evil.example)

Sec-Fetch-Mode

Supporto dei browser

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4.

Origine

Sec-Fetch-Mode indica la modalità della richiesta. Corrisponde approssimativamente al tipo di richiesta e consente di distinguere i caricamenti delle risorse dalle richieste di navigazione. Ad esempio, una destinazione navigate indica una richiesta di navigazione di primo livello, mentre no-cors indica richieste di risorse come il caricamento di un'immagine.

Sec-Fetch-Dest

Supporto dei browser

  • Chrome: 80.
  • Bordo: 80.
  • Firefox: 90.
  • Safari: 16.4.

Origine

Sec-Fetch-Dest espone la destinazione di una richiesta (ad es. se un tag script o img ha causato la richiesta di una risorsa da parte del browser).

Come utilizzare i metadati di recupero per proteggersi dagli attacchi cross-origin

Le informazioni aggiuntive fornite da queste intestazioni di richiesta sono piuttosto semplici, ma il contesto aggiuntivo consente di creare una logica di sicurezza efficace lato server, nota anche come criterio di isolamento delle risorse, con poche righe di codice.

Implementazione di un criterio di isolamento delle risorse

Un criterio di isolamento delle risorse impedisce che le risorse vengano richieste da siti web esterni. Il blocco di questo tipo di traffico riduce le vulnerabilità web cross-site comuni, come CSRF, XSSI, attacchi di temporizzazione e fughe di informazioni cross-origin. Questo criterio può essere attivato per tutti gli endpoint della tua applicazione e consentirà tutte le richieste di risorse provenienti dalla tua applicazione, nonché le navigazioni dirette (tramite una richiesta HTTP GET). Gli endpoint che dovrebbero essere caricati in un contesto cross-site (ad es. gli endpoint caricati utilizzando CORS) possono essere esclusi da questa logica.

Passaggio 1: consenti le richieste da browser che non inviano metadati di recupero

Poiché non tutti i browser supportano il recupero dei metadati, devi consentire le richieste che non impostano gli intestazioni Sec-Fetch-* controllando la presenza di sec-fetch-site.

if not req['sec-fetch-site']:
 
return True  # Allow this request

Passaggio 2: consenti le richieste all'interno del sito e quelle avviate dal browser

Tutte le richieste che non provengono da un contesto cross-origin (come evil.example) saranno consentite. In particolare, si tratta di richieste che:

  • Provenire dalla tua applicazione (ad es. una richiesta per la stessa origine in cui le richieste site.example a site.example/foo.json saranno sempre consentite).
  • Hanno origine dai tuoi sottodomini.
  • Sono causate esplicitamente dall'interazione di un utente con l'agente utente (ad es. navigazione diretta o facendo clic su un preferito e così via).
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
 
return True  # Allow this request

Passaggio 3: consenti la navigazione di primo livello semplice e l'iframe

Per assicurarti che il tuo sito possa comunque essere collegato da altri siti, devi consentire la navigazione di primo livello semplice (HTTP GET).

if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
 
# <object> and <embed> send navigation requests, which we disallow.
 
and req['sec-fetch-dest'] not in ('object', 'embed'):
   
return True  # Allow this request

(Facoltativo) Passaggio 4: disattiva gli endpoint destinati a gestire il traffico tra siti

In alcuni casi, l'applicazione potrebbe fornire risorse destinate a essere caricate su più siti. Queste risorse devono essere esenti in base al percorso o all'endpoint. Ecco alcuni esempi di endpoint di questo tipo:

  • Endpoint a cui è previsto l'accesso cross-origin: se la tua applicazione pubblica endpoint abilitati per CORS, devi disattivarli esplicitamente dall'isolamento delle risorse per assicurarti che le richieste cross-site a questi endpoint siano ancora possibili.
  • Risorse pubbliche (ad es. immagini, stili e così via): Possono essere esenti anche le risorse pubbliche e non autenticate che devono essere caricabili tra origini da altri siti.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
 
return True

Passaggio 5: rifiuta tutte le altre richieste tra siti e non di navigazione

Qualsiasi altra richiesta cross-site verrà rifiutata da questo criterio di isolamento delle risorse e, di conseguenza, la tua applicazione sarà protetta dai comuni attacchi cross-site.

Esempio: il codice seguente mostra un'implementazione completa di un criterio di isolamento delle risorse solido sul server o come middleware per negare richieste di risorse cross-site potenzialmente dannose, consentendo al contempo semplici richieste di navigazione:

# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
 
# Allow requests from browsers which don't send Fetch Metadata
 
if not req['sec-fetch-site']:
   
return True

 
# Allow same-site and browser-initiated requests
 
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
   
return True

 
# Allow simple top-level navigations except <object> and <embed>
 
if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
   
and req['sec-fetch-dest'] not in ('object', 'embed'):
     
return True

 
# [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
 
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
   
return True

 
# Reject all other requests that are cross-site and not navigational
 
return False

Eseguire il deployment di un criterio di isolamento delle risorse

  1. Installa un modulo come lo snippet di codice riportato sopra per registrare e monitorare il comportamento del tuo sito e assicurarti che le limitazioni non influiscano sul traffico legittimo.
  2. Correggi le potenziali violazioni esentando gli endpoint cross-origin legittimi.
  3. Applica il criterio ignorando le richieste non conformi.

Identificazione e correzione delle violazioni delle norme

Ti consigliamo di testare il criterio in modo da non avere effetti collaterali attivandolo prima in modalità di generazione di report nel codice lato server. In alternativa, puoi implementare questa logica nel middleware o in un proxy inverso che registri eventuali violazioni che le tue norme potrebbero produrre quando applicate al traffico di produzione.

Dalla nostra esperienza di implementazione di un criterio di isolamento delle risorse dei metadati di recupero in Google, la maggior parte delle applicazioni è compatibile per impostazione predefinita con questo criterio e raramente richiede l'esenzione degli endpoint per consentire il traffico tra siti.

Applicazione di un criterio di isolamento delle risorse

Dopo aver verificato che i tuoi criteri non influiscono sul traffico di produzione legittimo, puoi applicare le restrizioni, garantendo che altri siti non possano richiedere le tue risorse e proteggendo i tuoi utenti dagli attacchi cross-site.

Per approfondire