Yazılım bileşen analizi: bağımlılıklardaki gizli risk
- Seçtiğin birkaç paket yüzlerce dolaylı bağımlılık çeker; SCA taraması bu ağacı açık kayıtlarıyla eşleştirir ve gerçek riski sıralar.
- npm audit, pip-audit ve osv-scanner çıktısını satır satır oku. Bulguları CVSS, EPSS, KEV ve erişilebilirliğe göre sırala. Dolaylı bağımlılıktaki açığı overrides ile kapat.
Puan bütün etkinlikleri cevaplayınca hesaba yazılır. Bu dersi tamamlayınca +50 XP alacaksın. Giriş yapmadan ilerlersen puan yalnız bu tarayıcıda durur.
Altay Kargo'nun iade servisi, müşterinin iade talebini alır, etiket basar ve haftalık rapor üretir. Ekip package.json dosyasına yalnız birkaç paket yazdı. Kurulumdan sonra node_modules klasöründe yüzlerce paket duruyor. Bir sabah güvenlik ekibine yeni bir duyuru gelir: yaygın bir yardımcı kütüphanede komut enjeksiyonu bulunmuş.
İlk soru basittir: biz etkileniyor muyuz? Manifest dosyasında arama yapmak bu soruyu cevaplamaz, çünkü açıklı paket orada hiç yazmıyor olabilir. Cevabı yazılım bileşen analizi (SCA, Software Composition Analysis) verir.
SCA aracı uygulamanın bütün bileşenlerini çıkarır ve bilinen açık kayıtlarıyla eşleştirir. Bu derste bağımlılık ağacını okur, üç farklı araçla tarama yapar, bulguları önceliklendirir ve düzeltme yollarını görürsün.
Manifest, kilit dosyası ve bağımlılık ağacı
Doğrudan bağımlılık (direct dependency), manifest dosyasına kendi elinle yazdığın pakettir. npm'de bu dosya package.json, Python'da çoğu zaman requirements.txt ya da pyproject.toml olur. Her doğrudan bağımlılık kendi işi için başka paketler çeker. Bunlara dolaylı bağımlılık (transitive dependency) denir.
Zincir birkaç kat aşağı iner ve sonunda bir ağaç oluşur. Sen ağacın yalnız ilk katını seçersin, gerisini paket yöneticisi çözer. Güvenlik açısından iki kat arasında fark yoktur. Dolaylı paket de senin sürecinde, senin yetkilerinle çalışır.
'O paketi biz kullanmıyoruz' savunması bu yüzden dolaylı katmanda geçmez. Senin kodun onu çağırmasa bile, onu çağıran kütüphane üretimde çalışır.
Manifest çoğu zaman tam sürüm değil, bir aralık yazar. ^2.4.0 yazımı 2.4.0 ve üstündeki, 3.0.0'ın altındaki her sürümü kabul eder. ~2.4.0 ise yalnız 2.4.x yamalarını kabul eder. Aralık yüzünden iki ayrı kurulum iki ayrı ağaç üretebilir. Kilit dosyası (lockfile) bu belirsizliği kapatır.
package-lock.json, poetry.lock ya da Pipfile.lock, o gün çözülen ağacın her düğümünü tam sürümüyle kaydeder. SCA aracının okuması gereken asıl dosya kilit dosyasıdır. Yalnız manifeste bakan bir tarama dolaylı katmanı görmez, aralığın arkasındaki gerçek sürümü de bilmez. Ağacı komut satırında görmek için npm ls --all komutunu çalıştırırsın.
$ npm ls --all [email protected] /srv/iade-servisi ├─┬ [email protected] │ └── [email protected] └─┬ [email protected] └── [email protected]
Ağacı soldan sağa oku. İlk satır projenin kendisidir. En soldaki dallar doğrudan bağımlılıktır: etiket-basici ve rapor-sablon package.json içinde yazar. Bir kat içerideki satırlar dolaylıdır.
lodash, iade servisinin manifestinde hiç geçmez; onu rapor-sablon çeker ve 4.17.20 sürümüne tam sürümle sabitler. Duyuru lodash hakkındaysa, package.json içinde arama yapan ekip hiçbir şey bulamaz. Kilit dosyasında aynı arama açık içeren sürümü hemen gösterir. Bu fark gerçek hayatta pahalıya patladı.
2021 sonunda duyurulan Log4Shell (CVE-2021-44228), Java günlük kütüphanesi log4j-core içindeydi. Birçok ürün bu kütüphaneyi hiç doğrudan seçmemişti, başka bir çerçevenin içinde taşıyordu. Ekipler günlerce 'bizde var mı' sorusunun cevabını aradı.
Etkinlik 1 / 8
Altay Kargo'nun paket listesindeki girdileri doğrudan ve dolaylı bağımlılığa göre ayır.
Önce bir seçeneğe, sonra aşağıdaki uygun kutuya bas. İstersen seçeneği kutuya sürükleyip bırak. Yerini değiştirmek için aynı işlemi tekrarla.
0/4 seçenek yerleşti.
Etkinlik 2 / 8
Altay Kargo'nun paket dosyasında bilinen açık taşıyan sürüme izin veren satırı bul.
npm ile çözümlü tarama
SCA süreci dört adımdır. Araç önce kilit dosyasından tam ağacı çıkarır. Sonra her düğümü adı ve sürümüyle bir açık veritabanında arar; eşleşen kayıt için etkilenen aralığı, önem derecesini ve düzelten sürümü getirir. Üçüncü adımda sen, eşleşen açığın uygulamada gerçekten çalışıp çalışmadığına, yani erişilebilirliğe (reachability) bakarsın.
Dördüncü adımda yama içeren sürüme geçer ya da geçici bir önlem alırsın. npm ilk iki adımı npm audit komutuyla yapar. Komut ağacın özetini kayıt sunucusuna gönderir, sunucu da onu GitHub Advisory Database kayıtlarıyla eşleştirir. İade servisinde komutu çalıştırınca şu rapor gelir.
$ npm audit # npm audit report lodash <=4.17.23 Severity: high Command Injection in lodash - https://github.com/advisories/GHSA-35jh-r3h4-6jhm Regular Expression Denial of Service (ReDoS) in lodash - https://github.com/advisories/GHSA-29mw-wpgm-hmr9 lodash vulnerable to Code Injection via `_.template` imports key names - https://github.com/advisories/GHSA-r5fr-rjxr-66jc lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and `_.omit` - https://github.com/advisories/GHSA-f23m-r3pf-42rh Lodash has Prototype Pollution Vulnerability in `_.unset` and `_.omit` functions - https://github.com/advisories/GHSA-xxjr-mmjv-4gpg No fix available node_modules/lodash rapor-sablon * Depends on vulnerable versions of lodash node_modules/rapor-sablon 2 high severity vulnerabilities Some issues need review, and may require choosing a different dependency.
Raporu yukarıdan aşağı oku. İlk satır paketi ve etkilenen aralığı verir: kurulu lodash, 4.17.23 ve altındaki aralıkta kalıyor. Severity satırı bu paketteki en yüksek önem derecesidir.
Sonraki beş satır beş ayrı kayıttır; her biri bir başlık ve GHSA bağlantısı taşır. İlk kayıt GHSA-35jh-r3h4-6jhm, şablon fonksiyonundaki komut enjeksiyonudur ve CVE-2021-23337 kimliğini de taşır. No fix available satırı yanıltıcı görünür.
Düzelten sürüm vardır, ama npm onu kendisi kuramaz. rapor-sablon lodash'ı tam sürümle sabitler ve paketin daha yeni bir sürümü yoktur. Girintili satırlar zinciri gösterir: rapor-sablon, açıklı lodash sürümüne bağımlıdır. Son satırdaki sayı lodash ile rapor-sablon'u birlikte sayar.
$ npm explain lodash [email protected] node_modules/lodash lodash@"4.17.20" from [email protected] node_modules/rapor-sablon rapor-sablon@"^1.2.0" from the root project
npm explain, bir paketin ağaca neden girdiğini tersten anlatır; npm why da aynı komuttur. İlk iki satır kurulu sürümü ve diskteki yerini verir.
Üçüncü satır, lodash'ı tam olarak 4.17.20 diye isteyen paketin rapor-sablon olduğunu söyler. En alttaki satır zincirin köküdür: rapor-sablon'u package.json içinde ^1.2.0 aralığıyla sen istedin. Düzeltmenin kimde olduğu da buradan çıkar.
Ya rapor-sablon'un bakımcısı sabitlemeyi gevşetir ya da sen ağacı kendi tarafında zorlarsın. Zincir uzunsa her basamak bir girinti daha içeri kayar. Kök satıra kadar okuduğunda hangi doğrudan bağımlılığı değiştireceğini bilirsin.
Etkinlik 3 / 8
Altay Kargo'nun iade servisinde lodash paketini ağaca hangi doğrudan bağımlılığın soktuğunu gösteren npm komutunu yaz.
Etkinlik 4 / 8
Bir SCA sürecinin doğru adım sırasını kur.
Parçalara tıklayarak komutu soldan sağa kur.
Aynı açığın birçok adı: Python ve dil bağımsız tarama
Bir açık tek bir adla yaşamaz. CVE kimliği, sektörün ortak anahtarı olan CVE programından gelir. GHSA kimliği GitHub Advisory Database kaydıdır; npm audit raporundaki bağlantılar bu kayıtlara gider.
PYSEC kimliği, Python paketleri için PyPA'nın tuttuğu açık veritabanından gelir. OSV ise bu kaynakları tek biçimde toplayan açık bir şemadır. Şemadaki aliases alanı, aynı açığın bütün adlarını birbirine bağlar.
Bir araç PYSEC kimliği, başka bir araç GHSA kimliği gösterebilir. İki raporun çeliştiğini sanma; önce takma adları eşle, sonra say. Python tarafında yaygın araç pip-audit'tir. --aliases bayrağı her satıra takma adları ekler.
$ pip-audit -r requirements.txt --aliases Found 5 known vulnerabilities in 1 package Name Version ID Fix Versions Aliases ------ ------- --------------- ------------ ----------------------------------- jinja2 3.1.2 PYSEC-2026-1473 3.1.3 GHSA-h5c8-rqwp-cp95, CVE-2024-22195 jinja2 3.1.2 PYSEC-2026-1474 3.1.4 CVE-2024-34064, GHSA-h75v-3vvj-5mfj jinja2 3.1.2 PYSEC-2026-1472 3.1.5 GHSA-gmj6-6f8f-6699, CVE-2024-56201 jinja2 3.1.2 PYSEC-2026-1475 3.1.5 GHSA-q2x7-8rv6-6q7h, CVE-2024-56326 jinja2 3.1.2 PYSEC-2026-1471 3.1.6 CVE-2025-27516, GHSA-cpwx-vrp4-4pq7
Tabloyu sütun sütun oku. Name ve Version kurulu paketi verir: jinja2 3.1.2. ID sütunu birincil kimliktir ve burada PYSEC biçimindedir.
Fix Versions, o açığı kapatan ilk sürümdür. Aliases sütunu her kaydın CVE ve GHSA karşılığını verir; npm tarafındaki bir raporla karşılaştırırken bu sütunu kullanırsın. Beş satırın beşi aynı pakete aittir ve farklı düzeltme sürümleri gösterir.
Beş ayrı iş açman gerekmez. En yüksek düzeltme sürümüne çıkan tek yükseltme hepsini kapatır. pip-audit varsayılan modda requirements.txt içindeki paketlerin dolaylı bağımlılıklarını da çözer. Bunun için geçici bir sanal ortam kurar ve tam ağacı tarar.
Dil bağımsız bir seçenek osv-scanner'dır. osv-scanner scan source -r . komutu klasörü alt dizinleriyle tarar ve bulduğu her kilit dosyasını OSV veritabanına sorar. Tek bir dosya için --lockfile=package-lock.json yazarsın.
İade servisinde araç, lodash'ın beş kaydını ilişkili kayıtlara göre gruplar ve özette üç açık sayar. Sayı npm audit'ten farklıdır, ama ikisi de aynı paketi işaret eder. osv-scanner bir adım daha atar: çağrı analizi (call analysis).
Go projelerinde varsayılan olarak açıktır ve açıklı fonksiyona senin kodundan bir çağrı yolu olup olmadığını denetler. Rust desteği deneyseldir ve bağımlılıkların derleme betiklerini çalıştırır. Diğer ekosistemlerde erişilebilirlik kararı sende kalır.
$ osv-scanner scan source -r . Scanning dir . Scanned /srv/iade-servisi/package-lock.json file and found 4 packages Total 1 package affected by 3 known vulnerabilities (0 Critical, 1 High, 2 Medium, 0 Low, 0 Unknown) from 1 ecosystem. 3 vulnerabilities can be fixed.
Etkinlik 5 / 8
pip-audit raporunda jinja2 3.1.2 için beş açık var; düzeltme sürümleri 3.1.3, 3.1.4, 3.1.5 ve 3.1.6. Hepsini tek yükseltmeyle kapatmak için çıkman gereken en düşük sürüm ____.
Önceliklendirme: CVSS, EPSS, KEV ve erişilebilirlik
Orta boy bir projede rapor yüzlerce bulgu taşır. Hepsini aynı gün kapatamazsın, sıralaman gerekir. Üç dış sinyal bu sıralamaya yardım eder. CVSS (Common Vulnerability Scoring System), açığın teknik ağırlığını 0 ile 10 arasında puanlar.
Güncel sürümü Kasım 2023'te yayımlanan 4.0'dır, ama birçok kayıt hâlâ 3.1 puanı taşır. EPSS (Exploit Prediction Scoring System), açığın önümüzdeki 30 gün içinde sahada istismar edilme olasılığını tahmin eder ve her gün yeniden hesaplanır. CISA'nın KEV (Known Exploited Vulnerabilities) kataloğu, gerçek saldırılarda kullanıldığı kanıtlanan açıkları listeler. Kısaca CVSS 'ne kadar kötü olabilir', EPSS 'kullanılacak mı', KEV 'kullanıldı mı' sorusunu cevaplar.
Kimlik Bileşen CVSS 3.1 EPSS KEV CVE-2021-44228 log4j-core 10.0 %99,99 var (10.12.2021) CVE-2024-3094 xz (liblzma) 10.0 %85,97 yok CVE-2021-23337 lodash 7.2 %21,33 yok
Tabloyu birlikte oku. Log4Shell üç sinyalde de en üsttedir ve tartışma gerektirmez. xz satırı ilginçtir: CVSS 10, EPSS yüksek, ama KEV kaydı yok. Arka kapı büyük dağıtımların kararlı sürümlerine girmeden yakalandı, yaygın istismar kanıtı da oluşmadı.
lodash satırında CVSS 7.2'dir ve KEV kaydı yoktur. Buna karşın EPSS yüzdelik dilimi 97,5'tir, yani açıkların çok büyük bölümünün önündedir. Sinyaller çeliştiğinde son sözü erişilebilirlik söyler. lodash açığı şablon fonksiyonundadır.
Altay Kargo'nun kodu _.template fonksiyonunu kullanıcı girdisiyle hiç çağırmıyorsa açık erişilemez. Rapor şablonunu müşteri yazıyorsa durum tersine döner ve bulgu aynı gün kapanır. Puanı araç verir, bağlamı sen eklersin.
Derinleş:CVSS 4.0 neyi değiştirdi
CVSS 4.0, 3.1 sürümünün en çok eleştirilen yanlarını düzeltmeye çalışır. Temel gruba Attack Requirements (AT) adında yeni bir ölçüt eklendi. Bu ölçüt, saldırının başarılı olması için hedefte bulunması gereken ön koşulları anlatır; örneğin belirli bir yapılandırma ya da yarış koşulu. User Interaction artık üç değer alır: None, Passive ve Active.
Kullanıcının bilinçli bir işlem yapması ile farkında olmadan bir sayfayı açması ayrı puanlanır. 3.1'deki Scope ölçütü kaldırıldı. Yerine etki, açıklı sistem ve sonraki sistem için ayrı ayrı ölçülür. Böylece bir web uygulaması açığının kullanıcının tarayıcısına etkisi ayrıca görünür.
Temporal grubu Threat adını aldı ve yalnız Exploit Maturity ölçütünü taşır. Yeni Supplemental grubu Safety, Automatable ve Recovery gibi bağlam bilgileri ekler, ama puanı değiştirmez. Puanın hangi gruplarla hesaplandığı da adla belirtilir: CVSS-B yalnız temel puandır, CVSS-BTE tehdit ve ortam bilgisini de içerir. Bir raporda 4.0 puanı gördüğünde etiketin hangisi olduğuna bak.
Etkinlik 6 / 8
SCA taraması, kullanılmayan bir yardımcı fonksiyonda kritik önem dereceli bir açık buluyor. Bu bileşeni doğrudan hiçbir kod yolu çağırmıyor. En doğru öncelik kararı hangisidir?
Etkinlik 7 / 8
Altay Kargo'nun tarama raporundaki bulguları müdahale zamanına göre ayır.
Önce bir seçeneğe, sonra aşağıdaki uygun kutuya bas. İstersen seçeneği kutuya sürükleyip bırak. Yerini değiştirmek için aynı işlemi tekrarla.
0/5 seçenek yerleşti.
Düzeltme yolları ve bakım riski
Bir bulguyu kapatmanın dört yolu vardır. Birincisi doğrudan bağımlılığı yama içeren sürüme yükseltmektir; npm audit fix bunu manifestteki aralığın içinde kalarak yapar. İkincisi dolaylı bağımlılığı zorlamaktır.
package.json içindeki overrides alanı, ağacın derinindeki bir paketi senin seçtiğin sürüme çeker. Üçüncüsü geçici hafifletmedir: yama gelene kadar açıklı özelliği kapatır ya da girdiyi daraltırsın.
Dördüncüsü etkilenmezlik beyanıdır. VEX (Vulnerability Exploitability eXchange) belgesi, bir açığın ürünü neden etkilemediğini gerekçesiyle kaydeder; örneğin açıklı kod çalışma yolunda değildir. Tarayıcılar bu belgeyi okuyup bulguyu raporda susturabilir. Altay Kargo, rapor-sablon'un yeni sürümünü beklemeden lodash'ı overrides ile yükseltir.
// package.json
{
"name": "iade-servisi",
"dependencies": { "rapor-sablon": "^1.2.0" },
"overrides": { "lodash": "4.18.1" }
}
$ npm install
$ npm explain lodash
[email protected] overridden
node_modules/lodash
overridden lodash@"4.18.1" (was "4.17.20") from [email protected]
node_modules/rapor-sablon
rapor-sablon@"^1.2.0" from the root project
$ npm audit
found 0 vulnerabilitiesÇıktıdaki overridden ibaresi, sürümün senin kararınla değiştiğini gösterir. Parantezdeki was "4.17.20", rapor-sablon'un asıl isteğidir. npm audit artık temiz döner. Override yine de bir ara çözümdür.
rapor-sablon 4.18 serisiyle test edilmedi; testlerini çalıştır ve bakımcıya sabitlemeyi gevşetmesi için bir kayıt aç. Üç hata sık görülür. Birincisi npm audit fix --force komutudur. Bu bayrak gerekirse büyük sürüm atlar ve raporda bunu outside the stated dependency range diye yazar; kırılan bir API gözden geçirilmeden üretime gider.
İkincisi yalnız manifesti taramaktır. Üçüncüsü geliştirme bağımlılığını üretimle karıştırmaktır. npm audit --omit=dev yalnız üretim ağacını tarar, ama derleme makinesindeki test araçlarını da ayrıca izlersin.
Her risk bir CVE kaydıyla gelmez. Bakımı bırakılmış bir bileşen (CWE-1104) yeni açıklar için yama da almaz. Yeni bir bağımlılık eklemeden önce OpenSSF'in Concise Guide belgesindeki sorulara bak.
Bu pakete gerçekten ihtiyacın var mı? Adı ve deposu gerçek mi? Son on iki ayda bakım görmüş mü, birden fazla bakımcısı var mı, lisansı açık mı? OpenSSF Scorecard bu soruların bir bölümünü otomatik ölçer.
scorecard --repo=github.com/<kurum>/<depo> komutu Maintained, Code-Review, Pinned-Dependencies ve Vulnerabilities gibi kontrolleri 0 ile 10 arasında puanlar. Puan bir hüküm değil, inceleme listesidir. Tek bakımcılı ve az kullanılan bir paket, kodu temiz olsa bile risk taşır.
Derinleş:xz-utils arka kapısı: güvenin istismarı
xz, Linux dağıtımlarında yaygın bir sıkıştırma aracıdır ve liblzma kütüphanesini taşır. Proje uzun süre tek bir gönüllü bakımcıya dayandı. 2021'den başlayarak yeni bir katkıcı düzenli ve yararlı katkılar yaptı. Aynı dönemde başka hesaplar bakımcıya yavaşlıktan şikâyet eden mesajlar yazdı ve yeni bir yardımcı bakımcı istedi.
Yeni katkıcı zamanla sürüm çıkarma yetkisi aldı. 2024 başında yayımlanan 5.6.0 ve 5.6.1 sürümlerinin dağıtım arşivine, depoda bulunmayan değiştirilmiş bir derleme betiği girdi. Betik, depodaki test dosyalarına gizlenmiş yükü derleme sırasında kütüphaneye yerleştiriyordu.
Hedef, bazı dağıtımlarda SSH sunucusunun yüklediği liblzma idi. 29 Mart 2024'te bir geliştirici SSH girişlerinin yarım saniye kadar yavaşladığını fark etti, izi sürdü ve durumu açık güvenlik listesine bildirdi. Açık CVE-2024-3094 kimliğini aldı.
Olay iki ders bıraktı. Bakımcı yorgunluğu bir güvenlik riskidir. Depodaki kodla dağıtılan arşiv de aynı şey değildir; derlemeyi kaynaktan yeniden üretmek bu farkı yakalar.
Etkinlik 8 / 8
Doğru mu, yanlış mı?
Bir konteyner imajının SCA taramasında yalnız uygulama bağımlılıkları kontrol edilir, işletim sistemi paketleri kapsam dışıdır.
Okumayı istediğin sırayla sürdürebilirsin. Ders, bütün etkinlikleri cevapladığında tamamlanır.
- Etkinlik 1· Manifest, kilit dosyası ve bağımlılık ağacı
- Etkinlik 2· Manifest, kilit dosyası ve bağımlılık ağacı
- Etkinlik 3· npm ile çözümlü tarama
- Etkinlik 4· npm ile çözümlü tarama
- Etkinlik 5· Aynı açığın birçok adı: Python ve dil bağımsız tarama
- Etkinlik 6· Önceliklendirme: CVSS, EPSS, KEV ve erişilebilirlik
- Etkinlik 7· Önceliklendirme: CVSS, EPSS, KEV ve erişilebilirlik
- Etkinlik 8· Düzeltme yolları ve bakım riski