Bir sabah uyandığında, cluster'ındaki tüm podların senin rızan dışında Bitcoin madenciliği yaptığını ve bulut faturanın şirket değerlemesini geçtiğini fark edip o soğuk terleri döktün mü? Eğer dökmediysen, ya çok şanslısın ya da henüz o 'kritik' hata ile tanışmadın. Selam dostum, ben Sedat. Bugün seninle Kubernetes’in o parlak, esnek ve bir o kadar da karmaşık labirentine gireceğiz. Ama elimizde fenerle değil, bir Red Teamer gözlüğüyle bakacağız.
Kubernetes (K8s) dünyasına girdiğimizde hepimiz o muazzam ölçeklenebilirliğe aşık oluyoruz. Ama iş güvenliğe gelince, genelde 'YAML dosyasını kopyala-yapıştır yapayım da çalışsın' kafası baskın çıkıyor. İşte o kopyaladığın YAML dosyası, senin cluster'ının idam fermanı olabilir.
Kube-API Server: Kaleye Açılan Kapı
K8s dünyasında API Server her şeydir. Eğer burayı düzgün korumuyorsan, anahtarı kapının üstünde bırakmışsın demektir. Bir Red Teamer olarak bir cluster'a sızmaya çalışırken ilk baktığım yer https://example-cluster.com:6443 veya 8443 portlarıdır. Eğer burada bir 'Anonymous Authentication' açıksa, işim çok kolaylaşıyor.
Mesela, şu basit komutla cluster hakkında neler öğrenebileceğimi hayal et:
# Zararsızlaştırılmış örnek sorgu
curl -k https://127.0.0.1:6443/api/v1/namespaces/default/pods
Eğer bu komut bana 'Forbidden' dönmek yerine pod listesini döküyorsa, geçmiş olsun. İçerideyim demektir. Çözüm mü? --anonymous-auth=false bayrağını o API Server konfigürasyonuna eklemekle başla. Bu kadar basit ama bir o kadar kritik.
RBAC: Kimin Eli Kimin Cebinde?
Role-Based Access Control (RBAC), K8s güvenliğinin kalbidir ama aynı zamanda en çok yanlış anlaşılan kısmıdır. Sahada gördüğüm en büyük hata, her mikroservise veya her CI/CD aracına cluster-admin yetkisi verilmesi. Sanki kapıcıya tüm binanın master anahtarını vermek gibi bir şey bu.
Bir gün bir testCompany projesinde inceleme yaparken, bir podun service account'unun gereksiz yere secrets okuma yetkisi olduğunu gördüm. Podun içine sızdığım anda (ki bir RCE açığıyla bu çok kolay), cluster'daki tüm veritabanı şifrelerini çektim.
Kötü bir RBAC örneği (Bunu yapma!):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: her-seyi-yapan-rol
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"] # İşte bu 'all access' her şeyi bitiren nokta
Bunun yerine 'Least Privilege' prensibiyle, sadece ihtiyacı olan yetkiyi ver. Podun sadece configmap okuması mı gerekiyor? Sadece onu ver.
Network Policies: Default-Allow Felaketi
K8s'te varsayılan olarak her pod, diğer her podla konuşabilir. Bu ne demek? Senin frontend podun, arkadaki ödeme sisteminin poduna doğrudan ulaşıp ona 'Selam, nasılsın?' diyebilir. Bir saldırgan frontend'i ele geçirdiğinde, tüm cluster'ı tarayabilir (lateral movement).
Eğer bir NetworkPolicy tanımlamadıysan, içerideki ağ trafiği bir pazar yerinden farksızdır. Şu basit politikayı her namespace için 'default' olarak uygula ki her şey kapansın, sonra ihtiyaca göre açarsın:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {} # Tüm podları seçer
policyTypes:
- Ingress
- Egress
# Hiçbir kural yok, yani her şey yasak!
Bunu yaptıktan sonra developer'lar kapına dayanacaktır, 'Abi servisler birbirine ulaşamıyor' diye. İşte o an güvenliği inşa etmeye başladığın andır.
Container Escape: Konteynırdan Firar
'Privileged: true'... Bu iki kelime bir Red Teamer için Noel hediyesi gibidir. Eğer bir podu privileged modda çalıştırırsan, o pod host makinesindeki (node) her şeye erişebilir.
Saldırganın perspektifinden bakarsak, podun içine girdiğimde şunu yapmam yeterli:
# Host'un diskini podun içine mount etme simülasyonu
mount /dev/sda1 /mnt/host_root
chroot /mnt/host_root
# Tebrikler, artık node üzerindeki root kullanıcısısın!
Bunu engellemek için Pod Security Admission (eski adıyla Pod Security Policy) kullanmalısın. Privileged konteynırları kesinlikle yasaklamalısın, çok ama çok özel durumlar haricinde.
Secrets: Base64 Şifreleme Değildir!
Bunu 2024 yılında hala söylüyor olmamız üzücü ama K8s Secret'ları şifreli (encrypted) değildir, sadece base64 ile encode edilmiştir. Yani birisi etcd veritabanına erişirse veya namespace bazlı okuma yetkisi varsa, şifrelerini şu komutla saniyeler içinde çözer:
echo "Y29rX2d1dmVubGlfc2lmcmU=" | base64 --decode
# Çıktı: cok_guvenli_sifre
Çözüm? 'Encryption at Rest' özelliğini aktif et veya daha iyisi, HashiCorp Vault gibi harici bir secret management çözümü kullan. K8s'in kendi secret yapısına asla %100 güvenme.
Peki Şimdi Ne Yapmalı?
K8s güvenliği bir kerelik bir 'checklist' değil, yaşayan bir süreç. Yarın işe gittiğinde ilk yapacağın şey, cluster'ındaki cluster-admin yetkisine sahip kullanıcıları ve servis hesaplarını listelemek olsun. Sonra o 'privileged' podları bul ve neden orada olduklarını sor.
Unutma, mükemmel güvenlik yoktur; sadece saldırganın işini o kadar zorlaştırırsın ki, başka bir hedefe yönelir. Biz Red Teamer'lar tembel insanlarız, zor kapıyla uğraşmak yerine her zaman açık pencereyi ararız. Senin işin o pencereleri kapatmak.
Cluster'ını koru, loglarını izle ve asla 'Default' ayarlara güvenme. Bir sonraki teknik incelemede görüşürüz, klavyene zeval gelmesin!
