28 Temmuz 2008 Pazartesi

Cross-Site Request Forgery - XSRF - CSRF

XSS'i (Cross Site Scripting), web tarayıcısı gibi bir istemcinin bir web uygulamasına güveninden yararlanmak olarak düşünebiliriz. Peki bir uygulamanın bir kullanıcıya olan güveni de exploit edilebilir mi? Cross-Site Request Forgery (XSRF veya CSRF) bir web uygulamasının bir kullanıcıya uyguladığı güveni kullanarak tamamen legal (aslında bir anlamda zaten öyleler) görünen kimlik doğrulaması yapılmış istekler yapılması işlemidir. Tehlikesi açıkça ortadadır. XSRF kullanıcıların banka hesaplarından para transfer istekleri yapmaya zorlamada, kullanıcı bilgisi sıfırlamada, kötü amaçlı epostalar göndermede kullanılabilir. Maalesef, XSRF açıkları için kolay bir çözüm yok. Ve bu açıklar olduğunda, çok sayıda oluyorlar. Bu dokümanın amacı hem uygulama geliştiriclerini hemde güvenlik uzmanlarını bu tip saldırılar konusunda eğitmek ve açıkların nasıl kapatılacağı konusunda tavsiyeler sunmaktır.

XSRF nedir?
XSRF'nin en basit tanımı bir saldırganın, bir web sitesine, sitenin güvendiği bir kullanıcıdan yetkisiz komutlar göndermesidir. Bu tip saldırılara genelde "session riding" veya "hostile linking" saldırıları adı verilir çünkü sunucu ile halihazırda oturum açmış olan kullanıcıları kullanır. XSRF saldırı için web tarayıcısını kullanır ve kullanıcının yeni kullanmış olduğu varsayılan bir siteye bağlantı kuran bir script veya link içerir.
Sonrasında script görünüşte yetkili fakat kötü amaçlı işlemleri kullanıcı adına gerçekleştirir. Kimlik doğrulaması yapılmış kullanıcıların spesifik işlemleri onaylamalarını gerektirmeyen web uygulamaları XSRF saldırılarından etkilenebilir. Müşterilerinin tekrar kimlik doğrulaması işlemi yapmadan "hızlı" satın alma işlemi yapmalarına izin veren bir alışveriş sitesi düşünün. Veya MyFriends hesabına login olmuş bir kullanıcı düşünün. Aynı browser'ı kullanarak, MyFriends'den ayrılır ve tarayıcısının MyFriends sitesindeki AddToFriendList.cgi?friend=evildude sayfasına istek yapmasını sağlayan başka bir siteye girer. Farkında olmadan, ve izni olmadan, ziyaret ettiği web sitesi, onun MyFriends sitesinde arkadaş listesine evildude isimli birisini eklemesine yol açtı.

Exploit
XSRF'den başarılı olarak yararlanabilmek için, saldırganın yardımcı bir sistem kullanması gerekmektedir. Yardımcı sistem, web tarayıcınıza takip etmesi için XSRF linkini veren yerdir. Bir sistem hem kurban hem de yardımcı olabilir fakat önce web tarayıcısının alıp çalıştırabileceği birşeyler gönderilmesine (resim, script veya link) izin vermesi gerekir. Kısaca, yardımcı sitenin link gönderilmesine izin vermesi gerekir. Resim kullanılan XSRF saldırıları genelde kullanıcıların resim göndermesine izin veren fakat JavaScript'e izin vermeyen Internet forum'larından yapılır. Örneğin, saldırgan bir foruma aşağıdaki tag'lere sahip bir resim ekleme yapabilir:

Eğer kullanıcının bankaya logini aktifse ve web tarayıcısı forumda bu resime istek yaparsa, kötü amaçlı kişinin hesabına 10,000 dolarlık transfer isteği www.mybank.tld sitesine gönderilir. Aşağıdaki grafik bu durumu göstermektedir:

Hedef ek kimlik doğrulaması gerektirmeden kullanıcı işlemlerine izin veren uygulamadır.
Web tarayıcı yardımcı sitedeki kaynağa istek yaptığında neler olur? Önceki kod örneğimizdeki image tag örneğini kullanalım. Sayfaya istek yapıldığında, tarayıcı sayfada resim olduğunu bilmez. Dönülen cevaptaki HTML parse edildiğinde tarayıcı sayfada bir resim olduğunu bilir. Bu noktada, resim standart bir GET isteiği ile istenir. Problem burada yatmaktadır. Hedef site iş işten geçene kadar (ör. istek yapıldıktan sonra) isteğin bir resim için mi yoksa farklı bir kaynak içinmi olduğunu bilemez.

Bu konuyu açıklamada başka bir örnek daha verelim. Hayali bir e-ticaret sitesi düşünelim, spistore.com. Bir kullanıcı alışveriş sepetine bir ürün eklemek istediğinde, web tarayıcısı http://spistore.com/add
ToCart?item=5658 isteğini yapar ve buradaki 5658 eklemek istedikleri ürün id'si. Spistore.com ürünü kimin sepetine ekleyeceğini bilir çünkü tarayıcı kullanıcının çerez bilgisini de ürün ekleme isteği ile birlikte gönderir. Şimdi bir forum sitesi düşünelim, spiforum.com. Kötü amaçlı bir kullanıcı foruma

yazısını içeren bir mesaj gönderir. Bu mesajı birisi görüntülediğinde, kötü amaçlı img tag'ini içeren HTML, tarayıcıları tarafından yorumlanır. Tarayıcı img'yi gördüğünde
http://spistore.com/addToCart?item=5658
URL'sine istek yapar. spiforum.com'daki bu mesajı okuyan ve spistore.com da oturumu açık olan tüm kullanıcıların alış veriş sepetine 5658 nolu ürün eklenmiş olur.

XSRF ve XSS
XSRF ve XSS birbiri ile ilişkili açıklardır ve uygulamanızı hangilerinin etkilediğini belirlemek zor olabilir. Eğer bir uygulama XSS den etkileniyorsa, aynı zamanda XSRF'den de etkileniyordur çünkü XSRF bir XSS açığını kullanabilir. Fakat XSRF'ten etkileniyor olan bir uygulama XSS den etkilenmiyor olabilir. Aşağıdaki grafikte de görülebileceği gibi, XSS'i XSRF'nin bir alt kümesi olarak düşünebilirsiniz:

Bu iki saldırı şeklindeki ana fark saldırının nasıl yapıldığıdır. XSS giriş doğrulamayı atlatma ile ve bir sayfaya direk olarak kod enjekte etme ile yapılır. XSRF zaten orada olanı kötüye kullanmak için yapılır..izin verilen sayfa elementlerini, CGI'ları direk olarak ek kimlik doğrulaması gerekmeden çalıştırarak.

XSS ve XSRF'deki esas problem XSS'in, XSRF açıklarının riskini artırmasıdır. Birlikte kullanıldığında birbirlerini çok iyi tamamlarlar. En büyük risk, birleştirildiklerinde, tarayıcı farklı web sitelerine gidebilir, tek bir siteyle sınırlı kalmaz. XSRF tek başına saldırganın HTTP cevabını okuyabilmesine izin vermediği için saldırının başarılı olup olmadığı bilinemez. Fakat, XSS ile birleştirildiğinde, saldırgan sonuçları kendi seçtiği bir yere yönlendirebilir ve saldırının başarılı olup olmadığını anında görebilir.

Önleme
XSRF'i fixlemek XSS'i, hatta SQL Injectioni'ı fixlemekten daha zor olabilir. Çünkü kötü amaçlı isteği kurban gönderdiğinde, isteğin saldırı olup olmadığını anlamak zor olabilir. XSRF için alınan önlemler, eğer XSS açıkları varsa etkisiz olabilir. XSRF'i engellemek demek aynı zamanda XSS saldırılarını da engellemek demektir. Giriş filtreleme XSRF saldırılarını engellemese de XSS saldırılarını önlemek için mutlaka yapılmalıdır. Giriş filtreleme, kaynağı neresi olursa olsun, uygulama tarafından kabul edilen verilere uygulanmalıdır.

XSRF önleme genelde her web uygulaması özelliğinin ve form'unun tekrar kodlanmasını gerektirir. anti-XSRF token'ları kullanarak veya CAPTCHA implemente ederek XSRF saldırılarını önleyebilirsiniz. İmplementasyonu daha kolay fakat çok etkili olmayan, yine de hiç olmamasından iyi, başka metodlar da var. Birden fazla metodun kombinasyonunun kullanılması genelde tavsiye edilmektedir. Aşağıda her bir metod anlatılmaktadır:

Yardımcı
Kullanıcı tarafından gelebilecek tüm girişlerin filtrelenmesi gerekir. Bunun için aşağıdakileri yapın:
* Filtrelemede black list yerine white list metodunu kullanın. White list metodu, kötü olan içerikleri bloklamak yerine iyi olan girişleri kabul etme işlemidir. Örneğin Türkiyedeki bir telefon numarası her zaman (alan kodu ile birlikte) 10 rakam olmalıdır; telefon numarasına white list uygulamak demek sadece 10 ader rakam kabul etmek, başka birşeyi kabul etmemek demektir.
* Kullanıcı tarafından sağlanan tüm verileri, tarayıcılarının yorumlayabileceği bir formatta gönderilmesini engelleyecek şekilde kodlayın. Örneğin, küçüktür işareti < < olarak (veya URL'de %3c olarak) kodlanmalı.
* (programlama sitelerinden indirilen veya programlama örneklerinden alınan) Üçüncü parti kodları kendi web uygulamanızda (ne kadar güvenli olup olmadığını anlamadan) kullanmayın.

Kurban
Anti_XSRF Nonce Token
XSRF'i önlemede hiçbir metod kesin değil fakat anti_XSRF nonce token'ları kullanmak riskin büyük bir bölümünü yokeder. Teoride, geçerli bir token saldırgan tarafından tahmin edilebilir, fakat bu gerçekte kolay bir işlem değildir. Dahası, bu metod günümüzde XSRF saldırılarını engellemede en etkili metoddur. Kullanıcı login olduktan sonra bir "giz" yaratarak kullanıcının doğru olup olmadığını kontrol edebilirsiniz. Kullanıcı login olduktan sonra gizli bir hash veya token yaratıp sunucu-tarafı oturumunda depola ve bunu her link ve form'a dahil et. Birbirini takip eden her http isteği bunu içermeli, aksi takdirde kabul edilmemeli ve oturum geçersiz kılınmalı. Eğer XSS açığı varsa "Giz" oturum id'si ile aynı olmamalı. Token'ı herhangi bir oturum değişkeni gibi oluştur. Basit bir koşul ifadesi doğrulanabilir. Ayrıca etkisini artırmak için kısa bir zaman dilimine kısıtlanabilir. Bu değişiklik saldırganın XSRF saldırısında geçerli token kullanmasını gerektirir. Kullanıcı token'ı oturumda depolandığı için, saldırganın bu kurbanına özel token'ı kullanması gerekecektir.

Bunu PHPi'de yapılışı ile ilgili bir örnek verelim. Bu futbol maçı biletleri sipariş edilebilen bir web uygulaması örneği:
session_start();
$token = md5(uniqid(rand(),TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
?>


" />


Item:


Number:



Token herhangi bir oturum değişkeni gibi yaratılmalı.
if (!isset($_SESSION['token']))
{
$_SESSION['token'] = md5(uniqid(rand(), TRUE));
}
?>

Token'ı basit bir koşul ifadesi ile kontrol edin:
if ($_POST['token'] == $_SESSION['token'])
{
/* Valid Token */
}
?>

Token'ın geçerliliğini belirli bir zaman periyoduna kısıtlamak, örneğin dört dakika, güvenliği artıracaktır:
$token_age = time() - $_SESSION['token_time'];
if ($token_age <= 240)
{
/* Less than four minutes has passed. */
}
?>

CAPTCHA
CAPTCHA implemente etmekde XSRF saldırılarını engelleyebilir. CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) basitçe kullanıcının karışık fakat okunabilir harf (veya harf rakam kombinasyonu) içeren resimde gösterilenleri girmesini gerektirir. Burdaki fikir bilgisayarın grafikte gizli olan kelimeyi bulamayacağı ve insanların kolaylıkla ayırtedebileceğidir. CAPTCHA kullanımı, kullanıcının spesifik işlemler öncesi resimdeki bilgiyi girmesi ile olur. İşleme devam için otomatik bir script'in yaratılması çok zor olsa da bunu aşma konusunda araştırmalar yapılıyor. Eğer bu metodu kullanmaya karar verirseniz güçlü bir CAPTCHA kullanın. Güçlü bir CAPTCHA inşa etmek zor olabilir. Ek olarak, resimlerin bilgisayar tarafından okunamadığına emin olmak için, geliştiricilerin, CAPTCHA'nın script seviyesinde atlatılamayacağına emin olması gerekir. Aynı CAPTCHA birden fazla mı kullanılıyor? uygulamanın tekrar-oynatma (replay) saldırısından etkilenmesine yol açarmı? Ya da CAPTCHA ya geçirilen düz yazı cevap web formunun bir parçasımı? Bunlar düşünülmesi gereken problemler.

Diğer Çözümler
Daha az zaman ve efor gerektiren (fakat daha az etkili olan) diğer çözümlere gelelim. Çoğunlukla gizleme ile güvenlik (security through obscurity) den oluşurlar. Bu da saldırganın açıktan yararlanmasında ek bilgi gerektirir. Fakat, tekrar uyaralım, uygulamanız uzman bir saldırgana bu şekilde karşı koyamaz.

Yönlendirme
XSRF saldırılarını HTTP isteğinin yetkili bir kaynaktan gelip gelmediğini kontrol ederek ve yönlendirme kullanarak önleyebilirsiniz. Eğer Referer başlığı yoksa, veya işlemi gerçekleştirmesi gerekmeyen bir sayfa veya site içeriyorsa, yönlendirme kullanıcıyı başka bir sayfaya yönlendirerek ek işlem yapılmasını engelleyebilir.

if ($_SERVER['HTTP_REFERER'] != ‘http://www.victim.tld/transfer.html' )
{
header("Location: http://www.victim.tld/transfer.html");
exit;
}
?>

URL Rewrite
Form-tabanlı kimlik doprulama yaparken diğer bir opsiyon da cookie yerine URL rewrite (özellikle bu opsiyon uygulama sunucusu tarafından transparan olarak yapılabiliyorsa) kullanımıdır. Oturum tanımlayıcısını her URL'ye dahil edildiğinde, bu tanımlayıcı arka arkaya yapılan sayfa isteklerinde ayrıştırılıp oturum bilgisini tanımakta kullanılabilir. Fakat çoğu uygulamada bunun uygulanabilmesi büyük bir çalışma gerektirebilmektedir.

Get yerine Post kullanımı
uygulamanın objeleri yaratma, değiştirme ve silme gibi durum değişiklikleri için GET yerine POST kullanımına zorlama yapılabilir. Hem HTTP GET, hem de HTTP POST kullanan uygulamalar XSRF açıklarından etkilense de, HTTP GET kullanarak saldırıyı gerçekleştirmek çok daha kolaydır. POST kullanımı resim tag'leri örneğimizdeki saldırıyı etkisiz kılar ve uygulama içerisinde resim link'lerinin paylaşılabilmesine izin verir. Ayrıca bunu implemente etmek çok kolaydır. Ayrıca saldırganların başka hedef aramasına yol açacak kadar caydırıcı olabilir. Fakat yine de çok bilgili bir saldırgan JavaScript kullanarak POST isteklerinden de bu saldırıları yapabilir.

Oturum tanımlayıcılarının gizli form alanları olarak geçirmek
Formlarda hidden alanlarında oturum tanımlayıcılarını kullanabilirsiniz. Bu bilgi web sayfasında görülmez fakat diğer alanlarla birlikte otomatik olarak gönderilir. Gizli form alanlarında oturum tanımlayıcılarını geçirmek, bir sayfadan diğerine geçişte resim linkleri yazı linkleri kullanımından mahrum bırakır, bu sebeple bu pek kullanışlı değil. Ayrıca HIDDEN form alanı değeri web sayfasında görünmese de tarayıcının kaynak görüntüleme seçeneği ile kolayca görülebilir. Bunun içinde gizli veri kriptolanarak sadece gerektiğinde dekriptolanabilir.

Hiç yorum yok: