Bayrağı Ele Geçirme Mücadelesi için Haftada 16 Milyon İndirmeye Sahip Node.js Paketinin Sıfır Gününü Keşfetmek


Eugene Lim
CSG @ GovTech

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!

npm’nin son istatistikleri

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-streamCopay 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.logo 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’s kod farkı

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.

Grep.app’te JavaScript filtresiyle arama

İş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-parserbirden 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ı:

bu indirme istatistikleri

Bunun nedeni neredeyse 2000 bağımlı paketin kullanılmasıdır. ininpm 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-nativeetrafı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.

ini’ye bağlı paketler

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!



Source link