XSS cheat sheet di PortSwigger
Pochi giorni fa è stata pubblicata la nuova versione di XSS cheat sheet aggiornata al 14 gennaio 2020. In questa nuova versione ho partecipato inserendo un'intera e nuova sezione dedicata a "WAF Bypass" sfruttando JavaScript global object.
Per chi non lo conoscesse, Cross-site scripting (XSS) cheat sheet di PortSwigger contiene numerosi payload per sfruttare vulnerabilità XSS (sia stored che reflected e sia che si tratti di server side o DOM based) ma soprattuto per evadere filtri o regole di web application firewall. Ogni vettore di attacco ha il suo relativo PoC, oltre che alla descrizione e un esempio di sintassi URL-decoded.
Parte dei payload che ho inserito nella nuova sezione del XSS cheat sheet lo avevo già pubblicato sul nostro canale YouTube e su un articolo su secjuice Bypass XSS filters using JavaScript global variables. Ciò che manca, e che descriverò in questo articolo, sono alcune tecniche basate principalmente su diverse tipologie di character encoding e sulla proprietà source
di RegExp .
Come abbiamo visto nel video, quando parliamo di bypass di regole di un application firewall, la maggior parte dei casi sono tecniche che rientrano in 4 principali categorie: string concatenation, character encoding, escape sequence e comments. Relativamente al character encoding, JavaScript (come altri linguaggi) permette di utilizzare sequenze di escape per rappresentare sepcifici caratteri. Ad esempio sotto forma di octal escape sequences. Qualsiasi carattere con codice inferiore a 256
(extended ASCII range) può essere rappresentato tramite sequenza di escape come \nnn
. Stesso discorso vale per sequenze di escape esadecimale (\xnn
)
Ad esempio, il simbolo di copyright '©'
(character code 169
), che in base-8 è 251
e in base-16 è A9
. Questo significa che in JavaScript potrò rappresentare il simbolo di copyright con le seguentu sequenze di escape:
\251
(octal)\xa9
(hex)
Tutto ciò ci permette di bypassare facilmente filtri basati su black-list di parole. Può sembrare strano, ma alcuni application firewall implementano regole per mitigare XSS che si basano esclusivamente su blacklist di stringhe come "document" o "document.cookie". In questo caso potremmo bypassare i filtri selezionando l'oggetto document dal global object window
e selezionare l'oggetto cookie
dal relativo window[document]
senza aver bisogno di inviare le stringhe "document" e "cookie" all'interno dell'input.
Octal escape:
document = \144\157\143\165\155\145\156\164
cookie = \143\157\157\153\151\145
window['\144\157\143\165\155\145\156\164']['\143\157\157\153\151\145']
Hex escape:
document = \x64\x6f\x63\x75\x6d\x65\x6e\x74
cookie = \x63\x6f\x6f\x6b\x69\x65
window['\x64\x6f\x63\x75\x6d\x65\x6e\x74']['\x63\x6f\x6f\x6b\x69\x65']
Stesso discorso, ma con diversa sintassi, per quanto riguarda unicode escape sequence che prevedono una sequenza come \u{5-hex}
.
Unicode escpae
document = \u{64}\u{6f}\u{63}\u{75}\u{6d}\u{65}\u{6e}\u{74}
cookie = '\u{63}\u{6f}\u{6f}\u{6b}\u{69}\u{65}'
window['\u{64}\u{6f}\u{63}\u{75}\u{6d}\u{65}\u{6e}\u{74}']['\u{63}\u{6f}\u{6f}\u{6b}\u{69}\u{65}']
RegExp.prototype.source
La propietà source
di un oggetto RegExp restituisce una stringa contenente il testo sorgente delle regular expression (esclusi i delimiter /
).
Thesource
property returns aString
containing the source text of the regexp object, and it doesn't contain the two forward slashes on both sides and any flags. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source
Posso sfruttare questa proprietà per specificare stringhe di testo senza utilizzare caratteri double e single quote all'interno dell'input che potrebbero essere bloccati o sanitizzati dall'applicazione o da un application firewall. Per seguire gli esempi precedenti:
Reference
- https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
- https://www.secjuice.com/bypass-xss-filters-using-javascript-global-variables/
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source