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

Impedisci le fughe di informazioni CSRF, XSSI e multiorigine.

Lukas Weichselbaum
Lukas Weichselbaum

Molte applicazioni web sono vulnerabili agli attacchi cross-origin, come ad esempio gli attacchi cross-site request forgery (CSRF), cross-site script inclusion (XSSI), attacchi temporali, fuga di informazioni cross-origin o attacchi speculativi side-channel (Spectre).

Le intestazioni delle richieste Fetch Metadata consentono di eseguire il deployment di un meccanismo di difesa in profondità efficace, ovvero un criterio di isolamento delle risorse, per proteggere la tua applicazione da questi comuni attacchi multiorigine.

È comune 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 sulle intestazioni delle richieste di recupero dei metadati richiede uno sforzo minimo e allo stesso tempo protegge l'applicazione da attacchi tra siti.

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

Molti attacchi cross-site sono possibili 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 multiorigine è la falsificazione di richieste cross-site (CSRF), in cui un aggressore attira un utente su un sito che controlla e poi invia un modulo al server a 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 scartare il traffico tra siti 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 multiorigine. 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. In questo modo, è possibile rispondere solo a richieste legittime presentate dalla loro applicazione.

Same-Origin
Le richieste provenienti dai siti gestiti 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 valori:

  • same-origin, se la richiesta è stata effettuata dalla tua stessa 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 Recupera i metadati per proteggerti dagli attacchi multiorigine

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 traffico mitiga le vulnerabilità web più comuni tra siti come CSRF, XSSI, attacchi temporali e fughe di informazioni tra origini. Questo criterio può essere abilitato per tutti gli endpoint dell'applicazione e consentirà tutte le richieste di risorse provenienti dalla tua applicazione, nonché navigazioni dirette (tramite una richiesta GET HTTP). 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 header 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:

  • Deve avere origine dalla tua applicazione (ad esempio, una richiesta della stessa origine in cui site.example richiede site.example/foo.json sarà sempre consentita).
  • Provenienza 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 fare in modo che il tuo sito possa essere ancora inserito in altri siti tramite link, devi consentire una 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 a livello di singolo percorso o di singolo endpoint. Ecco alcuni esempi di endpoint di questo tipo:

  • Endpoint a cui è possibile accedere multiorigine: se la tua applicazione gestisce endpoint con CORS abilitato, devi disattivare esplicitamente l'isolamento delle risorse per questi endpoint affinché siano ancora possibili richieste tra siti a questi endpoint.
  • 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 cross-site e non di navigazione

Qualsiasi altra richiesta tra siti verrà rifiutata in base a queste norme sull'isolamento delle risorse, proteggendo così la tua applicazione dagli attacchi più comuni tra siti.

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

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 escludendo gli endpoint multiorigine legittimi.
  3. Applica il criterio ignorando le richieste non conformi.

Identificazione e correzione delle violazioni delle norme

Ti consigliamo di testare il criterio senza effetti collaterali attivandolo prima in modalità di reporting nel codice lato server. In alternativa, puoi implementare questa logica nel middleware o in un proxy inverso che registra le eventuali violazioni che il tuo criterio potrebbe generare quando applicato al traffico di produzione.

In base alla nostra esperienza nell'implementazione di un criterio di isolamento delle risorse di recupero dei metadati su Google, la maggior parte delle applicazioni è per impostazione predefinita compatibile con tale criterio e raramente richiedono l'esenzione degli endpoint per consentire il traffico tra siti.

Applicazione di un criterio di isolamento delle risorse

Dopo aver verificato che i criteri non incidono sul traffico di produzione legittimo, puoi applicare le restrizioni per garantire che altri siti non possano richiedere le tue risorse e proteggere gli utenti da attacchi tra siti.

Per approfondire