In jQuery puoi specificare un selettore CSS e un codice HTML con la stessa stenografia.
Questo è un selettore:
$('#some-thing')
Questo è HTML che viene valutato immediatamente:
$('<svg onload=alert(1)>')
Questo è un esempio di codice reale per l'analisi di un selettore dall'hash della posizione (la parte URL dopo un #
):
var x = $('#' + window.location.hash.substr(1));
x.addClass('highlighted').find('div').show();
È preso da questa domanda e un approccio simile è (pericolosamente) consigliato in questo SO thread .
Vedi il problema con esso? L'intento dell'autore era quello di consentire un selettore CSS controllato dall'utente, ma se si apre il sito interessato come https://example.com/#<svg onload=alert(1)>
, si finisce con questo selettore ambiguo:
$('#<svg onload=alert(1)>');
Le versioni precedenti di jQuery eseguono questo come codice HTML e creano quindi un difetto XSS poiché il gestore di eventi JS viene eseguito immediatamente dopo la creazione del nodo DOM. Tuttavia, le versioni più recenti decidono che una stringa che non inizia con una parentesi angolare deve essere analizzata come un selettore, attenuando così il difetto.
Da i documenti :
If a string is passed as the parameter to $()
, jQuery examines the string to see if it looks like HTML (i.e., it starts with <tag ... >
). If not, the string is interpreted as a selector expression, as explained above. But if the string appears to be an HTML snippet, jQuery attempts to create new DOM elements as described by the HTML.
Puoi leggere come questo comportamento è stato modificato nella discussione su bug # 9521 .
La pagina che hai collegato prende nota del tipo di selettore di ciascuna versione vulnerabile.