La politica di sicurezza del contenuto è applicata solo durante il rendering iniziale?

8

Il CSP viene applicato solo durante il rendering iniziale, ovvero non esiste una copertura continua dopo il caricamento del documento? Ecco un esempio di ciò di cui sto parlando:

Diciamo che la tua pagina, example.com , ha qualche JS che prende il parametro url name e lo mostra nella pagina:

<script nonce="test123">
$(document).ready(function() {
    $("#id").html(nameParameterTakenFromURLWithoutSanitation);
});
</script>

Se qualcuno visita example.com?name=<script>alert('XSS');</script> , in base ai miei test, lo script verrà comunque eseguito (facendo apparire l'avviso) indipendentemente dal CSP. Sono bloccati solo gli script illegali presenti all'interno della risposta iniziale del server.

Sto usando un approccio CSP "rigoroso" che usa nonce. Ecco la politica che sto utilizzando:

object-src 'none';
script-src 'nonce-test123' 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:;
report-uri http://localhost:8080/csp-collector

Perché lo script non è bloccato?

    
posta Andrew Schmitt 26.10.2016 - 21:13
fonte

3 risposte

10

Introduzione

CSP dovrebbe essere applicato dal browser fino a quando rimani sulla pagina, e non solo mentre è caricato o reso in origine. Tutto il resto lo renderebbe abbastanza sdolcinato.

Quindi il comportamento che stai riscontrando non ha nulla a che fare con quando lo script è caricato. Invece si tratta di cosa lo carica. Ci sono due problemi.

Problema 1: rigoroso-dinamico

Lascio che Mozilla lo spieghi:

The strict-dynamic directive specifies that the trust explicitly given to a script present in the markup, by accompanying it with a nonce or a hash, shall be propagated to all the scripts loaded by that root script.

Quindi, quando ti fidi di uno script dandogli un nonce, può a sua volta caricare altri script. Ciò significa che se hai una vulnerabilità DOM XSS in uno script con un nonce, il CSP non ti salverà. La soluzione è rimuovere 'strict-dynamic' (ma ciò sarà certamente problematico se ti affidi a questa funzione).

Problema 2: non sicuro-eval

Per caricare lo script, usi jQuery .html() . Da qualche parte nel codice sorgente jQuery (riga 343 per l'esattezza) fa una chiamata al buon vecchio eval() .

Quindi se esegui il codice

$(".test").html("<scr" + "ipt>alert('XSS');</scr" + "ipt>");

jQuery per qualche motivo (non chiedermi perché, ho provato e non sono riuscito a seguire il codice sorgente) esegui quanto segue:

eval("alert('XSS');");

Questo significa che il CSP non si applica più: dopo tutto non stai creando un nuovo tag script, stai valutando una stringa.

Qui la soluzione è rimuovere 'unsafe-eval' dal CSP, ma ciò interromperà jQuery. La soluzione potrebbe essere l'aggiornamento a jQuery 3, che su un'ispezione superficiale della sorgente sembra aver risolto questo problema.

Conclusione

Ciò significa che tutto il codice (utilizzando jQuery 2) nel modulo

x.html(unsafeFromURL);

può essere vulnerabile a XSS anche se è stato impostato un CSP . Penso che questo sia inaspettato per molte persone (era per me). Ma serve come promemoria di un altro punto importante: Non dovresti usare CSP come unica linea di difesa contro XSS .

Nota anche che questo non è un problema con il funzionamento di CSP, ma con il funzionamento di jQuery.

    
risposta data 26.10.2016 - 23:29
fonte
1

Il tuo esempio inizia disabilitando lo script inline di CSP e la protezione eval, che sono i suoi due principali controlli di sicurezza; in particolare quello in linea in quanto è il modo principale per prevenire XSS.

Quindi esegui uno script che scrive un tag <script> nella pagina, causandone l'inserimento nella pagina. Se avessi scritto manualmente lo stesso tag di script nella pagina tramite il codice lato server, avresti ottenuto lo stesso risultato. Il fatto che tu l'abbia fatto con JavaScript è per lo più irrilevante qui.

Disabilitando le funzionalità di protezione delle chiavi di CSP, hai rimosso tutta la protezione contro XSS, quindi hai ottenuto XSS.

    
risposta data 26.10.2016 - 23:18
fonte
0

Per rispondere al titolo della tua domanda: No, CSP viene applicato per tutta la durata del documento / risorsa HTML a meno che tu non entri in un URL completamente diverso.

Il motivo per cui il tuo script non è bloccato a causa della presenza di strict-dynamic sui browser che lo supportano e sui browser che non lo supportano unsafe-inline , non verrà bloccato.

Vediamo il caso dei browser che supportano strict-dynamic :

Lo scopo principale di strict-dynamic è eliminare la whitelist (che non è così sicura a causa di JSONP, ecc. Vedi qui ) e anche per consentire il caricamento dinamico di script che viene eseguito da molte API sul Web.

In sostanza, se si sta tagliando dinamicamente uno script creando un tag script, questo verrà bloccato se si utilizzano noces. Quindi, ciò che fa rigida-dinamica è se uno script che ha un nonce e quindi è considerato affidabile, è autorizzato a caricare script come questo (creazione di tag di script) in modo dinamico.

Quindi, nel tuo caso:

<script nonce="test123">
    $(document).ready(function() {
        $("#id").html(nameParameterTakenFromURLWithoutSanitation);
    });
</script>

Crea un tag script se il nameParameter è detto: <script>alert('XSS');</script> so per definizione di strict-dynamic che dovrebbe essere eseguito.

La preoccupazione principale qui per me è perché stai usando .html() ? Ti aspetti che il nome abbia qualche markup HTML? In caso contrario, utilizzare .text() che sfugge a qualsiasi markup HTML e quindi impedisce XSS.

    
risposta data 17.11.2016 - 07:24
fonte

Leggi altre domande sui tag