Gayet normal geçen bir Perşembe gecesiydi. “Searching” diye muazzam bir film izlemiştim. Allak bullak olan beynim biraz rahatlasın diye elime telefonu aldım. Telegram’a girip her zamanki gibi ParrotSec grubuna baktım ve gelen o link tam bir günüme mal oldu…

https://alf.nu/alert1 sayfası beni yer yer kanser etti, yer yer eğlendirdi. Baktım az biraz çözebildim, hemen yeni bloguma ilk yazımı yazayım dedim.

Not: Bu challenge cidden öğretici oldu. Okumadan önce kendiniz çözmenizi tavsiye ederim.

Buyrun, başlayalım.

 

LEVEL-1

Linke tıklayınca hemen mevzuya girmiş oluyoruz. Bizi böyle bir ekran karşılıyor. Bu egzersizlerin genel mantığı kaynak koda göre alert(1) içeren bir XSS payloadı yazabilmek.
Şimdi kaynak kodu inceliyoruz.

Level-1 olduğu için soru biraz kolay açıkçası. Herhangi bir filtrelemeye maruz bırakılmıyoruz.
console.log() fonksiyonunu bitirip alert(1) ekleyerek, daha sonrasında da açıkta kalan parantez ve tırnağı kapatarak bu soruyu tamamlayabiliriz.

LEVEL-2

Evet yavaştan filtreleme mevzularına başlıyoruz.

 

Kaynak kodu incelersek verdiğimizde replace() fonksiyonu input girdiğimiz her işaretini \” şeklinde değiştirmektedir.
Bu filtrelemeyi aşmak için de input olarak bir \ işareti girip devamında da koyarak yine console.log() fonksiyonu dışına çıkabiliriz. Sonrasında da yine <script> tag’i içerisinde olduğumuzdan alert basıp geri kalanı yoruma atarak soruyu çözebiliriz.

LEVEL-3

JSON.stringify() fonksiyonu ile ilk kez karşılaştım. Ne olduğunu gugılladığımda bu fonksiyonun aldığı değerleri JSON formatına çevirdiğini öğrendim. Pek anlam veremedim bu aşamada açıkçası fonksiyonun bu sorudaki işlevine. BugBounty’ci kardeşlerim bilirler biraz deneme yanılmadan kimseye zarar gelmez.

Ne deneyebilirim diye düşündüğümde yine önceki soruda olduğu şekilde başlamak geldi aklıma. Output kısmından gözlemleyebildiğimiz için bu şekilde içinden çıkarak çözmek kolay oluyor. Önce yine “\) ile içerisinden kaçtım. Sonra baktım ki bir <script> tag’i içerisindeyiz. </script> tag’ini sonlandırdım. Sonrasında da yeni bir <script> tag’i açarak içerisine alert(1) yerleştirdim. Kalan kısmı da yoruma aldım. Zaten ilk baştan beridir </script> elimizde vardı. Hal böyle olunca alert geldi.

\")</script><script>alert(1)//

Ama anlamadan çözmüştüm. Halen daha JSON.stringify() fonksiyonu ne işe yarar anlamamıştım. Biraz daha araştırdığımda bu fonksiyonun benim girdiğim her şeyi JSON datasına çevirdiğini fakat bazı özel karakterlere denk geldiğinde bu fonksiyondan kaçılabildiğini öğrendim. Burada kaçmamızı sağlayan karakter < oldu. Bu sayede soruyu aslında uzattığımı da öğrenmiş oldum. < karakterinden öncesinin bu durumda anlamsız kaldığını öğrenince payloadı değiştirdim. Fakat yine mantık değişmedi ben kaçmak için zaten < işareti kullandığımdan bu <script> tag’ini kapatarak yoluma önceki payloaddaki gibi devam ettim ve yine alert alabildim.

 

LEVEL-4

Bu soruyu öncekine göre kolay buldum.

Verilerin url’e çevrildiğini fark ettiğimde aklıma url encoding geldi.  filtrelense bile url encoding yapıldığında  işaretine karşılık gelen %22 olarak girdiğimde filtrelemeyi bypass edebileceğimi düşündüm. Ki öyle de oldu, alert geldi.

 

LEVEL-5

Soruyu gördüm ve önümü ilikleyerek incelemeye başladım.

 veya %22 ile atlatabileceğimiz bir yer bile yok şu an. Kaynak koda dikkatli baktığımızda bizden istenen input şekli belli oluyor aslında. Bizden [[x|y]] formatında input bekleniyor. Bu gelen inputların yorumlanışı ise şu şekilde oluyor.

input: [[x|y]]

output: <img alt=”y” src=”x.gif”>

Yani köşeli parantezler arasında girdiğimiz ilk değer <img> tag’inin src attribute değeri oluyor, ikincisi de alt attribute değeri oluyor.
O zaman biraz daha inceleyelim.
src attribute değeri için http:// şeklinde bir input girdiğim anda <a href=”http://”> şeklinde bir link yönlendirmesi yapıyor (Bahsettiklerimi output ve iframe kısımlarından gözlemleyebilirsiniz.).

Şimdi http:// şeklinde başlayıp bunu bir event ile devam ettirebilirsek alert alabiliriz. Link yönlendirmemiz çalıştığı zaman kaynak olmadığı için hata vereceğinden, bizim burada onerror event‘ini kullanarak bu hatayı fırsata çevirmemiz gerekiyor.

Payloadımızın bu kısmının normal şartlarda [[x|http://onerror=alert(1)]]  şekilde oluşması gerekirken, output kısmında gözlemlersek input formatımızdan kalan iki tane köşeli parantez bize sıkıntı çıkartıyor. Sıkıntı sever miyiz? Hayır. Sıkıntı görünce atar yoruma geçeriz. Hop aldık alert‘ı. Payloadımızın son hali aşağıdaki gibidir.

 

LEVEL-6

Soruyu anlayabilmem bile çok vaktimi aldı. Neyse ki soruda yorum satırı olarak biraz hint verilmişti de çözebildim.

Şimdi bizden bu soruyu çözebilmek için önce istenen şey her durumda kaçabilecek bir TextNode ile başlayıp devamında işareti ile mevzuya dalmak. foo kelimesi zaten random kelime.
Kaynak kodu incelediğimde document ve create kelimeleri özellikle dikkatimi çekti. Soru başlığı olan DOM ile de alaka kurmayı deneyince document.create() şeklinde başlayan bir fonksiyon olabileceğini tahmin ettim. Biraz gugıllayınca muazzam bir sonuca ulaştım. document.createComment() şeklinde bir fonksiyon kullanabilirdim. Yorum olduğu için de tüm karakterlerden kaçmış oluyordum. Zaten benden istenen sadece TextNode ismi olan Create‘i bulmaktı. E soruyu çözdük o zaman.

TextNode# formatına göre paydloadımıza Comment# ile başlarsak output kısmındaki değişimi görebiliriz. Buradan sonrası çok kolay, yapmamız gereken sadece tag’ler ile oynayıp comment içerisinden kaçarak alert almak olacak.
Bunun için de önce > ile comment dışına çıkıyoruz. sonrasında <script> tag’leri arasında alert(1) vererek sorumuzu tamamlıyoruz.

 

LEVEL-7

Tam bu satıra başlarken ezan okundu. Ben de dinlediğim şarkıyı kapattım. Siz de buyrun, kafanız dağılsın azcık.

Neyse sorumuza dönelim.

Kaynak kodu yorumlamaya çalışarak başlayalım. Bizden callback#userdata şeklinde biz çözüm bekleniyor. Anlamadım napayım hemen biraz random bişeyler girip output kısmını inceledim.
ve harfler haricinde girdiğim her input bana invalid callback şeklinde response döndürdü. Neymiş ulan bu callback diyip biraz gugılladım, bişey anlamadım. Ayrıca # işaretiyle de output kısmında görülen JSON içerisine girebiliyordum.

Sonra dedim ki niye benden istedikleri formatta input veriyorum? Hem zaten onların istediği şekilde input verince JSON içinden çıkamayacağım. E hazır  da kullanabiliyorken, çalışıp çalışmayacağından emin olmayarak JSON ve parantezleri tırnak arasına almaya çalıştım.
Cümle çok karmaşık gelebilir burayı yavaş yavaş anlatıcam.

Öncelikle şunu biliyoruz ki # girmeden input olarak harf veya  haricinde bizi kaçırabilecek bir karakter giremiyoruz. Biz de tek tırnak kullanarak başlıyoruz.

Gördüğümüz gibi süslü parantezlerin içine giremedik. Süslü parantezler içerisine girebilmek için de soruda hint olarak da verilmiş olan # işaretini kullanıyoruz. Ve içerdeyiz.

Artık yapmamız gereken userdata olan kısım dahil olmak üzere o kısımdan komple kurtulmak. Bunun için de ben tekrardan tek tırnak koyma yolunu seçtim ve ({“userdata”:” kısmını normal bir string gibi kabul ettirdim. Altını çizdiğim kısım komple string oldu artık süslü parantez falan bizi ilgilendirmiyor.

Sorunun bu kısmına kadar olan süreç çok zorlayıcıydı. Buradan sonrası rahatlıkla çözülebilir. ; kullanarak önce bi orayı tamamlayalım. Devamında da asıl hedefimiz olan alert(1) ile tamamlayalım.

Gördüğünüz üzere son kısımda da parantez tırnak falan kaldı. Bize yine sıkıntı çıkaracak şeyler bunlar. Sıkıntı sevmediğimizden yoruma attık ve alert döndürebildik.

 

LEVEL-8

CTF’lerde denk geldiyseniz rahatça çözebileceğiniz bir soruya geldi sıra.

Kaynak kodu çok temiz ve basit. Girdiğimiz her şey büyük harfe dönüşüyor. Hal böyle olunca da tag’leri kapatıp kaçma olanağımız yok.
Biraz boş yere uğraştıktan sonra aklıma bir CTF’te de denk geldiğim JSFuck yazı stili geldi. Kısaca bahsetmek gerekirse sadece (, ), [, ], !, + karakterlerini kullanarak javascript kodu yazmaktır. Tabii ki bunun için converter uygulamalar bulunmaktadır. Ben bu siteyi kullanarak alert(1) yazdırdım.

Soruya dönecek olursak soruda çok basit bir şekilde, filtrelemeye de maruz kalmadan, önce “); ile log fonksiyonumuzdan çıkıyoruz. Devamında JSFuck’tan gelen alert(1)‘i ifade eden uzun karakter dizisiyle alert(1) yazdırıyoruz. Sonrası yine sıkıntı olacağından son kısmı da // ile yoruma atarak sorumuzu tamamlıyoruz.

CTF’te denk gelmemiş olsam JSFuck’ı bulmam gerçekten zor olabilirdi. Neyse, payloadımız da şöyle.

 

LEVEL-9

Çok karışık duruyor.

Kaynak kodundan fazla bi şey anlamayınca input verdim ne olacağını görmek için. Kaçabileceğimiz güzel bir yerdeyiz aslında. Buradan bir javascript event ile alert alabiliriz.

Output’a bakınca kaynak kodu daha iyi anlayabildim. , , &, <, > karakterleri filtrelenmiş. Bunları kullanamayacağımız belli. Kullanabileceğimiz işaretler arasında \ var.
Burada aklıma Level-7’de kullanmadığım fakat kaynak kodunu incelerken öğrendiğim bir özellik geldi.
Hatırlamak gerekirse level-7 kaynak kodunda şu satır vardı.

Altı çizili kısımdaki dönüşümü görünce araştırdım ve < işaretinin unicode karakter karşılığı \u003c şeklinde olduğunu gördüm.

Sorumuza dönersek \ işaretini kullanabildiğim için de bu yöntemle soruyu çözebiliriz.
Tag’leri nasıl yazabileceğimizi bulduğumuza göre yazmaya başlayalım.
Hangi payload ile alert alabiliriz önce onu tespit edersek sonrasında sadece < ve > işaretlerini unicode ederek soruyu çözeriz.
Yani soru çok basit aslında bu aşamada. Kompleks olmayan bir payload ile sayfaya bir resim enjekte edebiliriz.
Kaynak kod <a href=#> </a> şeklinde yazıldığı için bizden sadece sayfaya clear bi text yazmamız isteniyor. Çünkü <a> tag’leri arasında yazılanlar, href attribute değerinde belirtildiği adrese gidebilmek için sayfada üzerine tıklanacak yazı veya simgedir. Biz bu kısma bir resim de koyabiliriz. Frontend’ci kardeşlerim bu tarz şeyler yapıyorlar zaten. Bazen bir resme tıkladığımızda bir sayfaya gidiyoruz. Buraya kadar olan kısım HTML101.

Biz de burada resim koyar gibi yapıp kaynağı boş vereceğiz ve hata vereceğini bildiğimizden dolayı onerror eventi ile de alert alabileceğiz.
örnek olarak: <img src=x onerror=alert(1)> kullandım ben.

çok uzattım yukarıda hakkaten ama o kadar da yazdım, şimdi silmek istemiyorum.
neyse, payloadımız bu. alert aldık.

 

LEVEL-10

Baya sardı bu challenge’lar, kalkamıyorum başından. Sıradaki sorumuzla devam edelim.

Kaynak koda ilk baktığımda </script> tag’ini engellediğini düşünmüştüm. Output kısmında gözlemlediğimde ise garip bir şekilde </script şeklinde bir engelleme yapıyor. Engellenen tag tam kapanmış değil. Sondaki > işareti eksik.

Neyse sorunun çözümüne gelirsek iç içe <script> tag’leri yazmayı deneyebiliriz. Eğer çalışırsa iç kısımdaki tamamlanmamış <script filtrelenir ve dıştan gelen </script> tag’i ile soruyu kolayca cevaplayabiliriz. Tabii bunlar için önce “); şeklinde log() fonksiyonundan çıkıyoruz.

log() fonksiyonunu kapattım. İç içe </script> tag’i yazdım ve yeni bir <script> tagi açtım. Sorun çıkaran bazı karakterler oldu, bunlar hakkında da tüm anayasal haklarımı kullanarak yoruma atma hükmü verdim ve alert geldi. Burada dikkat etmemiz gereken nokta <script> tag’i açarken bir filtrelemeye uğramayışımız.

Aslında dikkat etmemiz gereken nokta o değildi ama güzel bir tespit olarak söylemek istedim. Neyse yine alert aldık sonuçta, payload şöyle.

 

LEVEL-11

Polat Alemdar’ın Halep’ten gelip Boğaz Köprüsünde Türk bayrağına baktığı gibi baktım soruya.

Öncekinin aynısı ulan bu dedim ve önceki gibi ‘#’alert(1) şeklinde input verdim. Son kısım yine sıkıntılı olduğundan yoruma atmaya çalıştım ki ne göreyim, // yapamıyorum. Çünkü / karakteri filtrelenmiş ve /\ şeklinde anlamsız ifadeler çıkıyor.
Sonra aklıma HTML dokümanlarında da geçen başka bir comment stili geldi. <!– kullanarak da kalan kısmı yoruma alabilirdim. Denedim ve alert geldi.

Neyse bu soruya da farklı bir yorum getirmiş olduk :DDDD mimimizah şov
Payloadın son hali aşağıdaki gibi oldu.

 

LEVEL-12

Yine bir uppercase vakası ile daha karşı karşıyayız.

Sorunun çözümü böyle mi olmalı bilmiyorum ama ben yine Level-8’deki çözümün aynısını yapıp JSFuck ile alert alabildim.

Payload:

 

LEVEL-13

İş çirkinleşmeye başladı.

Soru gerçekten inanılmaz karışık. Özellikle ilk yorum dikkatimi çekti. İlk yorumda “sandboxed” derken aslında iframe‘in kurallarına uymadan bir alert alamayacağımızı belirtiyor. İkinci yorumda belirttiği https://4i.am web sayfasında sayfa kaynağını incelediğimizde yorumda bir alert ve import edilmiş bir javascript dosyası var. Üçüncü yorum neden var çözemedim.

Kaynak koda bakmaya başlarsak bir iframe oluşturulmuş ve tag değişkenine atanmış. Yani buradan sonra tag.xxx şeklinde devam eden gördüğümüz her şey iframe üzerinde çalışıyor. Buna ilk örnek olarak tag.setAttribute() fonksiyonunda onload event‘i youWon ve alert(1) ile ilişkilendirilmiş.

Kaynak kodda yine dikkatimi çeken kısım window.WINNING() fonksiyonunda youWon = true olarak atanmış. Yani fonksiyon çağrıldığında youWon true dönüyor anladığım kadarıyla (vallahi developer’lık iddiam yok. alemci, neşeli bir delikanlıyım 🙁 yanlışsa taşlamayın). Neyse output nasıl geliyor önce ona bir bakalım.

Anladığım kadarıyla <script> tag’leri arasındayız. Benim için hiçbir anlam ifade etmedi bu. İçeriden kaçmaya çalıştım ama manası da yok çünkü bu iframe‘den çıkamam. Yani soru öyle dedi. Benim bu soruyu çözebilmem için bir yerlerde youWon kullanıp fonksiyonu true döndürebilmem gerekiyor. Aslında şu an bu satırları yazarken “ya bu soruyu çözemedim hani buraya kadar geldim çözebilen varsa bana da anlatsın” yazacakken aklıma değişik bir şey geldi.
Öncelikle şu alert ile ilgili olan fonksiyonu bi düzenleyelim.

yani bu iframe‘imizin adı youWon olursa bu fonksiyon çalışacak ve alert dönecek. Bunu nasıl yaparım diye az biraz gugılladım ve şöyle bir sonuca ulaştım.

<script> tagleri arasında ben window.name olarak youWon verdiğimde iframe‘im youWon isminde bir nesneye dönüşmüş oluyor.

Soruya dönersek biz zaten iframe içerisindeki src attribute’unda bulunan url’de <script> tagleri arasındaydık. url encode edilmiş olduğu için dikkatli incelerseniz bunların <script> tag’leri olduğunu fark edersiniz. Şimdi tek yapmam gereken window.name olarak youWon değerini vermek. Şuan doğru payload’ı yazdım ve alert döndü.
Soru inanılmaz zordu, saatlerimi aldı. Çözemediğim için pes edip writeup’ta da çözemediğimi yazacakken, şu an writeup yazarken soruyu çözdüm. Böyle soru mu olur ya

Neyse, payload

 

Level-14 ile ciddi anlamda uğraştım ama buraya yazabilecek kadar bile ilerleme kaydedemedim. Input iki farklı yere aynı anda yazılıyor, nereyi kontrol edeceğimi bilemiyorum ve url’den kaçmayı deneyince de alt kısımda BAD URL diyerek tüm moralimi bozuyor 🙁
Zaten yazı da çok uzadı, burada noktalandırıyorum.

Çözebilirsem devamını part-2 olarak yayınlarım inşallah. Okuduğunuz için teşekkürler.
Yazı ile ilgili sorularınız için bana her yerden ulaşabilirsiniz

https://www.linkedin.com/feed/update/urn:li:activity:6489474803618058240

Tags: