GovTech’in Siber Güvenlik Grubu yakın zamanda 4 – 6 Aralık 2020 tarihleri arasında STACK the Flags Siber Güvenlik Bayrağı Yakalama (CTF) yarışmasını düzenledi. Web alanı için ekibim, sızma testleri sırasında karşılaştığımız gerçek dünya sorunlarını ele alan zorluklar oluşturmak istedi. Devlet web uygulamaları ve ticari kullanıma hazır ürünler.
Deneyimlerime göre, önemli sayıda güvenlik açığı, geliştiricilerin kodlarında kullandıkları üçüncü taraf kitaplıklara aşina olmamalarından kaynaklanmaktadır. Bu kitaplıkların kötü niyetli aktörler tarafından ele geçirilmesi veya güvenli olmayan bir şekilde uygulanması durumunda geliştiriciler farkında olmadan uygulamalarına yıkıcı zayıflıklar getirebilir. SolarWinds tedarik zinciri saldırısı bunun en iyi örneğidir.
Web geliştiricileri için en popüler programlama dillerinden biri olan Node.js ekosistemi, üçüncü taraf kitaplıklarla ilgili sorunlardan payına düşeni aldı. Daha çok npm olarak bilinen Düğüm paket yöneticisi, birden fazla hizmet sunar yüz milyar Aylık paketler ve bir buçuk milyona yakın paket barındırıyor. Paket yöneticilerini bu kadar büyük yapan şeylerden biri de ağaç benzeri bağımlılık yapısıdır. Projenize her paket yüklediğinizde, o paketin bağımlılıklarını ve bağımlılıklarını da yüklersiniz; bazen düzinelerce paketle sonuçlanırsınız!
Bu zincirdeki tek bir bağımlılığın tehlikeye atılması veya korunmasız hale gelmesi, tüm ekosistem üzerinde kademeli etkilere yol açabilir. 2018 yılında yaygın olarak kullanılan bir npm paketi, event-stream
Copay bitcoin cüzdanını hedef alan bitcoin çalma kodunu ekleyen kötü niyetli bir yazar tarafından ele geçirildi. Saldırganın aklında tek bir hedef olsa da popüler event-stream
Paket, kötü amaçlı kodun keşfedilmesinden önceki 2,5 ay içinde yaklaşık 8 milyon kez indirildi. 2019 yılında adında bir araç sundum. npm-scan
Black Hat Asia’da kötü amaçlı paketleri tanımlamaya çalışıyordu ancak npm’nin bunu sistematik bir şekilde çözmesi gerektiği açıktı. Neyse ki, npm ekosistemi o zamandan bu yana önemli ölçüde gelişti. npm audit
özellik ve daha aktif izleme.
Bu bağlamı göz önünde bulundurarak, savunmasız bir npm paketi kullanan bir meydan okuma tasarlamaya koyuldum. Ek olarak, prototip kirlilik güvenlik açığından yararlanmak istedim. Basitçe ifade etmek gerekirse, prototip kirliliği, bir uygulamadaki Javascript nesnelerinin özelliklerinin, nesnelerin prototiplerini kirleterek üzerine yazılmasını içerir. Örneğin, eğer üzerine yazarsam toString
bir nesnenin özelliği ve bu nesneyi yazdıran console.log
o nesnenin gerçek dize temsili yerine üzerine yazılan değerimin çıktısını alır. Bu, uygulamaya bağlı olarak kritik sorunlara yol açabilir; üzerine yazarsam ne olacağını hayal edin. isAdmin
bir mülk user
her zaman olmaya itiraz ediyorum true
! Bununla birlikte, prototip kirliliğinin etkisi uygulama bağlamına bağlı kaldığından, bundan nasıl doğru şekilde yararlanılacağını çok az kişi biliyor.
Daha sonra, prototip kirliliğine karşı savunmasız olan npm paketlerini bulmak için iki taktik uyguladım: desen eşleştirme ve işlevsellik gruplaması.
Desen Eşleştirme
Savunmasız kod yazıldığında, genellikle statik tarayıcılar tarafından yakalanabilecek tanınabilir kalıplara düşer. Bu, açık kaynak kod tabanlarını güvenli olmayan kod kalıplarına karşı tarayan GitHub CodeQL gibi birçok aracın temelini oluşturur. Tarayıcılar güvenlik açıklarını önceden keşfetmek için savunma amaçlı kullanılırken, saldırganlar da açık kaynak kodundaki bildirilmemiş güvenlik açıklarını keşfetmek için kendi kalıp eşleştirmelerini gerçekleştirebilir.
Tercih ettiğim araç, GitHub’da yarım milyondan fazla halka açık depoyu tarayan hızlı bir normal ifade arama motoru olan grep.app’ti. Çoğu npm paketi kodunu GitHub’da barındırdığından, bunun en azından birkaç savunmasız paketi ortaya çıkaracağından emindim. Bir sonraki adım, kullanışlı bir normal ifade modeli tanımlamaktı. NPM paketlerinde daha önce açıklanan prototip kirlilik güvenlik açıklarını araştırdım ve Ocak 2020’de Snyk’in bu güvenlik açığına ilişkin tavsiyesini buldum. dot-prop
paket. Daha sonra, güvenlik açığını kapatan GitHub taahhüdünü kontrol ettim.
dot-prop
Aşağıdaki anahtarları kara listeye alarak prototip kirliliği güvenlik açığını kapattı:
const disallowedKeys = [
‘__proto__’,
‘prototype’,
‘constructor’
];
Burada doğası gereği savunmasız olan belirgin bir kod modeli yoktu; oydu eksiklik onu savunmasız hale getiren bir kara liste. Biraz uzaklaştırmaya ve ne olduğuna odaklanmaya karar verdim. dot-prop
bu ilk etapta bir kara liste gerektirdi mi? Paket açıklamasına göre, dot-prop
nokta yolu kullanarak iç içe geçmiş bir nesneden bir özelliği almak, ayarlamak veya silmek için kullanılan bir pakettir.
Örneğin şöyle bir özellik ayarlayabilirim:
// Setter
const object = {foo: {bar: 'a'}};
dotProp.set(object, 'foo.bar', 'b');
console.log(object); // => {foo: {bar: 'b'}}
Bununla birlikte, aşağıdaki kavram kanıtı, aşağıdakileri kullanarak bir prototip kirliliğini tetikleyecektir: dot-prop
‘S set
işlev:
const object = {};
console.log("Before "+ object.b); // => Undefined
dotProp.set(object, '__proto__.b', true);
console.log("After "+ {}.b); // => true
Bu işe yaradı çünkü işlev ile ilgili dot-prop
noktalı yol dizesini bir nesnedeki anahtarlar olarak ayrıştırmak ve bu anahtarların değerlerini ayarlamaktı. Prototip kirliliği hakkında bildiklerimize göre, belirli anahtarlar kara listeye alınmadığı sürece bu durum doğası gereği tehlikelidir.
Bunu düşündükten sonra diğer noktalı yol ayrıştırıcılarıyla eşleşen kalıpları aramaya karar verdim. dot-prop
kullanılmış path.split('.')
noktalı yolları bölmek için, ancak bunu daha sonra keşfettim key.split('.')
diğer noktalı yol ayrıştırıcıları tarafından da yaygın olarak kullanıldı. Bu yaklaşımla birkaç savunmasız paket keşfettim, ancak bu, bir kara listenin kullanılıp kullanılmadığını doğrulamak için her paketin kodunu manuel olarak incelememi gerektirdi. Ek olarak, noktalı yol ayrıştırıcılarının tümü kullanılmaz key
veya path
noktalı yol dizesini belirtmek için, muhtemelen çok daha fazlasını kaçırdım.
İşlevsellik Gruplaması
Daha iyi bir yaklaşımın, npm paketlerini işlevlerine (önceki durumda noktalı yol ayrıştırıcıları) göre gruplandırmak olacağını fark ettim. Bunun nedeni, uygun kara listeler veya korumalar uygulanmadığı sürece bu tür işlevlerin varsayılan olarak güvenli olmamasıdır. Noktalı yol ayrıştırıcılarını inceledikten sonra çok daha verimli bir paket grubuyla karşılaştım: yapılandırma dosyası ayrıştırıcıları.
Yapılandırma dosyaları YAML, JSON ve daha fazlası gibi çeşitli formatlarda gelir. Bunlardan TOML ve INI birbirine çok benzer ve şu formatla eşleşir:
[foo]
bar = "baz"
Tipik bir INI ayrıştırıcısı bu dosyayı aşağıdaki nesneye ayrıştırır:
iniParser.parse(fs.readFileSync('./config.ini', 'utf-8')) // => { foo: { bar: 'baz' } }
Ancak ayrıştırıcı bir kara liste kullanmadığı sürece aşağıdaki yapılandırma dosyası prototip kirliliğine yol açacaktır:
[__proto__]
polluted = "polluted"iniParser.parse(fs.readFileSync('./payload.ini', 'utf-8')) // => { }
console.log(parsed.__proto__) // => { polluted: 'polluted' }
console.log({}.polluted) // => polluted
console.log(polluted) // => polluted
Aslında, bu tür ayrıştırıcılarda prototip kirliliği güvenlik açıkları daha önce rapor edilmişti, ancak bu yalnızca geçici olarak rapor edilmişti. Paketleri geniş ölçekte hızlı bir şekilde test etmek için kavram kanıtlama kodumu oluşturdum, ardından diğer ayrıştırıcıları keşfetmek için npm’nin arama işlevini kullandım. Arama işlevi aşağıdaki gibi etiketlere göre aramayı destekler: keywords:toml
veya keywords:toml-parser
birden fazla savunmasız paketi hızlı bir şekilde keşfetmemi sağlıyor.
Bunlardan biri şuydu ini
şaşırtıcı bir içeriğe sahip basit bir INI ayrıştırıcısı on altı milyon haftalık indirme sayısı:
Bunun nedeni neredeyse 2000 bağımlı paketin kullanılmasıdır. ini
npm CLI’nin kendisi de dahil! O zamandan beri npm
Her varsayılan Node.js kurulumuyla birlikte paketlenmiş olarak gelir; bu şu anlama gelir: Node.js’nin her kullanıcısı savunmasız olanı indiriyordum ini
paket de. Diğer önemli bağımlılar arasında Angular CLI ve sodium-native
etrafında bir sarmalayıcı libsodium
kriptografi kütüphanesi. Bu paketler dahilken ini
bir bağımlılık olarak riskleri nasıl olduğuna bağlıydı ini
kullanıldı; eğer güvenlik açığı bulunan işlevi çağırmamışlarsa güvenlik açığı tetiklenmeyecektir.
Kullanmamış olmama rağmen ini
Bu zorluk için, savunmasız paketlerin listesini sorumlu bir şekilde npm’ye açıkladığımdan emin oldum.
npm, şu anda beklemede olan bir güvenlik açığı açıklama programı da dahil olmak üzere, sağlam ve sorumlu bir açıklama sürecini destekler. Açık kaynaklı güvenlik şirketi Snyk ayrıca, açıklamaları koordine etmek için kullandığım basit bir güvenlik açığı açıklama formu da sağlıyor. Neyse ki, açıklama süreci ini
Geliştiricinin güvenlik açığını iki gün içinde kapatmasıyla sorunsuz bir şekilde ilerledi.
- 6 Aralık 2020: Snyk’e ilk açıklama
- 7 Aralık 2020: Snyk’ten ilk yanıt
- 8 Aralık 2020: Geliştiriciye Açıklama
- 10 Aralık 2020: Yama yayınlandı
- 10 Aralık 2020: Açıklama yayınlandı
- 11 Aralık 2020: CVE-2020–7788 atandı
Diğer paketler sorumlu bir şekilde ifşa ediliyor veya ifşa edildi, örneğin: multi-ini
.
Güvenlik açığı avlama süreci, açık kaynak paketlerinin hem güçlü hem de zayıf yönlerini ortaya çıkardı. Üçüncü taraflarca yazılan açık kaynak paketleri güvenlik açıkları açısından analiz edilebilse veya kötü niyetli kişiler tarafından ele geçirilebilse de geliştiriciler aynı zamanda güvenlik açıklarını hızlı bir şekilde bulabilir, raporlayabilir ve yamalayabilir. Paketleri kullanmadan önce incelemek kuruluşların ve geliştiricilerin sorumluluğundadır. Herkes kodu doğrudan incelemek için gereken kaynakları karşılayamasa da, bir paketin durumunu tahmin etmek için güncelleme sıklığı ve katkı geçmişi gibi ölçümleri kullanan Snyk Advisor gibi ücretsiz araçlar vardır. Geliştiriciler ayrıca, özellikle farklı bir yazar tarafından yazılmışsa veya düzensiz bir zamanlamada yayınlanmışsa, paketlerin yeni sürümlerini de incelemelidir.
Uzun vadede açık kaynak paket güvenliğine verilecek kolay yanıtlar yoktur. Bununla birlikte kuruluşlar, projelerini etkili bir şekilde güvence altına almak için makul önlemler uygulayabilirler.
Not: Katılımcılarımızdan biri olan Yeo Quan Yang, bir şablon oluşturma motorunda uzaktan kod yürütme aygıtı içeren bir pakette prototip kirliliğini zincirlemek için amaçlanan çözümü gösteren, sorunla ilgili mükemmel bir yazı yayınladı. Buraya göz atın!