CEH · OWASP · Juice Shop · XSS · Write-up
OWASP Juice Shop'ta DOM XSS: Arama kutusundan tarayıcıyı ele geçirmek
Halil Yaşarsoy · 14 Ekim 2026

Bu yazı, SiberDojo CEH sınıfının Juice Shop Write-up projesi için hazırlanmış örnek bir yazıdır. Kendi yazını hazırlarken yapıyı, tonu ve ekran görüntüsü kullanımını referans al; ama seçtiğin açık, çözüm ve anlatım tamamen senin olsun.
Okuma süresi: ~6 dk · Zorluk: ⭐ (1 yıldız) · Kategori: OWASP Top 10, A03 Injection (XSS)
TL;DR
OWASP Juice Shop'un arama kutusu, kullanıcının yazdığı metni temizlemeden sayfaya HTML olarak basıyor. Bu yüzden arama kutusuna yazılan bir <iframe> etiketi tarayıcıda JavaScript çalıştırıyor. Bu yazıda açığı nasıl bulduğumu, nasıl istismar ettiğimi, gerçek hayatta ne anlama geldiğini ve nasıl önleneceğini anlatıyorum.
1. Ortam
Lab'ı SiberDojo platformundaki izole CEH laboratuvarında çözdüm: kendi Kali masaüstüm ve bana ait bir OWASP Juice Shop örneği. Juice Shop, OWASP'ın eğitim amacıyla bilerek açıklarla dolu bıraktığı bir e-ticaret uygulaması.

⚠️ Etik not: Burada anlatılan teknikleri yalnızca izin verilen ortamlarda (kendi lab'ın, CTF platformları, yazılı izinli sızma testleri) kullan. İzinsiz sistemlerde denemek suçtur.
2. Keşif: Kullanıcı girdisi nereye gidiyor?
XSS ararken ilk sorduğum soru şu: "Benim yazdığım bir şey sayfada geri görünüyor mu?" Juice Shop'ta en belirgin aday üst bardaki arama kutusu.
apple diye arattığımda iki şey dikkatimi çekti:
- Adres çubuğu
#/search?q=appleoldu. Yani arama terimi URL'de taşınıyor. - Sonuç başlığında "Search Results - apple" yazıyor. Yazdığım kelime sayfaya geri basılıyor.

URL'deki # işaretinden sonraki kısım sunucuya hiç gitmez; tarayıcıda Angular tarafından okunur. Bu, sorun varsa sunucuda değil istemci tarafında (DOM'da) olduğuna işaret ediyor. Adı da buradan geliyor: DOM-based XSS.
3. İstismar
Önce zararsız bir HTML denemesi yaptım: <b>test</b>. Başlıkta "test" kalın yazıldı. Bu, girdinin metin olarak değil HTML olarak işlendiğinin kanıtı.
Sıradaki adım JavaScript çalıştırmak. <script> etiketi innerHTML ile eklendiğinde tarayıcılar onu çalıştırmaz, bu yüzden başka bir yol gerekiyor. javascript: şemasına sahip bir iframe bu iş için ideal:
<iframe src="javascript:alert(`xss`)">

Enter'a bastığım anda tarayıcı xss yazan bir uyarı penceresi açtı. JavaScript çalıştı. Juice Shop da challenge'ın çözüldüğünü yeşil bantla onayladı:

Aynı saldırı URL üzerinden de yapılabilir. Bu, en tehlikeli kısım:
http://<juice-shop>/#/search?q=<iframe src="javascript:alert(`xss`)">
Bu linki bir kurbana gönderdiğinizde, kurban linke tıkladığı an kod onun tarayıcısında, onun oturumuyla çalışır.
4. Kök neden
Angular normalde {{ }} ile basılan her şeyi otomatik olarak temizler. Juice Shop'un arama bileşeni ise girdiyi bypassSecurityTrustHtml() ile "güvenilir HTML" olarak işaretleyip innerHTML ile sayfaya yerleştiriyor. Yani geliştirici, framework'ün koruma kalkanını bilerek kapatmış.
Kısaca zincir şöyle:
URL (q=) → Angular bileşeni → güvenlik atlatılıyor → innerHTML → tarayıcı payload'ı çalıştırıyor
5. Gerçek hayatta etkisi
Ekrana alert çıkarmak zararsız görünür ama bu sadece kanıttır. Gerçek bir saldırgan aynı yerden şunları yapabilir:
- Oturum çalma:
localStorageveya erişilebilir cookie'lerdeki oturum token'ını kendi sunucusuna göndermek. (Juice Shop token'ılocalStorage'da tutuyor.) - Kimlik avı: Sayfanın içine sahte bir "oturumunuz düştü, şifrenizi tekrar girin" formu çizmek.
- Kullanıcı adına işlem: Kurbanın oturumuyla sepete ürün eklemek, adres değiştirmek, yorum yazmak.
OWASP Top 10 2021'de XSS, A03: Injection başlığı altında yer alıyor.
6. Nasıl önlenir?
- Framework'ün korumasını kapatma.
bypassSecurityTrustHtml,dangerouslySetInnerHTML,v-htmlgibi API'ler yalnızca gerçekten güvenilir içerik için kullanılmalı. - Çıktıyı bağlama göre kodla (output encoding). Kullanıcı girdisi HTML olarak değil, metin olarak basılmalı (
textContent). - HTML gerekiyorsa sterilize et. DOMPurify gibi bir kütüphaneyle izin verilen etiketleri sınırla.
- Content Security Policy (CSP).
script-src 'self'vejavascript:URL'lerini engelleyen bir CSP, açık kalsa bile istismarı büyük ölçüde zorlaştırır. - Oturum token'ını
localStorageyerineHttpOnlycookie'de tut. XSS olsa bile token JavaScript ile okunamaz.
7. Öğrendiklerim
- Kullanıcı girdisinin nereye yansıdığını takip etmek, XSS avının yarısı.
- URL'deki
#sonrası sunucuya gitmez; bu yüzden DOM XSS'i sunucu taraflı WAF'lar çoğu zaman göremez. <script>çalışmadığında pes etme:iframe,img onerror,svg onloadgibi alternatif vektörler var.
Juice Shop skor tahtasında (#/score-board) "DOM XSS" challenge'ı artık çözülmüş görünüyor:

Kaynaklar
- OWASP Juice Shop: https://owasp.org/www-project-juice-shop/
- Pwning OWASP Juice Shop (resmi çözüm kitabı, CC BY-SA 4.0): https://pwning.owasp-juice.shop/
- OWASP XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- OWASP DOM-based XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html
Bu çalışmayı SiberDojo CEH eğitimi kapsamında, SiberDojo'nun izole laboratuvar ortamında gerçekleştirdim. #SiberDojo #CyberSecurity #OWASP #JuiceShop #XSS #EthicalHacking
Bu yazı işine yaradıysa alkışla