In che modo lo stesso criterio di origine causa il fallimento del PoC quando non è necessario leggere i dati di restituzione?

3

Sto eseguendo un'analisi di vulnerabilità autorizzata su un servizio Web personalizzato e ho scoperto una vulnerabilità CSRF.

Dato che non ci sono token di forma accoppiati con il servizio che non verifica l'intestazione di origine, credevo di poter falsificare richieste tramite i POST AJAX da una pagina di prova di "infetti".

A causa del modo in cui il server web mantiene lo stato richiede una serie di sei POST sequenziali per completare il mio attacco. Ecco il problema:

Il mio primo PoC comportava la creazione di sei semplici pagine html (ognuna con un modulo) che avrei caricato e inviato una per una, nell'ordine, per convalidare le mie ipotesi. Questo ha funzionato bene, quindi ho convertito queste azioni modulo in POST AJAX sequenziali. Il mio attacco ha smesso di funzionare a questo punto. Ho confrontato le richieste HTTP effettive sia per il contenuto che per l'ordine: tutte le corrispondenze dei dati del livello applicazione.

Sono diventato sospettoso della stessa politica di origine per qualche ragione nonostante NON abbia bisogno di leggere alcun dato di ritorno, quindi ho avviato Chrome con l'opzione --disable-web-security (per disabilitare la policy), ho provato di nuovo il mio attacco, e questo tempo è riuscito. Sembra che la stessa politica di origine stia in qualche modo impedendo il mio attacco, ma non ho idea del perché non ho bisogno di leggere alcun dato restituito. Cosa non sto comprendendo? A cosa non ho pensato? C'è un modo per realizzare ciò che voglio fare?

    
posta Ryan 17.10.2014 - 04:30
fonte

3 risposte

2

Non c'è motivo per cui questo non dovrebbe funzionare finché i cookie di terze parti sono abilitati nel tuo browser.

È possibile utilizzare i POST in formato HTML oppure, nel caso in cui i moduli siano un processo a più stadi, sarà più utile eseguire come richieste XHR, in quanto la pagina di attacco può quindi controllare le richieste e rilasciarle a turno - solo come stai facendo.

Assicurati di impostare withCredentials sulle tue richieste AJAX.

In jQuery questo è fatto come il seguente

$.ajax({
  type: "POST",
    url: 'http://www.example.com/Controller/Action',
    data: 'foo=bar',
    async: true,
    xhrFields: {
      withCredentials: true
   }
});

Altre risposte suggeriscono che l'utilizzo di withCredentials significa che una CORS richiesta pre-volo viene inviata al risorsa al posto del GET o POST previsto. Questo non è il caso finché la richiesta è una "richiesta semplice". Se il tuo exploit ha funzionato con i moduli HTML, l'equivalente AJAX corretto sarebbe una richiesta semplice, quindi controlla che tutto il codice sia corretto.

Cross-origin requests come in two flavors:

  • simple requests
  • "not-so-simple requests" (a term I just made up)

Simple requests are requests that meet the following criteria:

  • HTTP Method matches (case-sensitive) one of:

    • HEAD
    • GET
    • POST
  • HTTP Headers matches (case-insensitive):
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type, but only if the value is one of:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

Simple requests are characterized as such because they can already be made from a browser without using CORS.

Questo è effettivamente menzionato nella specifica CORS e indica che CORS in realtà non aggiunge sicurezza, ma abilita solo il cross -la comunicazione di dominio quando sia il client che il server optano per la specifica. Se entrambe le parti non aderiscono (come in un attacco CSRF in cui il sito della vittima non desidera essere comunicato in questo modo), il browser agirà in modo simile a pre-CORS. i cookie verranno inviati sebbene la risposta non sia leggibile:

resources conforming to this specification must always be prepared to expect simple cross-origin requests with credentials. Because of this, resources for which simple requests have significance other than retrieval must protect themselves from Cross-Site Request Forgery (CSRF) by requiring the inclusion of an unguessable token in the explicitly provided content of the request.

Torna alla tua domanda:

I compared the actual HTTP requests for both content and order - all of the application layer data matches.

Suggerisco di utilizzare un proxy di intercettazione come Burp o Fiddler2 per verificare le richieste. Controllare le richieste dall'interno del browser non è un modo accurato per verificare ciò perché le richieste visualizzate in Chrome sono soggette a essere interpretate dall'origine della pagina da cui provengono e se l'origine non vede la risposta dovuta allo stesso Politica sull'origine, quindi neanche in strumenti di sviluppo. Chrome ti informa di ciò tramite il messaggio “CAUTION: provisional headers are shown” .

Ad esempio, la seguente è la stessa richiesta mostrata negli strumenti di sviluppo di Chrome e poi in Burp. Nota come solo lo strumento esterno mostra i cookie.

Ho testato questo comportamento con Chrome 38, Firefox 32 e Internet Explorer 11 su Windows 7 x64, ed è coerente tra i browser (tuttavia, assicurati che i cookie di terze parti siano abilitati nelle impostazioni) quindi questa è un'ulteriore indicazione che questo il comportamento è conforme agli standard attuali.

Quindi il mio consiglio è di ricontrollare il codice e le richieste usando un proxy di intercettazione. Forse pubblicale qui per un altro paio di occhi per verificare come funziona in un modo, ma non l'altro, quindi ci deve essere un errore da qualche parte perché le richieste non saranno le stesse.

Inoltre, assicurati che il tuo codice non stia uscendo presto a causa dell'errore restituito a causa della violazione della stessa politica di origine.

    
risposta data 19.10.2014 - 11:29
fonte
0

Prova a cogliere l'errore senza niente. L'errore SOP genera un'eccezione, che interrompe l'esecuzione dello script. Se invece si cattura l'errore, la richiesta verrà respinta, la risposta verrà filtrata, verrà generata un'eccezione che verrà catturata e lo script continuerà con la richiesta successiva.

Quindi in pratica, ora funziona così:

attackstep1() << script stop here due to a exception, thus only step1 of attack is performed
attackstep2()
attackstep3()
.....

Invece, prova qualcosa del genere:

try {
attackstep1()
}
Catch(e) {}
try {
attackstep2()
}
Catch(e) {}
try {
attackstep3()
}
Catch(e) {}
try {
....
}
Catch(e) {}

Questo ignorerà l'errore di autorizzazione SOP e continuerà l'esecuzione dello script. Nota che non avrai accesso a nessuna risorsa che la risorsa protetta restituisce.

    
risposta data 17.10.2014 - 05:43
fonte
0

Il messaggio di errore che hai ricevuto è perché Condivisione di risorse tra origini (CORS) non è abilitato sul server si tenta di attaccare. Quindi tutte le tue richieste AJAX non saranno accettate dal server che ospita i servizi web.

Quindi, se abiliti CORS sul tuo server di destinazione, il server accetterà le tue richieste AJAX. Non utilizzare AJAX poiché se CORS non è abilitato la richiesta verrà rifiutata. Puoi usare curl un bel tool a linea di comando che può chiamare servizi web.

    
risposta data 17.10.2014 - 06:05
fonte

Leggi altre domande sui tag