È possibile sfruttare XSS nel seguente codice?
jQuery(window.location.hash)
Mi sembra che window.location.hash
inizi sempre con un hash #
, e il jQuery moderno interpreta sempre questo come un selettore ID. È corretto?
Patch 9521 e 11290 diversi anni fa tentano di mitigare questo problema, sebbene non pretenda di rimuovere completamente la possibilità di XSS. Ho eseguito in jQuery 2.x alcuni degli exploit che affermano che esistono ancora, ma sembra che non funzionino, quindi non posso assolutamente confermare e negare se il codice che hai fornito sia sufficiente da sfruttare.
Per quello che vale, è anche possibile che questo exploit si verifichi se fai qualcosa con l'oggetto jQuery. Supponiamo che tu abbia consentito ai clienti di inviare HTML e un cliente ha inviato quanto segue:
<div id="xss">alert('xss');<div>
E per qualche strana ragione hai il seguente codice sulla pagina che mostra questo codice HTML:
eval(jQuery(window.location.hash).text());
Un hash URL di #xss
causerebbe l'attivazione di un avviso.
Quindi posso confermare che è possibile, anche se sarebbe molto difficile sfruttare questo particolare modo senza scrivere il codice in modo specifico per essere vulnerabili.
Suggerirei di eseguire un controllo di convalida sul valore di window.location.hash
o di rimuovere i caratteri speciali prima di passarlo a jQuery()
, e come sempre riflettere su ciò che fai con l'oggetto jQuery.
Come dice la risposta di Goose, sembra che ci fossero alcune versioni precedenti di jQuery che erano vulnerabili a questo.
Poiché la funzione jQuery può convertire stringhe in elementi DOM come questo ...
$(‘<p>Something</p>’);
Se il tuo codice aveva:
$(location.hash);
E un utente malintenzionato ti ha causato l'accesso alla tua pagina con un URL appositamente predisposto che terminava con un frammento di hash come:
#p=<img src%3D/%20onerror%3Dalert(1)>
Quindi jQuery interpreterà l'hash come HTML, creerà gli elementi DOM necessari e nel processo eseguirà effettivamente qualsiasi gestore JS ad essi associato.
Le versioni future di jQuery sembrano aver mitigato questo dando la priorità ai selettori ID su HTML, quindi tutto ciò che inizia con un hash viene trattato come un selettore CSS, non come HTML.
Perché indovinare? Per prima cosa disinfettiamo con \ w, è così facile. Sembra piuttosto terrificante se hanno il controllo completo su quella linea jQuery anche se deve iniziare con un hash. Nelle parole del link 9521 collegato a Goose,
I guess the question is whether this is such a common bone-headed move that we need to prioritize an id selector over HTML for this case. I could be convinced.
e
However, I am not sure how we can generally protect against this. The hash symbol is just text, and the string is valid HTML. Users should not be passing untrusted input to $() that could contain script.
Quindi, secondo almeno uno sviluppatore di jQuery, questa non è nemmeno considerata una vulnerabilità - E vuole lasciare al programmatore di non farlo. Anche se non lo aggiungi ora, un manutentore successivo probabilmente lo noterà e aggiungerà window.location.hash.replace(/[^\w]/g, "")
. (Oppure [^\w-]
se usi trattini). Nulla è veramente salvato evitandolo. Certo che possono mitigarlo, ma non avrei questa attitudine a essere la forza trainante della tua sicurezza web.
Il mio go-to per l'input dell'utente è un file JS speciale nella parte superiore che gestisce tutti gli input disinfettanti e memorizza cose come window.location.hash in una variabile "UserHash" che è già sterilizzata, con sanificazione documentata in modo che gli altri sappiano cosa possono assumere. Ho scoperto che non farlo in seguito porterà inevitabilmente a vulnerabilità in seguito. Qualcuno penserà "Oh, qui è al sicuro, quindi sarà al sicuro qui", lasciando le cose ai margini della semisafety che cadono in una vulnerabilità reale.