Prototype Pollution Nedir?
Prototype pollution, saldırganların JavaScript’teki genel prototiplere istedikleri özellikleri ekleyebilmesine izin veren bir güvenlik açığıdır. Bu sayede eklenen özellikler uygulamadaki diğer nesneler tarafından devralınır ve istenmeyen davranışlara yol açabilir.
Prototype Pollution çoğunlukla tek başına doğrudan istismar edilemese de, saldırgana normalde erişilemeyen obje özelliklerini ele geçirip kontrol etme imkânı tanır. Eğer uygulama bu saldırgan kontrollü özelliği güvensiz bir şekilde kullanırsa, durum diğer zafiyetlerle zincirlenerek tehlikeli sonuçlara yol açabilir. İstemci tarafında bu genellikle DOM tabanlı XSS ile sonuçlanır; sunucu tarafındaki bir prototype pollution ise RCE gibi daha ciddi etkiler doğurabilir.
Prototype Pollution Nasıl Oluşur?
Prototype pollution genellikle şu şekilde ortaya çıkar: uygulama, kullanıcıdan gelen bir nesneyi anahtarlarına bakmadan ve temizlemeden mevcut bir nesneyle derinlemesine birleştirir. Böyle bir durumda saldırgan __proto__ gibi özel bir anahtar göndererek, içine istedikleri alt özellikleri koyabilir.
JavaScript’te __proto__ özel davranır; bu yüzden merge işlemi, saldırganın eklediği alt özellikleri hedef nesneye değil, o nesnenin prototipine yazabilir. Bu sayede tüm nesnelerin miras aldığı prototip, saldırgan kontrollü zararlı özelliklerle dolabilir ve uygulama bu özellikleri kullandığında tehlikeli sonuçlar ortaya çıkabilir.
Her prototip kirletilebilir, ama en sık hedeflenen Object.prototype’tır.
Başarılı bir sömürü için üç şey gerekir: (1) prototipi kirletmeyi sağlayan bir giriş (source), (2) bu kontrol edilen değerin tehlike yaratacağı bir yer (sink — ör. DOM insertion veya eval benzeri), ve (3) uygulamada bu değerin filtrelenmeden kullanıldığı bir “gadget”.
Prototype Pollution Kaynakları
Prototype Pollution kaynağı , prototip nesnelere rastgele özellikler eklemene izin veren, kullanıcı tarafından kontrol edilebilen herhangi bir girdi türüdür. En yaygın kaynaklar şunlardır:
URL: Sorgu parametreleri veya fragment (hash) üzerinden gelen veriler
JSON tabanlı girişler: API veya web servislerinden alınan JSON verileri
Web mesajları: postMessage gibi tarayıcılar arası iletişimle gelen veriler
URL Üzerinden Prototype Pollution
Saldırgan tarafından oluşturulmuş bir sorgu dizesi içeren aşağıdaki URL'i ele alalım:
Kod:
https://vulnerable-website.com/?__proto__[evilProperty]=payload[/SIZE][/CENTER][/SIZE][/CENTER][/SIZE][/CENTER][/SIZE][/CENTER]
[SIZE=4][CENTER][SIZE=4][CENTER][SIZE=4][CENTER][SIZE=4][CENTER]
URL parametreleri anahtar-değer çiftlerine ayrıldığında, bazı URL parser’lar __proto__’yu normal bir string olarak yorumlayabilir. Ancak, bu anahtarlar ve değerler daha sonra mevcut bir nesneye özellik olarak merge edilirse ne olacağına bakalım.
İlk akla gelen düşünce, __proto__ özelliği ve içindeki evilProperty’nin hedef nesneye şu şekilde eklenmesidir:
Kod:
{
existingProperty1: 'foo',
existingProperty2: 'bar',
__proto__: {
evilProperty: 'payload'
}
}
Fakat gerçek durum farklıdır. Recursive merge işlemi sırasında, evilProperty şu şekilde atanabilir:
Kod:
targetObject.__proto__.evilProperty = 'payload';
Bu atama sırasında JavaScript motoru __proto__’yu prototip getter’ı olarak yorumlar. Sonuç olarak evilProperty değeri hedef nesneye değil, döndürülen prototip nesnesine atanır. Hedef nesne varsayılan Object.prototype’u kullanıyorsa, artık runtime’daki tüm nesneler evilProperty özelliğini devralır tabi kendi nesnelerinde aynı anahtara sahip değillerse.
Pratikte, evilProperty isimli bir özellik eklemek genellikle doğrudan bir etki yaratmaz. Ancak saldırgan aynı yöntemi, uygulamanın veya kullanılan kütüphanelerin kullandığı özellikleri prototip üzerinde kirletmek için kullanabilir.
JSON Girdisi Üzerinden Prototype Pollution
Kullanıcı kontrollü nesneler genellikle JSON string’lerinden JSON.parse() ile oluşturulur. İlginç olan, JSON.parse()’in JSON içindeki herhangi bir anahtarı — örneğin __proto__ — normal bir string olarak değerlendirmesidir. Bu da prototype pollution için başka bir potansiyel vektör sağlar.
Örnek: Bir saldırgan web mesajı aracılığıyla aşağıdaki kötü niyetli JSON’u enjekte edebilir:
JSON:
{
"__proto__": {
"evilProperty": "payload"
}
}
Bu JSON, JSON.parse() ile bir JavaScript nesnesine dönüştürüldüğünde, ortaya çıkan nesne gerçekten __proto__ anahtarına sahip olur:
Kod:
const objectLiteral = {__proto__: {evilProperty: 'payload'}};
const objectFromJson = JSON.parse('{"__proto__": {"evilProperty": "payload"}}');
objectLiteral.hasOwnProperty('__proto__'); // false
objectFromJson.hasOwnProperty('__proto__'); // true
Prototype Pollution Sink
Prototype pollution zafiyeti, yalnızca prototip üzerinde kontrol sağlamakla kalmaz; bu kontrolün bir saldırıya dönüşebilmesi için sink olarak adlandırılan noktaların olması gerekir. Sink, saldırganın etkisini gösterebileceği bir JavaScript fonksiyonu veya DOM elemanıdır. Örneğin, istemci tarafında DOM XSS saldırıları buna örnek gösterilebilir.
Bu tür zafiyetler sayesinde, normalde kullanıcı tarafından değiştirilemeyen özellikleri kontrol edebilirsin. Uygulama geliştiricileri prototype pollution’a aşina değilse, bu özelliklerin güvenli olduğunu varsayabilir. Sonuç olarak, bu değerler üzerinde sadece sınırlı filtreleme veya doğrulama yapılır ve saldırganın işini kolaylaştırır.
Prototype Pollution Gadgets
Bir gadget, prototype pollution açığının gerçek bir saldırıya dönüşmesini sağlayan özelliktir. Yani şunları karşılayan herhangi bir özellik gadget sayılır:
-Uygulama tarafından güvensiz kullanılması: Örneğin, doğrudan bir sink’e filtrelenmeden aktarılması.
-Saldırgan tarafından kontrol edilebilir olması: Nesnenin, prototipe saldırganın eklediği sahte versiyonu miras alabiliyor olması.
Güvenli web uygulamaları, nesnelerin prototipini özellikle null olarak ayarlayarak bu riski ortadan kaldırabilir. Böylece nesne, prototipten hiçbir özellik devralmaz.
Konum bu kadardı. İlginiz için teşekkür ederim, iyi forumlar dilerim.
-Kryzlo-



