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

container-security

İzolasyon Masalı ve Konteyner Kaosu: 'Dockerized' Olurken Nerede Patlıyoruz?

Konteynerlar bizi gerçekten kurtarıyor mu yoksa sadece zafiyetlerimizi paketleyip mi taşıyoruz? Sahadan tecrübelerle konteyner güvenliğinin karanlık noktalarına dalıyoruz.

Sedat Özdemir
· 4 dk okuma

Hiç Docker imajın build olurken CVE taramasında binlerce 'High' ve 'Critical' bulguyu görüp klavyeyi yeme noktasına geldin mi?

Selam millet, ben Sedat. Bugün biraz 'konteyner' konuşalım ama öyle dökümantasyonlardaki o toz pembe dünyadan değil; sahadan, testCompany çatısı altında yaptığımız testlerde karşımıza çıkan o acı gerçeklerden bahsedelim. Hani şu 'Abi konteyner zaten izole, bir şey olmaz' deyip arkamızı döndüğümüzde başımıza iş açan o meşhur kutulardan.

Konteyner teknolojisi hayatımızı kurtardı, kabul. Bağımlılık sorunlarını çözdü, 'benim makinemde çalışıyordu' geyiğini tarihe gömdü. Ama dürüst olalım; çoğumuz konteynerları güvenlik katmanı sanıyoruz. Oysa konteyner dediğin şey, aslında sadece süslenmiş birer process'ten ibaret. Kernel paylaşımlı bir dünyada yaşıyoruz ve o kernel patlarsa, hepimiz patlıyoruz.

İlk Hata: 'Base Image' Seçerken Cömert Davranmak

Genelde şöyle oluyor: Yazılımcı arkadaşım hızlıca bir şeyler denemek istiyor ve gidip FROM ubuntu:latest veya FROM python:3.9 çekiyor. Oh mis, içinde her şey var: curl, wget, netcat, hatta bazen gcc bile! İşte Red Team olarak bizim en sevdiğimiz yer burası. Bir şekilde o konteyner içine sızdığımızda, sistemde halihazırda yüklü olan bu araçlar bizim için 'post-exploitation' altın madeni oluyor.

Bakın, bir saldırgan olarak içeri girdiğimde kendi tool'larımı indirmekle uğraşmak istemem. Sistemde zaten curl varsa, reverse shell almak sadece birkaç saniye sürer.

Kötü Örnek (Zararsızlaştırılmış Dockerfile):

# Her şey dahil paket, adeta açık büfe
FROM node:14
WORKDIR /app
COPY . .
RUN npm install
# Uygulamayı root olarak çalıştırmak mı? Harika fikir!
CMD ["node", "server.js"]

Bu imajın boyutu muhtemelen 1GB ve içinde en az 500 tane bilinen zafiyet (CVE) var. Bunun yerine ne yapmalıyız? Tabi ki 'Distroless' veya 'Alpine' gibi minimalist yaklaşımlar. İçinde shell bile olmayan bir imajdan bahsediyorum. Düşünsene, içeri giriyorum ama ls bile yazamıyorum. İşte gerçek güvenlik bu.

Secret Management: Çöp Kovasındaki Elmaslar

Red Team operasyonlarında en çok ekmeğini yediğimiz şeylerden biri docker history komutudur. Bir arkadaşımız 'ya acelem vardı, API key'i ENV olarak yazdım ama sonra sildim' der. Geçmiş olsun. Docker katmanlı bir yapıya sahiptir. Sen üst katmanda silsen de, o alt katmanda sonsuza kadar kalır.

Görünüşte Masum Ama Tehlikeli Komut:

# Terminalden çalıştırıldığını düşün
docker build --build-arg API_KEY="super-secret-key-123" -t my-app .

Bunu yaptıktan sonra docker history my-app dediğim an, o key'i kabak gibi görürüm. testCompany içindeki testlerimizde, CI/CD pipeline'larından sızan bu tarz sırlar yüzünden koca cloud altyapılarını 'pwn'lediğimiz oldu. Sırlarınızı (secrets) asla Dockerfile içinde veya build argument olarak taşımayın. Bunun için Vault kullanın, o da yoksa en azından runtime'da güvenli bir şekilde mount edin.

'Root' Olma Sevdası ve Capabilities

Konteyner içindeki user genelde varsayılan olarak root gelir. Birçok kişi 'Zaten konteynerın içi, dışarıya çıkamaz ki' diye düşünür. Ama Linux Kernel öyle demiyor. Eğer konteyner içinde root isen ve o konteyner privileged bayrağıyla veya yanlış capabilities ile ayağa kaldırıldıysa, host makinesine zıplamak (escape) çocuk oyuncağı.

Mesela CAP_SYS_ADMIN yetkisi verilmiş bir konteyner, aslında host makinesinin anahtarlarını elinde tutuyordur.

Tehlikeli Çalıştırma Örneği:

# Sakın evde (veya production'da) denemeyin!
docker run --rm -it --privileged --net=host --pid=host alpine sh

Yukarıdaki komutla konteyner değil, resmen host makinesinde bir arka kapı açmış oluyorsun. testCompany olarak biz bu tarz yapılandırmaları gördüğümüzde direkt 'Break-out' senaryolarını devreye alıyoruz. Konteynerları her zaman USER komutuyla kısıtlanmış bir kullanıcı ile çalıştırın ve host network'ünden uzak tutun.

Runtime Security: Birileri İçeride Cirit Atıyor mu?

Konteynerı güvenli build ettin, taradın, tertemiz çıktı. Peki ya runtime? Bir zero-day zafiyetiyle veya bir uygulama açığıyla içeri sızılırsa ne olacak? Çoğu sistem yöneticisi konteyner ayağa kalktıktan sonra içeride ne olup bittiğini izlemiyor.

Burada imdadımıza 'eBPF' tabanlı araçlar yetişiyor. Örneğin Falco gibi araçlarla 'Konteyner içinde neden shell açıldı?' veya 'Neden bu konteyner beklenmedik bir IP'ye (örneğin 127.0.0.1 dışındaki bir adrese) bağlanmaya çalışıyor?' gibi alarmlar kurmalıyız.

Örnek Bir 'Hardening' Senaryosu:

# Konteynerın dosya sistemini read-only yaparak saldırganın işini zorlaştıralım
docker run --read-only --tmpfs /tmp --tmpfs /run -d my-secure-app

Eğer bir saldırgan bu konteyner içine dosya yazamazsa, zararlı bir binary indiremez veya config dosyalarını değiştiremez. Evet, biraz sancılıdır; uygulamanın nereye yazması gerektiğini tek tek belirlemen gerekir ama inan bana, gece rahat uyumanı sağlar.

Defansif Düşünmek: 'Shift Left' Ama Gerçekten

'Shift Left' lafı çok pelesenk oldu herkesin diline. Ama konteyner güvenliğinde bu sadece bir slogan değil, bir zorunluluk. İmajları daha build aşamasında trivy veya grype gibi araçlarla taramayan bir pipeline, bomba taşımaktan farksızdır.

Ancak sadece taramak yetmez. 'Critical' bulguları ignore etmek bir alışkanlık haline gelmemeli. Biz testCompany'de genelde şunu öneriyoruz: Minimum baz imaj (distroless), çok aşamalı (multi-stage) build ve runtime sırasında 'least privilege' prensibi.

Son Söz Yerine (Hadi Bi' Çay İçelim)

Konteyner dünyası uçsuz bucaksız bir derya. Kubernetes tarafına girmedim bile, orası ayrı bir kaos. Ama temel sağlam olmazsa, üzerine kurduğun kule ilk rüzgarda devrilir. Unutma, siber güvenlikte 'olmaz' diye bir şey yoktur, 'henüz olmadı' vardır.

Yazılımı geliştirirken sadece 'çalışmasına' değil, 'nasıl patlatılabileceğine' de odaklanın. Bir sonraki kahve molasında 'Ya bizim şu Dockerfile'da acaba ne sırlar kalmıştır?' diye bir sorgulama yapın, pişman olmazsınız.

Haydi, güvenli kodlamalar!

İlgili yazılar