Ders 14 - Ajax Security > DOM Injection
AJAX Security ünitesinin dördüncü dersi olan DOM Injection(Document Object Model Enjeksiyonu) dersinde AJAX teknolojisi ile gerçekleştirilen sunucu bağlantısında sunucudan gelecek veriye kod enjekte edeceğiz. Böylece dersin sunduğu (sözde) uygulamaya girebilmek için lisans anahtarını bilmeden girişi gerçekleştirmiş olacağız.

Dersin Hedefi

*Bu derste kurban olan taraf aktivasyon anahtarını kullanmamıza izin veren ve bu aktivasyon kodunu alan sistemdir.

*Hedefiniz activate butonunu tıklanamaz durumdan tıklanabilir duruma getirmektir.

*Bir süreliğine dersin kaynak kodunu sağ tık yapıp View Page Source(Sayfa Kaynağını Görüntüle) sekmesine tıklayarak inceleyin ve anahtar geçerliliğini kontrol eden sistemin nasıl çalıştığına dair bir fikir edinin.

Açıklamalar

Bu derste AJAX teknolojisi kullanıldığından dolayı biraz AJAX kodlarına girişmekte fayda var. Bu başlık altında bu dersin kaynak kodunda kullanılan AJAX kodları anlatılacaktır. Eğer Dersin Hedefi kısmındaki 3.maddeyi uyguladıysanız dersin kendi işlevini gerçekleştirebilmesi için kullandığı AJAX kodlarının neler olduğunu belki de bulmuşsunuzdur. Aşağıda bulmanız gereken bu dersin kullandığı AJAX kodları gösterilmektedir:

function validate() {
   var keyField = document.getElementById('key');
   var url = 'attack?Screen=74&menu=400&from=ajax&key=' + encodeURIComponent(keyField.value);
   
   if (typeof XMLHttpRequest != 'undefined') {
      req = new XMLHttpRequest();
   } 
   else if (window.ActiveXObject) {
      req = new ActiveXObject('Microsoft.XMLHTTP');
   }

   req.open('GET', url, true);
   req.onreadystatechange = callback;
   req.send(null);
}

function callback() {
   if (req.readyState == 4) { 
       if (req.status == 200) { 
           var message = req.responseText;
   
   var messageDiv = document.getElementById('MessageDiv');
  
   try {
      eval(message);
    
      messageDiv.innerHTML = 'Correct licence Key.' 
   }
   catch(err) { 
      messageDiv.innerHTML = 'Wrong license key.'
   } 
}


Adım adım bu kodların ne anlama geldiğinden bahsedelim. Öncelikle XMLHttpRequest nesnesine değinelim. Hatırlarsanız daha önce bu nesnenin AJAX'ın kilit noktası olduğudan bahsetmiştik.(bkz. Ders 11) Bu nesne ile biz sayfayı komple yenilemeden sayfanın sadece belirli bir kısmını güncelleyebiliyoruz. Bu esnekliği dikkat ederseniz şimdiki ders ekranı da kullanmaktadır. Nasıl mı? Şöyle ki ders ekranındaki Lisans anahtarı gireceğiniz metin kutusuna veri girdiğinizde sayfa yenilenmeden girdiğiniz veriler sunucuya gönderilmektedir. Sunucu ise gelen veriye göre yanlışsa Wrong License Key, doğruysa Correct Licence Key bildirimlerinin ders ekranında görüntülenmesini sağlamaktadır.





İşte ders ekranındaki bu dinamizmi veren kodların temeli XMLHttpRequest'tir. Şimdi dersin kullandığı kodlara bir göz atalım. validate() fonksiyonu ilk olarak kod bloğunda yer almaktadır.

function validate() {
   var keyField = document.getElementById('key');
   var url = 'attack?Screen=74&menu=400&from=ajax&key=' + encodeURIComponent(keyField.value);
    
   if (typeof XMLHttpRequest != 'undefined') {
      req = new XMLHttpRequest();
   } 
   else if (window.ActiveXObject) {
      req = new ActiveXObject('Microsoft.XMLHTTP');
   }
 
   req.open('GET', url, true);
   req.onreadystatechange = callback;
   req.send(null);
}


Bu fonksiyon siz lisans anahtarı gireceğiniz metin kutusuna veri girdiğiniz her an çalıştırılmaktadır. Çünkü dersin kaynak kodunda görebileceğiniz üzere metin kutusunun koduna onkeyup="validate();" ifadesi eklenmiştir.





Yani metin kutusuna ne tuşlanırsa tuşlansın validate() fonksiyonu her bir karakter tuşlanmasında çalıştırılacaktır. Şimdi bu fonksiyonun içerisine göz atalım. İlk satırlara değinmeden önce sırası gelmişken XMLHttpRequest nesnesiyle alakalı kod bloğunu ele alalım. Kod bloğundaki XMLHttpRequest kısmı aşağıda gösterilmektedir.

if (typeof XMLHttpRequest != 'undefined') {
   req = new XMLHttpRequest();
} 
else if (window.ActiveXObject) {
   req = new ActiveXObject('Microsoft.XMLHTTP');
}


typeof ile tarayıcıda XMLHttpRequest nesnesi var mı yok muyu test etmiş bulunmaktayız. XMLHttpRequest nesnesi maalesef Internet Explorer'da yoktur. IE(Internet Explorer) XMLHttpRequest nesnesi yerine ActiveXObject nesnesi kullanmaktadır. Dolayısıyla web geliştiricileri bu siteler arası uyumusuzluğun üstesinden gelebilmek için yukarıdaki gibi ekstradan bir kod(bir else if koşulu) eklerler. Yukarıdaki if koşulu XmlHttpRequest nesnesine sahip olan tarayıcıların okuyacağı kodu içeriyorken ekstra kodlama olan Else if koşulu ise ActiveXObject nesnesine sahip olan tarayıcının okuyacağı kodu içermektedir. new komutu ile req adlı nesne oluşturulmuş bulunmaktadır. Şimdi validate() fonksiyonu içerisindeki bir sonraki kodlara göz atalım:

req.open('GET', url, true);
req.onreadystatechange = callback;
req.send(null);


Yukarıdaki kod bloğu XMLHttpRequest nesnesi olan req üzerinden sunucuya bağlantı kurmaktadır. Sunucuya "url" ile GET talebinde bulunulmaktadır. "url"nin içeriği bu bölümün en başında verilen kod bloğunun 1. ve 2.satırında oluşturulmaktadır. O satırlar şunlardır:

var keyField = document.getElementById('key');
var url = 'attack?Screen=74&menu=400&from=ajax&key=' + encodeURIComponent(keyField.value);


Birinci satır ile ders ekranıdaki lisans anahtarının girileceği metin kutusu nesnesi kod bazında keyField değişkenine atanır. İkinci satırda ise keyField'a atanan metin kutusunun içerdiği değer url değişkeninin sonuna eklenir. İlgili kodlara geri dönelim:

req.open('GET', url, true);
req.onreadystatechange = callback;
req.send(null);


req.open ile sunucuya bir GET talebinde bulunulmaktadır. Buradaki url tıpkı adı gibi bir işlevde kullanılmaktadır. Yani adres çubuğuna url girip site içeriği nasıl bekliyorsak yukarıdaki kodlar ile de aynı işi yapıyoruz. Buradaki fark bu talep işini kodların yapmasıdır. Hem de sayfayı yenilemeden. req.onreadystatechange = callback; satırında ise req.onreadystatechange'e callback adlı bir fonksiyon atanmıştır(Bu atama Javascript'e yapancı kimseler için biraz garip gelebilir) Şimdi atanan bu fonksiyonu inceleyelim. Bu fonksiyon validate() fonksiyonundan sonra yer almaktadır:

function callback() {
   if (req.readyState == 4) { 
       if (req.status == 200) { 
           var message = req.responseText;
    
   var messageDiv = document.getElementById('MessageDiv');
   
   try {
      eval(message);
     
      messageDiv.innerHTML = 'Correct licence Key.'
   }
   catch(err) { 
      messageDiv.innerHTML = 'Wrong license key.'
   } 
}


Fonksiyonda gördüğünüz üzere iki tane iç içe if koşulu vardır. Bu koşullar şu anlama gelir: Eğer sunucuya yapılmış olan GET talebi başarılı olduysa ilk if'in içine girilir. Eğer GET talebi sonrası ilgili içerik sunucuda bulunduysa bu sefer içteki if'e de girilir. Böylelikle sunucuda bulunan içerik tarayıcıya çekilir. Bu veriyi çekme işlemine parsing denmektedir. Aşağıda parse eden kodu görmektesiniz:

   if (req.readyState == 4) { 
       if (req.status == 200) { 
           var message = req.responseText;


message değişkenine sunucudan gelen veri atanır. Şimdi callback fonksiyonunun devamına bakalım:

var messageDiv = document.getElementById('MessageDiv');

try {
   eval(message);
  
   messageDiv.innerHTML = 'Correct licence Key.'
}
catch(err) { 
   messageDiv.innerHTML = 'Wrong license key.'
}


Ders ekranında veri girmeden önce görünmeyen bir alan vardır. O alanın id'si MessageDiv'dir. O html elemanı messageDiv değişkenine yukarıdaki kod bloğunun ilk satırında olduğu gibi atanır. Sonra try bloğuna girilir. Eğer parse edilen veriyi tutan message değişkeni sunucudan hata üretecek bir veri almışsa try bloğu içerisinde bir hata fırlatacaktır. Bu yüzden hatanın fırlatıldığı satırın hemen aşağısındaki messageDiv.innerHTML = 'Correct license Key.' satırı çalışmayacaktır. Fırlatılan hatayı catch bloğu yakalayıp messageDiv elemanına 'Wrong licence key' bildirimini atayacaktır. Eğer girilen lisans anahtarı doğruysa eval() fonksiyonu hata fırlatmayacaktır. Böylelikle MessageDiv id'li html elemanına 'Correct Licence Key' bildirimi atanacaktır. Bu arada eval() fonksiyonu ne diye merak etmiş olabilirsiniz. eval() fonksiyonu argüman olarak aritmetik bir işlem girilirse aritmetik işlemin sonucunu döndüren, javascript komutu girilirse javascript komutunu "çalıştıran" bir fonksiyondur.

function callback() {
   if (req.readyState == 4) { 
       if (req.status == 200) { 
           var message = req.responseText;
     
   var messageDiv = document.getElementById('MessageDiv');
    
   try {
      eval(message);
      
      messageDiv.innerHTML = 'Correct licence Key.'
   }
   catch(err) { 
      messageDiv.innerHTML = 'Wrong license key.'
   } 
}


Buraya kadarki yaptığımız işi toparlayacak olursak şunu diyebiliriz ki eğer lisans anahtarı girilecek yere bir karakter girersek validate() fonksiyonu tetiklenecektir. Girdiğimiz karakteri url değişkeninin sonuna ekleyerek sunucuya talepte bulunacaktır. Sunucu veri göndermeye hazır olana kadarki tüm aşamalarda callback fonksiyonu tetiklenecektir. Çünkü callback fonksiyonu XMLHttpRequest nesnesi olan req'in onreadystatechange event'ine atanmıştır. (req.onreadystatechange = callback;) Fakat sadece sunucu hazır olduğunda callback fonksiyonu içerisindeki iç içe if'lere girilecektir. Varsayalım ki yanlış lisans anahtarı girdiniz. Yanlış lisans anahtarını alan sunucu hatalı bir veriyi message değişkenine döndürecektir. eval() hata fırlatacaktır ve catch bloğundaki 'Wrong Licence Key' bildirimi ekrandaki html elemanına atanacak ve ekranda görünür olacaktır. Eğer sunucu kendisine gelen verinin doğru lisans anahtarı olduğunu görürse ders ekranındaki Active butonunu tıklanabilir yapan javascript komutlarını message değişkenine gönderecektir. Böylelikle eval() hata fırlatmayacaktır ve aldığı javascript komutlarını çalıştırıp ders ekranındaki Active butonunu tıklanabilir yapacaktır. Sonra 'Correct Licence Key' bildirimi ders ekranındaki html elemanına atanacaktır.

Böylelikle bu dersin kodunu anlamlandırmış olduk. Şimdi sıra dersi çözmekte.

Dersin Çözümü

Bu dersi çözmek için WebScarab yazılımından faydalanacağız. Öncelikle WebScarab yazılımındaki Intercept sekmesine tıklayın. Ardından Intercept Response kutucuğuna tick işareti koyun.





Ardından ders ekranına dönün ve lisans anahtarı girilecek metin kutusuna bir şey girin. Girdiğiniz veri sunucuya talep olarak AJAX teknolojisi ile gidecektir. Sunucudan lisans anahtarı doğru ya da yanlış şeklinde bir yanıt geldiğinde ise WebScarab yazılımı bunun önünü kesecektir ve ekrana bir popup penceresi gelecektir. O penceredeki Text sekmesine tıklayın ve içeriği komple silin! Ardından şu javascript komutlarını sildiklerinizin yerine girin: "document.form.SUBMIT.disabled = false;" Böylelikle Active butonunu tıklanabilir yapmış olmaktasınız ve ayrıca 'Correct Licence Key' bildirimini ekranda görüntülemiş olmaktasınız.





Ardından Accept Changes diyerek popup'ı kapatın. Göreceğiniz üzere ders ekranında buton aktifleşmiştir ve Correct Licence Key bildirimi görüntülenmektedir. Dersi tamamlamak için Active butonuna tıklamanız yeterlidir(NOT: WebScarab'da halen Intercept Response kutucuğu tick'li olduğu için butona tıkladığınızda yeni bir popup penceresi gelecektir. Bu pencereyi de Accept Changes diyerek geçin.Dersi tamamlamış bulunmaktasınız. Diğer derslerde sizi rahatsız etmemesi için WebScarab'ın Intercept Response kutucuğunun tick'ini kaldırabilirsiniz.)

Sonuç
Bu derste AJAX teknolojisiyle sunucu iletişimini deneyimlemiş olduk. Kodlara da biraz vakıf olduk. Dersten yapılabilecek çıkarım şudur: Eğer bir websitesi erişim kısıtlamasını sunucu taraflı değil de bu dersteki gibi istemci taraflı yaparsa bu güvenlik açığına sahip sistem üzerinde istemci taraflı olan kalkanlar, inmiş html dosyası üzerinde elle manipulasyon yaparak ya da mesela bu derste yaptığımız gibi WebScarab yazılımı gibi bir proxy ile DOM Injection yaparak kaldırılabilir ve erişim kolaylıkla sağlanabilir. Bu ders senaryosuna göre ders ekranındaki uygulamaya giriş işlemi epostaya gönderilmiş lisans anahtarının girilmesi ile mümkün kılınmıştır ve eğer lisans anahtarı yanlış girilmişse istemci tarafındaki giriş kısıtlaması olan buton tıkını kaldırma işlemi devreye koyulmuştur. Halbuki istemci tarafındaki giriş kısıtlaması olan buton tıkını kaldırmayı DOM Injection yaparak kaldırabilir ve yanlış lisans anahtarı olmasına rağmen bu derste gördüğünüz üzere buton tıklanabilir yapılabilir ve nihayetinde sisteme giriş sağlayabiliriz. Bu derste ve önceki derslerde gördüğünüz üzere istemci taraflı sağlanan güvenlik sadece kötü niyet taşımayan ve "yanlışlıkla" sisteme zarar vermemesini istediğimiz kişiler için koyulmalıdır. Fakat aynı zamanda kötü niyetli kişilerden sistemi korumak istiyorsak o zaman sunucu taraflı bir güvenlik önlemi de alınmalıdır. Yani sunucu tarafındaki programlama dili ile mesela doğru lisans anahtarı girildiğinde if, yanlış lisans anahtarı girildiğinde else koşulunun çalıştırılıp ekrana ilgili içeriğin yansıtıldığı bir erişim kontrolü oluşturulabilir. Eğer böyle yapılmazsa ve bu derste olduğu gibi erişim geçidi bir butonu tıklanamaz hale sokarak kapatılırsa bu tam anlamıyla bir akıl tutulması olur. Çünkü daha önceden de söylediğimiz gibi istemci taraflı filtrelemeler, kontroller istenildiği takdirde kolayca atlatılabilir. Tıklanamaz bir butonu biz bu derste WebScarab sayesinde tıklanabilir yaptık. Eğer sunucuda az önce bahsedilen if-else koşulları ile içerik sunma kontrolü yoksa butonu tıklanabilir yaparak erişim geçidinden kolaylıkla geçebilir ve erişememiz gereken bilgilere erişebiliriz. Sonuç olarak istemci taraflı kontroller masum kullanıcılar için yönlendirme amaçlı kullanılmalıyken sunucu taraflı kontroller ise kötü niyetli kullanıcıları engellemek için kullanılmalıdır. Yani her iki kontrol de gereklidir. Biri olmazsa denge bozulur.
Bu yazı 26.06.2015 tarihinde, saat 09:19:25'de yazılmıştır. 23.09.2015 tarihi ve 14:32:08 saatinde ise güncellenmiştir.
Yazar : Hasan Fatih ŞİMŞEK Görüntülenme Sayısı : 2380
Yorumlar
Henüz yorum girilmemiştir.
Yorum Ekle
*
* (E-posta adresiniz yayınlanmayacaktır.)
*
*

#Arşiv


#Giriş

ID :
Şifre :