CORS - Misconfigurations & Bypass
Last updated
Last updated
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Il Cross-Origin Resource Sharing (CORS) standard consente ai server di definire chi può accedere alle loro risorse e quali metodi di richiesta HTTP sono consentiti da fonti esterne.
Una politica di same-origin impone che un server che richiede una risorsa e il server che ospita la risorsa condividano lo stesso protocollo (ad es., http://
), nome di dominio (ad es., internal-web.com
) e porta (ad es., 80). Sotto questa politica, solo le pagine web dello stesso dominio e porta sono autorizzate ad accedere alle risorse.
L'applicazione della politica di same-origin nel contesto di http://normal-website.com/example/example.html
è illustrata come segue:
http://normal-website.com/example/
Sì: Schema, dominio e porta identici
http://normal-website.com/example2/
Sì: Schema, dominio e porta identici
https://normal-website.com/example/
No: Schema e porta diversi
http://en.normal-website.com/example/
No: Dominio diverso
http://www.normal-website.com/example/
No: Dominio diverso
http://normal-website.com:8080/example/
No: Porta diversa*
*Internet Explorer ignora il numero di porta nell'applicazione della politica di same-origin, consentendo quindi questo accesso.
Access-Control-Allow-Origin
Questa intestazione può consentire più origini, un valore null
o un carattere jolly *
. Tuttavia, nessun browser supporta più origini, e l'uso del carattere jolly *
è soggetto a limitazioni. (Il carattere jolly deve essere usato da solo, e il suo uso insieme a Access-Control-Allow-Credentials: true
non è consentito.)
Questa intestazione è emessa da un server in risposta a una richiesta di risorsa cross-domain avviata da un sito web, con il browser che aggiunge automaticamente un'intestazione Origin
.
Access-Control-Allow-Credentials
Per default, le richieste cross-origin vengono effettuate senza credenziali come cookie o l'intestazione di autorizzazione. Tuttavia, un server cross-domain può consentire la lettura della risposta quando le credenziali vengono inviate impostando l'intestazione Access-Control-Allow-Credentials
su true
.
Se impostata su true
, il browser trasmetterà le credenziali (cookie, intestazioni di autorizzazione o certificati client TLS).
Quando si avvia una richiesta cross-domain in determinate condizioni, come l'uso di un metodo HTTP non standard (qualsiasi cosa diversa da HEAD, GET, POST), l'introduzione di nuovi header, o l'impiego di un particolare valore dell'header Content-Type, potrebbe essere necessaria una richiesta di pre-flight. Questa richiesta preliminare, che sfrutta il metodo OPTIONS
, serve a informare il server delle intenzioni della prossima richiesta cross-origin, inclusi i metodi HTTP e gli header che si intende utilizzare.
Il protocollo Cross-Origin Resource Sharing (CORS) richiede questo controllo di pre-flight per determinare la fattibilità dell'operazione cross-origin richiesta verificando i metodi, gli header e l'affidabilità dell'origine consentiti. Per una comprensione dettagliata delle condizioni che eludono la necessità di una richiesta di pre-flight, fare riferimento alla guida completa fornita da Mozilla Developer Network (MDN).
È fondamentale notare che l'assenza di una richiesta di pre-flight non annulla l'obbligo che la risposta contenga header di autorizzazione. Senza questi header, il browser è incapace di elaborare la risposta dalla richiesta cross-origin.
Considera la seguente illustrazione di una richiesta di pre-flight mirata a utilizzare il metodo PUT
insieme a un header personalizzato chiamato Special-Request-Header
:
In risposta, il server potrebbe restituire intestazioni che indicano i metodi accettati, l'origine consentita e altri dettagli della politica CORS, come mostrato di seguito:
Access-Control-Allow-Headers
: Questo header specifica quali header possono essere utilizzati durante la richiesta effettiva. Viene impostato dal server per indicare gli header consentiti nelle richieste dal client.
Access-Control-Expose-Headers
: Attraverso questo header, il server informa il client su quali header possono essere esposti come parte della risposta oltre agli header di risposta semplici.
Access-Control-Max-Age
: Questo header indica per quanto tempo i risultati di una richiesta pre-flight possono essere memorizzati nella cache. Il server imposta il tempo massimo, in secondi, che le informazioni restituite da una richiesta pre-flight possono essere riutilizzate.
Access-Control-Request-Headers
: Utilizzato nelle richieste pre-flight, questo header è impostato dal client per informare il server su quali header HTTP il client desidera utilizzare nella richiesta effettiva.
Access-Control-Request-Method
: Questo header, utilizzato anche nelle richieste pre-flight, è impostato dal client per indicare quale metodo HTTP sarà utilizzato nella richiesta effettiva.
Origin
: Questo header è impostato automaticamente dal browser e indica l'origine della richiesta cross-origin. Viene utilizzato dal server per valutare se la richiesta in arrivo debba essere consentita o negata in base alla politica CORS.
Nota che di solito (a seconda del content-type e degli header impostati) in una richiesta GET/POST non viene inviata alcuna richiesta pre-flight (la richiesta viene inviata direttamente), ma se vuoi accedere agli header/corpo della risposta, deve contenere un header Access-Control-Allow-Origin che lo consente. Pertanto, CORS non protegge contro CSRF (ma può essere utile).
Access-Control-Request-Local-Network
: Questo header è incluso nella richiesta del client per significare che l'inchiesta è rivolta a una risorsa di rete locale. Serve come un marcatore per informare il server che la richiesta proviene dall'interno della rete locale.
Access-Control-Allow-Local-Network
: In risposta, i server utilizzano questo header per comunicare che la risorsa richiesta è consentita per essere condivisa con entità al di fuori della rete locale. Funziona come un semaforo verde per la condivisione delle risorse attraverso diversi confini di rete, garantendo un accesso controllato mantenendo i protocolli di sicurezza.
Una risposta valida che consente la richiesta di rete locale deve avere anche nella risposta l'header Access-Controls-Allow-Local_network: true
:
Nota che l'IP linux 0.0.0.0 funziona per bypassare questi requisiti per accedere a localhost poiché quell'indirizzo IP non è considerato "locale".
È anche possibile bypassare i requisiti della rete locale se si utilizza l'indirizzo IP pubblico di un endpoint locale (come l'IP pubblico del router). Perché in diverse occasioni, anche se l'IP pubblico viene accesso, se è dalla rete locale, l'accesso sarà concesso.
Nota che anche se la seguente configurazione potrebbe sembrare super permissiva:
Questo non è consentito dai browser e quindi le credenziali non verranno inviate con la richiesta consentita da questo.
È stato osservato che l'impostazione di Access-Control-Allow-Credentials
su true
è un prerequisito per la maggior parte degli attacchi reali. Questa impostazione consente al browser di inviare credenziali e leggere la risposta, aumentando l'efficacia dell'attacco. Senza questo, il vantaggio di far emettere una richiesta da un browser rispetto a farlo da soli diminuisce, poiché sfruttare i cookie di un utente diventa impraticabile.
Esiste un'eccezione in cui la posizione di rete della vittima funge da forma di autenticazione. Questo consente di utilizzare il browser della vittima come proxy, eludendo l'autenticazione basata su IP per accedere alle applicazioni intranet. Questo metodo condivide somiglianze nell'impatto con il DNS rebinding ma è più semplice da sfruttare.
Origin
in Access-Control-Allow-Origin
Lo scenario del mondo reale in cui il valore dell'intestazione Origin
è riflesso in Access-Control-Allow-Origin
è teoricamente improbabile a causa delle restrizioni sulla combinazione di queste intestazioni. Tuttavia, gli sviluppatori che cercano di abilitare CORS per più URL possono generare dinamicamente l'intestazione Access-Control-Allow-Origin
copiando il valore dell'intestazione Origin
. Questo approccio può introdurre vulnerabilità, in particolare quando un attaccante utilizza un dominio con un nome progettato per apparire legittimo, ingannando così la logica di convalida.
null
L'origine null
, specificata per situazioni come i reindirizzamenti o i file HTML locali, occupa una posizione unica. Alcune applicazioni autorizzano questa origine per facilitare lo sviluppo locale, consentendo involontariamente a qualsiasi sito web di imitare un'origine null
tramite un iframe sandboxed, eludendo così le restrizioni CORS.
Quando si incontra una whitelist di domini, è fondamentale testare le opportunità di bypass, come l'aggiunta del dominio dell'attaccante a un dominio autorizzato o lo sfruttamento delle vulnerabilità di takeover dei sottodomini. Inoltre, le espressioni regolari utilizzate per la convalida dei domini possono trascurare le sfumature nelle convenzioni di denominazione dei domini, presentando ulteriori opportunità di bypass.
I modelli Regex si concentrano tipicamente su caratteri alfanumerici, punto (.) e trattino (-), trascurando altre possibilità. Ad esempio, un nome di dominio creato per includere caratteri interpretati in modo diverso dai browser e dai modelli regex può eludere i controlli di sicurezza. La gestione dei caratteri di sottolineatura nei sottodomini da parte di Safari, Chrome e Firefox illustra come tali discrepanze possano essere sfruttate per eludere la logica di convalida dei domini.
Per ulteriori informazioni e impostazioni di questo controllo di bypass: https://www.corben.io/advanced-cors-techniques/ e https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397
Gli sviluppatori spesso implementano meccanismi difensivi per proteggere contro lo sfruttamento di CORS autorizzando i domini che possono richiedere informazioni. Nonostante queste precauzioni, la sicurezza del sistema non è infallibile. La presenza di anche un singolo sottodominio vulnerabile all'interno dei domini autorizzati può aprire la porta allo sfruttamento di CORS attraverso altre vulnerabilità, come XSS (Cross-Site Scripting).
Per illustrare, consideriamo lo scenario in cui un dominio, requester.com
, è autorizzato ad accedere alle risorse di un altro dominio, provider.com
. La configurazione lato server potrebbe apparire in questo modo:
In this setup, all subdomains of requester.com
are allowed access. However, if a subdomain, say sub.requester.com
, is compromised with an XSS vulnerability, an attacker can leverage this weakness. For example, an attacker with access to sub.requester.com
could exploit the XSS vulnerability to bypass CORS policies and maliciously access resources on provider.com
.
PortSwigger’s URL validation bypass cheat sheet ha scoperto che alcuni browser supportano caratteri strani all'interno dei nomi di dominio.
Chrome e Firefox supportano i trattini bassi _
che possono bypassare le regex implementate per convalidare l'intestazione Origin
:
Safari è ancora più permissivo nell'accettare caratteri speciali nel nome di dominio:
È possibile che sfruttando l'avvelenamento della cache lato server attraverso l'iniezione di intestazioni HTTP, si possa indurre una vulnerabilità Cross-Site Scripting (XSS) memorizzata. Questo scenario si verifica quando un'applicazione non riesce a sanificare l'intestazione Origin
per caratteri non validi, creando una vulnerabilità particolarmente per gli utenti di Internet Explorer e Edge. Questi browser trattano (0x0d) come un terminatore di intestazione HTTP legittimo, portando a vulnerabilità di iniezione di intestazioni HTTP.
Considera la seguente richiesta in cui l'intestazione Origin
è manipolata:
Internet Explorer ed Edge interpretano la risposta come:
Mentre sfruttare direttamente questa vulnerabilità facendo inviare a un browser web un'intestazione malformata non è fattibile, una richiesta elaborata può essere generata manualmente utilizzando strumenti come Burp Suite. Questo metodo potrebbe portare a una cache lato server che salva la risposta e la serve involontariamente ad altri. Il payload elaborato mira a modificare il set di caratteri della pagina in UTF-7, una codifica di caratteri spesso associata a vulnerabilità XSS a causa della sua capacità di codificare caratteri in un modo che può essere eseguito come script in determinati contesti.
Per ulteriori letture sulle vulnerabilità XSS memorizzate, vedere PortSwigger.
Nota: Lo sfruttamento delle vulnerabilità di iniezione di intestazioni HTTP, in particolare attraverso il poisoning della cache lato server, sottolinea l'importanza critica di convalidare e sanificare tutti gli input forniti dall'utente, comprese le intestazioni HTTP. Utilizzare sempre un modello di sicurezza robusto che includa la convalida degli input per prevenire tali vulnerabilità.
In questo scenario, si osserva un'istanza di una pagina web che riflette i contenuti di un'intestazione HTTP personalizzata senza una corretta codifica. In particolare, la pagina web riflette i contenuti inclusi in un'intestazione X-User-id
, che potrebbe includere JavaScript malevolo, come dimostrato dall'esempio in cui l'intestazione contiene un tag immagine SVG progettato per eseguire codice JavaScript al caricamento.
Le politiche di Cross-Origin Resource Sharing (CORS) consentono l'invio di intestazioni personalizzate. Tuttavia, senza che la risposta venga direttamente renderizzata dal browser a causa delle restrizioni CORS, l'utilità di tale iniezione potrebbe sembrare limitata. Il punto critico sorge quando si considera il comportamento della cache del browser. Se l'intestazione Vary: Origin
non è specificata, diventa possibile che la risposta malevola venga memorizzata nella cache dal browser. Successivamente, questa risposta memorizzata nella cache potrebbe essere renderizzata direttamente quando si naviga all'URL, eludendo la necessità di un rendering diretto alla richiesta iniziale. Questo meccanismo aumenta l'affidabilità dell'attacco sfruttando la cache lato client.
Per illustrare questo attacco, viene fornito un esempio di JavaScript, progettato per essere eseguito nell'ambiente di una pagina web, come attraverso un JSFiddle. Questo script esegue un'azione semplice: invia una richiesta a un URL specificato con un'intestazione personalizzata contenente il JavaScript malevolo. Al completamento con successo della richiesta, tenta di navigare all'URL di destinazione, potenzialmente attivando l'esecuzione dello script iniettato se la risposta è stata memorizzata nella cache senza una corretta gestione dell'intestazione Vary: Origin
.
Ecco un riepilogo del JavaScript utilizzato per eseguire questo attacco:
XSSI, noto anche come Cross-Site Script Inclusion, è un tipo di vulnerabilità che sfrutta il fatto che la Same Origin Policy (SOP) non si applica quando si includono risorse utilizzando il tag script. Questo perché gli script devono poter essere inclusi da domini diversi. Questa vulnerabilità consente a un attaccante di accedere e leggere qualsiasi contenuto che è stato incluso utilizzando il tag script.
Questa vulnerabilità diventa particolarmente significativa quando si tratta di JavaScript dinamico o JSONP (JSON con Padding), specialmente quando vengono utilizzate informazioni di autorità ambientale come i cookie per l'autenticazione. Quando si richiede una risorsa da un host diverso, i cookie vengono inclusi, rendendoli accessibili all'attaccante.
Per comprendere meglio e mitigare questa vulnerabilità, puoi utilizzare il plugin BurpSuite disponibile su https://github.com/kapytein/jsonp. Questo plugin può aiutare a identificare e affrontare potenziali vulnerabilità XSSI nelle tue applicazioni web.
Leggi di più sui diversi tipi di XSSI e su come sfruttarli qui.
Prova ad aggiungere un callback
parameter nella richiesta. Forse la pagina è stata preparata per inviare i dati come JSONP. In tal caso, la pagina restituirà i dati con Content-Type: application/javascript
, il che bypasserà la politica CORS.
Un modo per bypassare la restrizione Access-Control-Allow-Origin
è richiedere a un'applicazione web di effettuare una richiesta per tuo conto e restituire la risposta. Tuttavia, in questo scenario, le credenziali della vittima finale non verranno inviate poiché la richiesta viene effettuata a un dominio diverso.
CORS-escape: Questo strumento fornisce un proxy che inoltra la tua richiesta insieme ai suoi header, mentre falsifica anche l'header Origin per corrispondere al dominio richiesto. Questo bypassa efficacemente la politica CORS. Ecco un esempio di utilizzo con XMLHttpRequest:
simple-cors-escape: Questo strumento offre un approccio alternativo per il proxy delle richieste. Invece di passare la tua richiesta così com'è, il server effettua la propria richiesta con i parametri specificati.
Puoi bypassare i controlli CORS come e.origin === window.origin
creando un iframe e da esso aprendo una nuova finestra. Maggiori informazioni nella pagina seguente:
Il DNS rebinding tramite TTL è una tecnica utilizzata per bypassare alcune misure di sicurezza manipolando i record DNS. Ecco come funziona:
L'attaccante crea una pagina web e fa accedere la vittima ad essa.
L'attaccante quindi cambia il DNS (IP) del proprio dominio per puntare alla pagina web della vittima.
Il browser della vittima memorizza nella cache la risposta DNS, che può avere un valore TTL (Time to Live) che indica per quanto tempo il record DNS dovrebbe essere considerato valido.
Quando il TTL scade, il browser della vittima effettua una nuova richiesta DNS, consentendo all'attaccante di eseguire codice JavaScript sulla pagina della vittima.
Mantenendo il controllo sull'IP della vittima, l'attaccante può raccogliere informazioni dalla vittima senza inviare cookie al server della vittima.
È importante notare che i browser hanno meccanismi di caching che possono impedire l'abuso immediato di questa tecnica, anche con valori TTL bassi.
Il DNS rebinding può essere utile per bypassare controlli espliciti dell'IP eseguiti dalla vittima o per scenari in cui un utente o un bot rimane sulla stessa pagina per un lungo periodo, consentendo alla cache di scadere.
Se hai bisogno di un modo rapido per abusare del DNS rebinding, puoi utilizzare servizi come https://lock.cmpxchg8b.com/rebinder.html.
Per eseguire il tuo server DNS rebinding, puoi utilizzare strumenti come DNSrebinder (https://github.com/mogwailabs/DNSrebinder). Questo comporta l'esposizione della tua porta locale 53/udp, la creazione di un record A che punta ad essa (ad es., ns.example.com) e la creazione di un record NS che punta al sottodominio A precedentemente creato (ad es., ns.example.com). Qualsiasi sottodominio del sottodominio ns.example.com verrà quindi risolto dal tuo host.
Puoi anche esplorare un server pubblico in esecuzione su http://rebind.it/singularity.html per una comprensione e sperimentazione ulteriori.
Il DNS rebinding tramite DNS cache flooding è un'altra tecnica utilizzata per bypassare il meccanismo di caching dei browser e forzare una seconda richiesta DNS. Ecco come funziona:
Inizialmente, quando la vittima effettua una richiesta DNS, viene risposto con l'indirizzo IP dell'attaccante.
Per bypassare la difesa di caching, l'attaccante sfrutta un service worker. Il service worker inonda la cache DNS, il che effettivamente elimina il nome del server dell'attaccante memorizzato nella cache.
Quando il browser della vittima effettua una seconda richiesta DNS, ora riceve come risposta l'indirizzo IP 127.0.0.1, che di solito si riferisce al localhost.
Inondando la cache DNS con il service worker, l'attaccante può manipolare il processo di risoluzione DNS e costringere il browser della vittima a effettuare una seconda richiesta, questa volta risolvendo all'indirizzo IP desiderato dall'attaccante.
Un altro modo per bypassare la difesa di caching è utilizzare più indirizzi IP per lo stesso sottodominio nel provider DNS. Ecco come funziona:
L'attaccante imposta due record A (o un singolo record A con due IP) per lo stesso sottodominio nel provider DNS.
Quando un browser controlla questi record, riceve entrambi gli indirizzi IP.
Se il browser decide di utilizzare prima l'indirizzo IP dell'attaccante, l'attaccante può servire un payload che esegue richieste HTTP allo stesso dominio.
Tuttavia, una volta che l'attaccante ottiene l'indirizzo IP della vittima, smettono di rispondere al browser della vittima.
Il browser della vittima, rendendosi conto che il dominio non risponde, passa a utilizzare il secondo indirizzo IP fornito.
Accedendo al secondo indirizzo IP, il browser bypassa la Same Origin Policy (SOP), consentendo all'attaccante di abusare di questo e raccogliere ed esfiltrare informazioni.
Questa tecnica sfrutta il comportamento dei browser quando vengono forniti più indirizzi IP per un dominio. Controllando strategicamente le risposte e manipolando la scelta dell'indirizzo IP del browser, un attaccante può sfruttare la SOP e accedere alle informazioni dalla vittima.
Nota che per accedere a localhost dovresti provare a riassociare 127.0.0.1 in Windows e 0.0.0.0 in Linux. Provider come godaddy o cloudflare non mi hanno permesso di utilizzare l'IP 0.0.0.0, ma AWS route53 mi ha permesso di creare un record A con 2 IP, uno dei quali è "0.0.0.0"
Per ulteriori informazioni puoi controllare https://unit42.paloaltonetworks.com/dns-rebinding/
Se gli IP interni non sono consentiti, potrebbero dimenticare di vietare 0.0.0.0 (funziona su Linux e Mac)
Se gli IP interni non sono consentiti, rispondere con un CNAME a localhost (funziona su Linux e Mac)
Se gli IP interni non sono consentiti come risposte DNS, puoi rispondere con CNAME a servizi interni come www.corporate.internal.
Puoi trovare ulteriori informazioni sulle tecniche di bypass precedenti e su come utilizzare il seguente strumento nella conferenza Gerald Doussot - State of DNS Rebinding Attacks & Singularity of Origin - DEF CON 27 Conference.
Singularity of Origin
è uno strumento per eseguire attacchi di DNS rebinding. Include i componenti necessari per riassociare l'indirizzo IP del nome DNS del server di attacco all'indirizzo IP della macchina target e per servire payload di attacco per sfruttare software vulnerabili sulla macchina target.
Utilizzare TLS nei servizi interni
Richiedere autenticazione per accedere ai dati
Validare l'header Host
https://wicg.github.io/private-network-access/: Proposta per inviare sempre una richiesta pre-flight quando i server pubblici vogliono accedere ai server interni
Fuzz possibili misconfigurazioni nelle politiche CORS
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)