DOM Clobbering

Omer Citak - 08 Mart 2017 -

Clobbering’i bilgisayar terminolojisi çerçevesinde Türkçe’ye çevirdiğimizde “üzerine yazmak” gibi bir manaya geliyor. Bu yazıda kastettiğimiz olay tam da bu aslında. Bir DOM objesinin başka bir DOM objesi üzerine sorgusuz sualsiz yazması sonucu ortaya çıkan duruma verilen isimdir DOM Clobbering.

DOM Clobbering

DOM Nedir?

Document Object Model, "DOM", "Belge Nesnesi Modeli" anlamlarına da gelmektedir. İnternet tarayıcıları girilen internet sayfasını bir belge, bu belge (sayfa) içerisinde bulunan tüm elemanları da nesne olarak kabul eder. Buna göre resim, yazı, form gibi tüm elemanlar nesnedir. İşte DOM sayfa içindeki herhangi bir nesnenin özelliğine müdahele edebilmemize, nesne özelliklerini değiştirebilmemize olanak sağlar. Bunu yapabilmek için de JavaScript gibi bazı script dilleri kullanmamız gerekir.*

Yani; DOM vasıtası ile HTML dokümanındaki tüm nesneler üzerinde işlem yapabiliriz. Aşağıda Developer Tools tarafından DOM nesnelerinin nasıl highlight edildiğini yani belirginleştirilip ön plana çıkartıldığını görebilirsiniz.

DOM Clobbering-1

netsparker.com.tr'ye bir request’te bulunduğunuzda server size response olarak bir takım header bilgileri ve istekte bulunduğumuz sayfanın HTML kodunu döndürecektir. Kullandığınız browser bu HTML kodunu yorumlayıp DOM’ları üretecek ve yukarıdaki resimdeki gibi bir hal alacaktır.

Örneğin yukarıdaki resimdeki "id" attribute’ünün değeri “products-section" olan “div" nesnesini aşağıdaki gibi bir seçici (selectors) ile seçebiliriz.

var dom = document.getElementById("products-section");

Clobbering Nedir?

Clobbering’i bilgisayar terminolojisi çerçevesinde Türkçe’ye çevirdiğimizde “üzerine yazmak" gibi bir manaya geliyor. Bu yazıda kastettiğimiz olay tam da bu aslında. Bir DOM objesinin başka bir DOM objesi üzerine sorgusuz sualsiz yazması sonucu ortaya çıkan duruma verilen isimdir DOM Clobbering.

DOM Clobbering

Araştırma ilk olarak Unsafe Names for HTML Form Controls adı ile Garrett Smith tarafından yayınlandı.

Browserlar, FORM elemanlarının name ve id değerlerini form'un bir property'si gibi değerlendiriyor. Eğer FORM'un aynı adı taşıyan bir property’si mevcutsa, FORM elemanının değeri ile bu property eziliyor.

Browserlar benzer biçimde, diğer elemanların name ve id değerlerini de document nesnesinin bir property'si gibi ekliyor, bazı implementasyonlarda ise bu değerleri global scope'da bir değişken olarak oluşturuyor.

Yine aynı şekilde, document nesnesinin aynı adı taşıyan bir property'si varsa ya da global scope'da aynı adı taşıyan bir değişken varsa çakışma oluyor ve eleman değeri ile bu değer eziliyor/üzerine yazılıyor.

Aşağıdaki örnekler ile yukarıda anlatılanları netleştirelim.

Örnek 1

<form action="">
	<input type="text" value="n3tsp4rk3r">
	<input type="submit">
</form>

Yukarıdaki formu göndermek için aşağıdaki JavaScript kodunu çalıştırmalıyız.

<script>
	document.forms[0].submit();
</script>

Bu şekilde yukarıdaki form başarıyla gönderilmiş olacak. Ancak formu aşağıdaki gibi revize edip aynı JavaScript kodu ile tekrar göndermeye çalıştığımızda bakalım ne olacak?

<form action="">
	<input type="text" value="n3tsp4rk3r">
	<input type="submit" name="submit">
</form>

DOM Clobbering-2

Ekran görüntüsünde görüldüğü üzere JavaScript “submit" fonksiyonunu çalıştırıp formu göndereceğine, form içerisindeki name değeri “submit" olan nesneyi seçiyor.

Örnek 2

<form action="test2.html" name="nsForm">
	...
</form>

<script>
    document.nsForm.submit();
</script>

Oluşturulan form nesnesinin name’i “nsForm" olduğundan doğrudan doküman üzerinden “document.nsForm" ile formu seçip, “submit" metodunu çalıştırabiliriz.

Ancak formu aşağıdaki gibi revize edip aynı JavaScript kodu ile tekrar göndermeye çalıştığımızda bakalım ne olacak?

<form action="test2.html" name="getElementById">
	...
</form>

<div id="netsparker"></div>

<script>
	document.getElementById('netsparker');
</script>

DOM Clobbering-3

Gerçek Dünyadan Örnekler 1 - Gist

GitHub’ın kod paylaşım servisi olan Gist üzerinde Mathias Karlsson adındaki araştırmacı DOM Clobbering zafiyetini keşfetmiş. Zafiyet tam olarak şöyle;

JavaScript tarafında bir yerde şu şekilde bir kod bulunuyor;

<script>
	…….
	document.querySelector….
	…….
</script>

Gist’te yorum yaparken görsel yerleştirebiliyor ve bu görsele custom attribute tanımlanabiliyor. Bundan dolayı Mathias şöyle bir görsel yerleştirme kodu kullanmış:

<img src='something.png' name='querySelector'>

Yukarıdaki JavaScript kodu ulaşması gereken asıl querySelector nesnesi yerine Mathias’ın oluşturduğu querySelector nesnesine ulaştığından sayfa olması gerektiği gibi çalışmadı ve Gist bir süreliğine devre dışı kaldı.

Gerçek Dünyadan Örnekler 2 - CKEditor

CKEditor’ün dahil edildiği sayfada kullanılmaya başlanması için aşağıdaki gibi bir JavaScript kodu yazılmalıdır.

<script type="text/javascript">
	var doc = document;
	doc.open();
	doc.write(window.opener._cke_htmlToLoad);
</script>

Yukarıdaki kodun olduğu sayfayı referans alan sayfaya aşağıdaki gibi bir HTML kodu yazıldığında, ulaşılması gereken asıl _cke_htmlToLoad nesnesi yerine aşağıdaki _cke_htmlToLoad nesnesine ulaşılacağından sayfanın XSS zafiyeti ortaya çıkacaktır.

<a href="plugins/preview/preview.html#<svg onload=alert(1)>" id="_cke_htmlToLoad" target="_blank">test</a>

Kaynaklar