XSS che esce dall'attributo JSON.parse e href

4

Ho un caso piuttosto complicato in cui tento di eseguire un attacco XSS memorizzato quando carico un file jpg con nome file dannoso.

Gli spazi bianchi vengono filtrati ma sembrano virgolette singole e doppie insieme a < > non sono filtrati Inoltre, slash / e backslash \ sembrano essere proibiti.

L'input controllato dall'utente è un nome di file; questo nome file viene prima passato a uno script js che crea dati JSON nel modo seguente (il nome file controllato dall'utente è rappresentato come INJECT_HERE).

<script>
var foo = JSON.parse('{"x":1,"id":"2","myarr":[{"x1":"1"}],"x2":[{"id1":3,"id2":"15","name":"INJECT_HERE","path":"\/uploads\/pics\/1\/INJECT_HERE","b":"1"}]}')
</script>

Quindi la variabile precedente viene utilizzata per passare l'input fornito dall'utente a un elemento HTML. Il nome del file (tramite foo.myarr.x2.name) viene passato a un attributo href (con vue-js e v-bind) e il risultato html è simile a questo:

<div href="https://localhost/INJECT_HERE" class="foobar"></div>

Come posso uscire da entrambi i contesti allo stesso tempo per eseguire un XSS memorizzato? È fattibile o provo qualcosa che non può essere fatto?

    
posta XII 31.05.2018 - 13:13
fonte

3 risposte

4

Non puoi farlo. Vue usa il DOM per impostare l'attributo href, quindi non è codificato dal server in un modo che potrebbe ingannare il parser HTML. È semplicemente impossibile impostare un attrib con il DOM in un modo che "scoppi" dell'attrib, o inizi un nuovo attributo come se avessi una sorgente HTML grezza; tutti i caratteri non validi saranno evitati logicamente, anche se i valori non elaborati negli strumenti dev lo fanno sembrare che l'attacco dovrebbe funzionare.

Se hai eseguito uno dei template sul server (forse nel tentativo di pre-rendering), allora è un problema, ma così com'è, sei al sicuro.

tieni presente che data: e javascript: urls potrebbero essere ancora un problema, ma probabilmente hai già ottenuto la protezione da tale configurazione, dato il tuo livello apparente di competenza.

EDIT: risposta al commento

considera una semplice pagina che usa il DOM per iniettare contenuti:

<html> 
   <a id=a href="#">xss</a>
   <script>a.href='"><script>alert(123)<\/script>';</script>
</html>

Se guardi gli strumenti dello sviluppatore ispeziona la visualizzazione, potresti vedere qualcosa di spaventoso come questo:

<a id="a" href=""><script>alert(123)</script>">xss</a>

Sembra che ci sia un tag <script> all'interno del tag <a> e, in effetti, se lo copi in una pagina vuota e lo guardi, avverrà. Tuttavia, non è in realtà un problema perché gli strumenti di sviluppo stanno giocando un trucco visivo. Il contenuto effettivo dell'elemento quando serializzato è più simile a questo:

<a id="a" href="&quot;&gt;&lt;script&gt;alert(123)&lt;/script&gt;">xss</a>

Questo è ciò che intendevo quando il DOM scappava automaticamente da qualsiasi contenuto arbitrario; Finché usi il DOM per impostare un attrib, non c'è modo di "sbaragliare" l'attrib con qualsiasi contenuto. Ciò non significa che un attributo con effetto collaterale, come onmouseover non può sbagliarti, solo che non puoi impostare onmouseover regolando un href .

Quel data: e javascript: url protocol è ben discusso altrove, ma tieni presente che è un modo per collegare a documenti di contenuto arbitrario ( data: ) e codice JS ( jacascript: ).

Ad esempio, entrambi questi avvisi "666" (segno della bestia) quando si fa clic:

Javascript: <a href=javascript:alert(666)>xss</a>

Dati: <a href=data:text/html,%3Cscript%3Ealert%28666%29%3C/script%3E>xss</a>

Entrambi possono essere utilizzati al posto di un URL http (s), quindi assicurati di proteggerti, specialmente javascript: perché non ha bisogno di una barra per rendere eseguibile il codice.

    
risposta data 31.05.2018 - 21:54
fonte
0

Se viene generata l'intera riga JSON.parse sul server (anziché, per esempio, chiamando JSON.parse su una variabile contenente il risultato di un XHR) e sono consentiti segni di virgolette singole e doppie (più ( ) e almeno uno di + - ; ) questo è facile. Il tuo contenuto è già stato valutato all'interno di un blocco di script, perché ti preoccupi di ciò che accade dopo lo script termina? Dovresti già aver eseguito il tuo carico utile da allora!

Un nome file di esempio, utilizzando + per la concatenazione di stringhe: badfile"'+alert('xss')+' Questo genererà una stringa JSON completamente senza senso (e non valida), ma non ti interessa; il tuo codice viene eseguito (due volte) quando il motore JS tenta di concatenare le stringhe, prima che anche JSON.parse venga chiamato!

<script>
var foo = JSON.parse('{"x":1,"id":"2","myarr":[{"x1":"1"}],"x2":[{"id1":3,"id2":"15","name":"badfile"'+alert('xss')+'","path":"\/uploads\/pics\/1\/badfile"'+alert('xss')+'","b":"1"}]}')
</script>
    
risposta data 31.05.2018 - 22:21
fonte
-1

Questo non sembra affatto possibile. Quando un file viene selezionato per il caricamento, rimane lì fino a quando non viene elaborato. Quindi, affinché JavaScript ottenga il nome file, deve prima selezionare l'input e ottenere il valore dell'attributo o textContent , che viene restituito come string . Pertanto, non puoi uscire da JSON.parse .

E, come hai detto nel commento, sta impostando l'attributo href aggiungendo all'URL di base. Pertanto, non puoi interrompere l'attributo href. Puoi solo modificare il valore dell'attributo href ma non modificare anche base_url .

Quindi, in questo caso particolare, non è possibile attivare XSS in ogni caso.

    
risposta data 31.05.2018 - 14:53
fonte

Leggi altre domande sui tag