01 Mart 2015

Web Uygulama Denetimi - Bölüm-14: XPATH Sorgularına Enjeksiyon

XML Path Language (XPATH) XML dokümanları içinde sorgu yapmak için kullanılan yorumlanan bir dildir. Web uygulamaları genellikle veri saklamak için XML dosyalarını kullanmasa da konfigürasyon verisi saklama amacıyla kullanılabilir.


XPath sorgularına aşağıdaki XML veri deposunu kullanarak örnek verebiliriz:

<addressBook>
<address>
<firstname>Ali</firstname>
<surname>Kara</surname>
<password>abc</password>
<email>[email protected]</email>
<ccard>1234 2345 3456 4567</ccard>
</address>
.
.
.
</addressBook>

Bu veri deposundaki tüm e-posta adreslerini sorgulamak için aşağıdaki sorguyu kullanabiliriz:

//address/email/text()

Adı Ali olan kullanıcı hakkındaki tüm bilgileri görüntülemek için aşağıdaki sorguyu kullanabiliriz:

//address[firstname/text()=’Ali’]

Bu tür sorguların içine kullanıcı tarafından girilen verilerin yerleştirildiği durumlarda sorgunun yapısını değiştirmek suretiyle elde edilen veri veya uygulamanın çalışma şekli etkilenebilir. Örneğin aşağıdaki Xpath sorgusu kullanıcı adı ve password’ünü doğrulayarak kullanıcının kredi kartı numarasını döndürmektedir:

//address[firstname/text()=’Ali’ and password/text()=’abc’]/ccard/text()

Bu durumda eğer kullanıcının girdiği veri password sahasına yerleştiriliyorsa password sahasına SQL enjeksiyon saldırısına benzer şekilde aşağıdaki veri girilirse:

‘ or ‘a’=’a

sonuç şu sorguya dönüşür ve tüm kullanıcılara ait kredi kartı numaralarına erişmek mümkün olur:

//address[firstname/text()=’Ali’ and password/text()=’’ or ‘a’=’a’]/ccard/text()

Yine SQL enjeksiyon saldırılarında olduğu gibi numerik sahalara enjeksiyon yapılıyorsa tek tırnak “’” işaretine gerek yoktur. Xpath sorgularının SQL sorgularından bir farkı da büyük ve küçük harflere duyarlı olmalarıdır, çünkü XML dokümanındaki eleman isimleri de büyük küçük harf duyarlıdır.

Bilgilendirilmiş Xpath Enjeksiyonu


Xpath enjeksiyonu prensip olarak SQL enjeksiyonuna benzese ve yukarıdaki başlık sanki hata mesajlarından yola çıkarak bilgi toplama yöntemine benzese de aslında burada SQL enjeksiyonundaki kör enjeksiyon yöntemine benzer bir yöntemden bahsediyoruz. Ne varki kör SQL enjeksiyonunda karşımızdaki veritabanını tespit edebilmişsek herkesçe bilinen metadata tablo isimleri ve alan adları bilgisine sahiptik. XML veri depoları karşısında malesef bu kadar şanslı değiliz ve veri elde edebilmek için XML veri deposu eleman isimlerini bilmek durumundayız. Bir sonraki başlıkta açıklayacağımız yöntemde bu bilgiye sahip olmak gerekmeyecek.

Bu yöntemde tıpkı kör SQL enjeksiyonda olduğu gibi uygulamanın doğru (true) koşul ile yanlış (false) koşulla yapılan isteklere verdiği yanıtlardaki farktan yola çıkarak veri deposundaki verilerin karakter karakter tahmin edilmesi şeklinde gerçekleştirilmektedir. Örneğin aşağıdaki enjeksiyonlardan birincisi her durumda doğru sonuç üreteceğinden sorgu muhtemelen normal ürettiği veriden daha fazlasını üretecek ikincisiyse ya hiç sonuç üretmeyecek ya da sınırlı veri üretecektir:

‘ or 1=1 and ‘a’=’a
‘ or 1=2 and ‘a’=’a

Farklı koşullara verilen tepki farklılıklarından yola çıkarak ve Xpath dilinin “substring” fonksiyonundan faydalanarak XML elemanlarının içerikleri karakter karakter elde edilebilir. Örneğin aşağıdaki sorgu parçasını girdi alanına enjekte ederek “Ali” kullanıcısının password bilgisini karakter karakter öğrenebiliriz:

‘ or //address[firstname/text()=’Ali’ and substring(password/text(),1,1=’a’] and ‘a’=’a

Bu enjeksiyon yapıldığında aşağıdaki sorgu oluşacak ve bu sorgu password’ün ilk karakterinin “a” olması durumunda sonuç döndürecektir:

//address[firstname/text()=’Veli’ and password/text()=’’ or //address[firstname/text()=’Ali’ and substring(password/text(),1,1=’a’] and ‘a’=’a’]/ccard/text()

Bu şekilde tüm karakterler test edilerek password bilgisine ulaşmak mümkün olacaktır.

Kör Xpath Enjeksiyonu


Önceki yöntemde araştırılan verinin tam erişim adresi (absolute path) ve eleman isimleri (firstname ve password) biliniyordu. Ancak Xpath dilinde içinde bulunulan noktaya göreceli sorgular geliştirmek mümkün olduğundan üst (parent) ve alt (child) noktalara yönelik sadece pozisyon bilgilerini belirterek sorgular geliştirebiliriz. Ayrıca Xpath dilinde XML meta bilgilerini sorgulamak için de fonksiyonlar bulunmaktadır. Xpath dilinin 100’ün üzerinde fonksiyonu bulunmaktadır. Bu imkanlar kullanılarak XML dokümanında bulunan tüm noktaların (done) isim ve içeriklerini elde etmek mümkündür.

Ayrıca count() fonksiyonu kullanılarak position() fonksiyonu için alan (range) ve string-length() fonksiyonu kullanılarak substring() fonksiyonu için alan (range) belirlemesi yapılabilir.

Örneğin yine bir önceki metod da kullanılarak (yani doğru ve yanlış koşullara alınan yanıtlardaki farklılıklardan yola çıkarak) içinde bulunulan noktanın (node) üst noktasının (parent node) adını öğrenmek için aşağıdaki enjeksiyon metni döngüsel biçimde enjekte edilebilir:

‘ or substring(name(parent::*[position()=1]),1,1)=’a

Üst noktanın ismi öğrenildikten sonra çocuk noktaların (child node) isimlerini öğrenmeden sadece indeksleri ile içeriklerine ulaşmak mümkündür. Örneğin yukarıdaki XML örneği için aşağıdaki sorgu “abc” değerini döndürecektir:

//address[position()=1]/child::node()[position()=3]/text()

Eğer sorgu sonuçları dönmüyorsa kör SQL enjeksiyon saldırısına benzer biçimde doğru (true) ve yanlış (false) koşullar kullanılarak karakter karakter bir verinin içeriğini tahmin etmek mümkündür. Örneğin “Ali” kullanıcısının password’ünün ilk karakteri “a” ise aşağıdaki koşulun doğru sonuçlanacaktır:

‘ or substring(//address[position()=1]/child::node()[position()=3]/text(),1,1)=’a’ and ‘a’=a

Xpath Enjeksiyon Açıklıklarının Tespiti


SQL enjeksiyon tespiti için kullanılan aşağıdaki test girdileri Xpath sorgu sentaksını bozacağından hataya neden olacaktır:


‘- -

Yine SQL enjeksiyon için kullanılan aşağıdaki test girdileri Xpath sorgusunu değiştireceğinden uygulamanın mantığını etkileyebilecektir:

‘ or ‘a’=’a
‘ and ‘a’=’b
or 1=1
and 1=2

Bu benzerlikler nedeniyle SQL enjeksiyon açıklığı bulunduğundan şüphe ettiğiniz ancak sentaksı doğru tahmin edemediğiniz durumlarda Xpath enjeksiyon ihtimalini de göz önünde bulundurmakta fayda vardır. Aşağıda Xpath açıklıklarını büyük ihtimalle tespit etmek için izlenebilecek denetim adımları bulunmaktadır:
  • Aşağıdaki test metinleri girilerek uygulamanın hata almadan davranışında değişiklik gerçekleştirilip gerçekleştirilemediği araştırılır:
    • ‘ or count(parent::*[position()=1])=0 or ‘a’=’b
    • ‘ or count(parent::*[position()=1])>0 or ‘a’=’b
  • Eğer parametre numerikse aşağıdaki test metinleri de denenebilir:
    • 1 or count(parent::*[position()=1])=0
    • 1 or count(parent::*[position()=1])>0
  • Eğer yukarıdaki girdiler hataya neden olmadan uygulama davranışında farklılaşmaya neden olabiliyorsa XML veri deposundaki veriler karakter karakter elde edilebilir. Bunun için ilk olarak üst nokta adı karakter karakter belirlenir:
    • substring(name(parent::*[position()=1]),1,1)=’a’
  • Üst nokta adı belirlendikten sonra aşağıdaki sorgularla karakter karakter tüm XML ağacı elde edilebilir:
    • substring(//ustnokta[position()=1]/child::node()[position()=1]/text(),1,1)=’a’


<<Önceki Bölüm                                                                                                      Sonraki Bölüm>>