İçeriğe geç
Sedat Özdemir
Yazılar

appsec

Paket Yöneticine Güvenmek mi? Tedarik Zincirinde Truva Atı Beslemek

SCA araçlarına güvenip uyumak, pimi çekilmiş el bombasını yastık altına koymaktır. Tedarik zinciri güvenliğinde neden hala sınıfta kalıyoruz?

Sedat Özdemir
· 4 dk okuma

Herkes SCA (Software Composition Analysis) araçlarını öve öve bitiremiyor, CI/CD pipeline'ına iki tane açık kaynak tarayıcı ekleyince 'tamam abi biz güvenliyiz' moduna giriyorlar. Açık konuşayım: Sadece bilinen CVE'leri tarayan bir araçla supply chain güvenliği sağladığını sanmak, kapıya kilit asıp anahtarı paspasın altına bırakmaktan farksızdır. Hatta daha beteri, o anahtarın kopyasını saldırgana bizzat kuryeyle göndermektir. Prod ortamında 'npm install' veya 'pip install' yaparken terlemeyen mühendis varsa, ya işi çok iyi biliyordur ya da başımıza nelerin gelebileceğinden bihaberdir.

Tarayıcıların Görmediği Kör Nokta: Kötü Niyetli Mantık

Sektördeki en büyük yanılgı şu: 'Pakette bilinen bir zafiyet (CVE) yoksa paket güvenlidir.' Hadi canım sen de! Bir saldırganın mevcut bir pakete 'malicious code' enjekte ettiğini düşünün. Bu kod bir zafiyet değil, tasarım gereği çalışan bir özelliktir. Örneğin, preinstall script'ine eklenen basit bir curl komutu, senin tüm ortam değişkenlerini (environment variables) saldırganın sunucusuna paketleyip gönderebilir. SCA aracın burada neyi bulacak? Hiçbir şeyi. Çünkü ortada 'hatalı kod' yok, 'kötü niyetli mantık' var.

Bir keresinde testCompany bünyesinde yaptığımız bir simülasyonda, sadece dahili bir kütüphanenin ismini taklit ederek (typosquatting) neler yapabileceğimizi gördük. Geliştiricinin elinin sürçmesiyle internal-auth-lib yerine internal-auth-lb yazması, tüm prod credential'larının elimize geçmesi için yetti de arttı bile.

Dependency Confusion: En Klasik Ama En Etkili Numara

Dependency Confusion (Bağımlılık Karışıklığı), Alex Birsan'ın dünyaya tanıttığı ama hala tam anlamıyla çözemediğimiz bir bela. Olay çok basit: Şirket içinde kullandığın @testCompany/cool-feature isimli bir paket var ve sürümü 1.2.0. Eğer ben gider de public registry'ye (npm, PyPI vb.) aynı isimle 99.9.9 sürümünü yüklersem, senin paket yöneticin 'Aaa, daha günceli varmış!' diyerek benim zararlı paketimi şak diye indirir.

Bunu defanged bir örnekle açıklayalım. Bir package.json dosyasında saldırganın neler yapabileceğine bakalım:

{
  "name": "@testCompany/internal-auth-lib",
  "version": "99.9.9",
  "description": "Güvenlik simülasyonu amaçlı zararsızlaştırılmış paket",
  "scripts": {
    "preinstall": "node -e \"const fs = require('fs'); const os = require('os'); const data = { env: process.env, home: os.homedir() }; console.log('Simüle edilen veri toplama:', JSON.stringify(data).substring(0, 50) + '...'); /* Gerçek bir senaryoda bu veri https://attacker-example.com adresine post edilirdi */\""
  }
}

Buradaki preinstall hook'u, paket daha kurulmadan çalışır. Geliştiricinin makinesindeki AWS anahtarları, SSH keyleri ve Kubernetes konfigürasyonları... Hepsi tek bir npm install komutuyla uçup gidebilir.

Transitive Dependencies: Buzdağının Görünmeyen Kısmı

Sen sadece 5 tane kütüphane kullandığını sanırsın ama o 5 kütüphane arka planda 500 tane kütüphaneye bağımlıdır. İşte o 500 kütüphaneden birinin maintainer'ı (geliştiricisi) hesabını çaldırırsa veya 'ben artık bu sektöre küstüm' deyip koda zararlı bir şeyler eklerse ne yapacaksın?

'Colors.js' ve 'faker.js' olaylarını hatırlayın. Geliştiriciler kendi kodlarını sabote ettiler. Binlerce kurumsal uygulama bir anda sonsuz döngülere girdi veya garip çıktılar vermeye başladı. Bu bir 'protesto'ydu, peki ya sessizce veri sızdıran bir saldırı olsaydı? Aylar boyu ruhumuz duymazdı.

Peki Ne Yapacağız? Defans Hattını Kuralım

'Hocam çok korkuttun, ne yapalım, interneti mi kapatalım?' diyenleri duyar gibiyim. Hayır, ama biraz 'paronayak' olacağız. İşte testCompany Red Team gözüyle alınması gereken gerçek önlemler:

  1. Lock Dosyaları Kutsaldır: package-lock.json, poetry.lock veya go.sum dosyalarını asla ignore etmeyin. Bu dosyalar, bağımlılıkların hash değerlerini tutar. Eğer birisi public registry'deki paketi değiştirirse, hash uyuşmazlığı sayesinde bunu fark edersiniz.
  2. Private Registry ve Proxy Kullanın: Tüm dış kütüphaneleri doğrudan internetten çekmek yerine, kendi iç ağınızdaki bir Artifactory veya Nexus üzerinden geçirin. Dışarıdaki paketleri içeri almadan önce bir 'güvenlik kontrol noktasından' geçirmek hayat kurtarır.
  3. Scope Kullanımı: Şirket içi paketlerinizde mutlaka @şirketismi/paket formatını (Scoped Packages) kullanın ve bu scope'u public registry'de üzerinize rezerve edin. Bu, dependency confusion saldırılarını büyük oranda engeller.
  4. Frozen Lockfile CI/CD: Pipeline'larınızda npm install yerine npm ci kullanın. npm ci, lock dosyasını baz alır ve asla onu değiştirmeye çalışmaz. Eğer lock dosyasıyla package.json uyumsuzsa hata verir ve durur.
  5. SBOM (Software Bill of Materials): Uygulamanızın içinde tam olarak ne olduğunu bilmeniz lazım. SBOM araçlarıyla (CycloneDX, SPDX) envanterinizi çıkartın. Hangi paketin hangi sürümü nerede çalışıyor, bir zafiyet çıktığında 'bizde bu var mı?' sorusuna 10 saniyede cevap verebilmelisiniz.

Sahadan Bir Tavsiye

Güvenlik sadece 'tool' işi değil, bir kültür meselesidir. Geliştirici arkadaşım, projesine bir paket eklerken 'bu paketin kaç yıldızı var, en son ne zaman güncellenmiş, arkasında kim var?' diye bakmıyorsa, dünyanın en pahalı SCA aracını da alsanız o supply chain bir noktada kırılır.

Tedarik zinciri saldırıları sinsidir. Kapıyı içeriden açan birileri her zaman olur. Önemli olan, o kapı açıldığında içerideki odaya geçişi engelleyecek bariyerleri (Zero Trust, Network Segmentation) çoktan kurmuş olmaktır.

Unutmayın, zincir en zayıf halkası kadar güçlüdür ve o halka bazen çok sevdiğiniz bir left-pad kütüphanesi olabilir. Hadi şimdi gidip bağımlılıklarınızı bir kontrol edin, bakalım orada tanımadığınız kimler var.

İlgili yazılar