Attenuazione dell'XSS riflesso nelle richieste di nodo / espresso per le risorse statiche

2

L'ho chiesto su Stack Overflow perché è correlato a un problema di programmazione (come mititgate le vulnerabilità nel codice) ma ho alcune domande più ampie e una mancanza di comprensione su come mitigare la vulnerabilità. Si prega di notare la sezione di aggiornamento qui sotto dove ho messo in atto le attenuazioni in queste domande collegate qui e qui .

Ho eseguito uno strumento di test della penna (Burp) contro il mio nodo (espresso) / applicazione angolare e identificato una vulnerabilità XSS riflessa in particolare quando si tenta una richiesta di GET di risorse statiche (non sono state rilevate vulnerabilità per nessuno dei le richieste che vengono fatte quando un utente interagisce con l'applicazione).

I dettagli del problema sono:

The name of an arbitrarily supplied URL parameter is copied into a JavaScript expression which is not encapsulated in any quotation marks. The payload 41b68(a)184a9=1 was submitted in the name of an arbitrarily supplied URL parameter. This input was echoed unmodified in the application's response.

This behavior demonstrates that it is possible to inject JavaScript commands into the returned document. An attempt was made to identify a full proof-of-concept attack for injecting arbitrary JavaScript but this was not successful. You should manually examine the application's behavior and attempt to identify any unusual input validation or other obstacles that may be in place.

La vulnerabilità è stata testata passando un parametro url arbitrario alla richiesta in questo modo:

GET /images/?41b68(a)184a9=1

La risposta è stata:

HTTP/1.1 404 Not Found
X-Content-Security-Policy: connect-src 'self'; default-src 'self'; font-src 'self'; frame-src; img-src 'self' *.google-analytics.com; media-src; object-src; script-src 'self' 'unsafe-eval' *.google-analytics.com; style-src 'self' 'unsafe-inline'
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Strict-Transport-Security: max-age=10886400; includeSubDomains; preload
X-Download-Options: noopen
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Content-Length: 52
Date: Wed, 08 Oct 2015 10:46:43 GMT
Connection: close

Cannot GET /images/?41b68(a)184a9=1

Puoi vedere che ho CSP in posizione (usando Helmet per implementare) e altre protezioni contro gli exploit. L'app viene pubblicata su https, ma non è richiesta alcuna autorizzazione dell'utente. CSP limita le richieste dal dominio dell'app e da Google Analytics.

Il rapporto sul test della penna suggerisce l'input di validazione (lo sono, ma sicuramente farebbe richieste che includono dati inviati da un utente non sicuro se non lo fossi?), e la codifica html quale angolare fa per impostazione predefinita, più gli URL di richiesta GET sono sfuggito (vedi aggiornamento sotto).

Sto davvero lottando per trovare una soluzione per prevenire o mitigare questo per quelle richieste di risorse statiche:

  • Devo autorizzare tutte le richieste per la mia applicazione in csp?
  • Posso farlo anche solo o farò solo i domini nella whitelist?
  • Può / dovrebbe tutte le risposte dal nodo / espresso alle richieste di risorse statiche essere codificate in qualche modo (vedere l'aggiornamento sull'URL che si sta eseguendo in seguito)?
  • Il rapporto afferma che "Il nome di un parametro URL fornito arbitrariamente viene copiato in un'espressione JavaScript che non è incapsulato in virgolette ". Questa espressione potrebbe trovarsi da qualche parte nel codice espresso che gestisce la restituzione di asset statici?
  • Oppure che il parametro di richiesta GET può essere valutato in qualche modo nel mio codice applicazione?

Aggiornamento

Avendo svolto alcune indagini su questo, sembra che almeno una parte della mitigazione sia quella di escape data in url param values e sanitizza l'input nel URL.

L'escape dell'URL è già presente, quindi:

curl 'http://mydomain/images/?<script>alert('hello')</script>'

ritorna

Cannot GET /images/?&lt;script&gt;alert(hello)&lt;/script&gt;

Ho anche inserito express-sanitized in cima a questo.

Tuttavia, se applico il test originale, il parametro della richiesta viene comunque riflesso.

curl 'http://mydomain/images/?41b68(a)184a9=1'
Cannot GET /images/?41b68(a)184a9=1

Che ti aspetteresti perché HTML non viene inserito nell'URL.

Le risposte alle richieste GET per le risorse statiche sono tutte gestite da app.use(express.static('static-dir')) , quindi la query viene passata a questo. express.static è basato su serve-static che dipende da parseURL .

    
posta br3w5 12.10.2015 - 10:39
fonte

1 risposta

0

La causa del problema è che per le richieste GET non valide express verrà restituito qualcosa come:

Cannot GET /pathname/?yourQueryString

Che in molti casi è una risposta valida, anche per il servizio di asset statici. Tuttavia, nel mio caso e sono sicuro che per gli altri le uniche richieste valide per le risorse statiche saranno qualcosa del tipo:

GET /pathname/your-file.jpg

Ho un gestore 404 personalizzato che restituisce un oggetto dati:

var data = {
    status: 404,
    message: 'Not Found',
    description: description,
    url: req.url
}; 

Viene gestito solo per richieste di modelli non valide in app.js con:

app.use('/template-path/*', function(req, res, next) {
    custom404.send404(req, res);
});

Ora ho aggiunto gestori espliciti per le richieste alle cartelle statiche:

app.use('/static-path/*', function(req, res, next) {
        custom404.send404(req, res);
});

Opzionalmente, potrei anche eliminare i parametri di richiesta della richiesta prima che venga restituito il 404:

var data = {
    status: 404,
    message: 'Not Found',
    description: description,
    url: url.parse(req.url).pathname // needs a var url = require('url')
};
    
risposta data 12.10.2015 - 11:43
fonte

Leggi altre domande sui tag