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

containersecurity

Küçücük Fıçıcık, İçi Dolu Tehlike: Alpine Güzellemesine Bir Son Verelim

Alpine kullanınca siber saldırganlar kapıda mı kalıyor sanıyorsunuz? Konteyner güvenliği sadece imaj boyutu değildir. Gelin, prod ortamında yapılan o 'sessiz' hataları ve gerçek korunma yollarını konuşalım.

Sedat Özdemir
· 4 dk okuma

Selamlar millet, ben Sedat. Bugün biraz 'container' dünyasının kirli çamaşırlarını ortaya dökeceğiz. Ama önce, sektörde neredeyse bir din haline gelmiş o büyük yanılgıyla başlayalım: 'Alpine Linux kullanın, saldırı yüzeyiniz sıfıra insun.'

Abicim, kusura bakmayın ama bu tam bir 'security by obscurity' (gizlilik yoluyla güvenlik) avuntusu. Herkes Alpine imajlarını övüyor, 'Bak 5 MB, içinde shell bile yok' diye hava atıyor. Tamam, küçük olması güzel bir şey ama prod ortamında musl-libc ile glibc arasındaki o minik uyumsuzluk yüzünden uygulamanız garip davranışlar sergilediğinde ya da paket yönetiminde güvenlik güncellemelerini takip edemediğinizde o 5 MB size bir kalkan olmayacak. Hatta çoğu zaman, içinde 'troubleshooting' araçları olmayan bir imaj, incident response (olaya müdahale) anında kendi ayağınıza sıkmanızdan başka bir işe yaramıyor. Güvenlik, bir imajı küçültmekten ibaret olsaydı, siber dünya çok sıkıcı bir yer olurdu.

İmaj Sadece Bir Kabuktur, Önemli Olan İçindeki Zehir

Red Team operasyonlarında karşımıza en çok çıkan şey, tertemiz, ufacık tefecik imajların içine 'hardcoded' olarak gömülmüş sırlar (secrets). Geliştirici arkadaşım, Dockerfile içine ENV DB_PASSWORD=testPassword123 yazdığında o imajı katmanlara böldüğün an, o şifre artık tarihin tozlu sayfalarına (ve her katman loguna) kazınmış oluyor.

Bir sızma testinde imajın katmanlarını (layers) inceleyerek çekilen o 'eski' env değerleri, bizim için birer altın madenidir. İsterse imajın boyutu 2 KB olsun, o şifre oradaysa konteyner güvenliğinden bahsedemeyiz.

'Root' Takıntımız ve Capabilities Belası

Konteyner dünyasının en büyük günahı: USER root.

Birçok kişi 'Aman abi, şimdi permission hatalarıyla uğraşmayalım, zaten konteyner izole değil mi?' diyerek uygulamayı root haklarıyla çalıştırıyor. Hayır dostum, konteyner bir sanal makine değildir. Kernel'ı ana makineyle paylaşır. Eğer konteyner içindeki bir süreci root olarak çalıştırırsan ve o süreçte bir 'escape' (kaçış) zafiyeti varsa, tebrikler; tüm host makinesini bize hediye ettin.

Özellikle --privileged bayrağıyla konteyner çalıştırmak, evin anahtarını hırsıza verip 'Ben markete gidiyorum, sen takıl' demekle aynı şey. Gelin, kötü bir Dockerfile örneğine ve onu nasıl düzelteceğimize bakalım:

Kötü Örnek (Red Team Favorisi):

# testCompany - Bad Practice
FROM node:14
WORKDIR /app
COPY . .
# Uygulama root olarak çalışıyor!
RUN npm install
CMD ["node", "app.js"]

İyi Örnek (Hardened):

# testCompany - Secure Practice
FROM node:14-slim
# Gereksiz dosyaları temizle ve bir kullanıcı oluştur
RUN groupadd -r nodejs && useradd -r -g nodejs nodejs
WORKDIR /app
COPY --chown=nodejs:nodejs . .
USER nodejs
# Sadece gerekli portu aç
EXPOSE 3000
CMD ["node", "app.js"]

Buradaki USER nodejs satırı, bir saldırganın konteyner içinde kod çalıştırsa bile sistemde yetki yükseltmesini (privilege escalation) inanılmaz zorlaştırır.

Docker Socket: Şeytanın Arka Kapısı

Bazen sistem yöneticileri, konteyner içinden Docker'ı yönetmek için /var/run/docker.sock dosyasını konteynerin içine mount ederler. İşte bu, Red Team için 'Game Over' anıdır. Eğer bir saldırgan o sokete erişebilirse, host üzerinde yeni bir konteyner oluşturup host'un tüm dosya sistemini (/) o konteynere mount edebilir.

Zararsızlaştırılmış (Defanged) Saldırı Senaryosu:

Saldırgan sokete eriştiğinde şu komutu (veya benzerini) çalıştırabilir: docker -H unix:///var/run/docker.sock run -v /:/host -it alpine chroot /host

Bu komutla birlikte artık konteynerden çıktık, doğrudan ana makinedeyiz. O yüzden, çok ama çok geçerli bir sebebiniz yoksa Docker socket'i asla ama asla konteynerlere göstermeyin.

Ağ Güvenliği: 'Default Bridge' Bir Tuzaktır

Docker'ı kurduğunuzda gelen varsayılan bridge ağı, konteynerlerin birbirleriyle IP adresi üzerinden konuşmasına izin verir. Eğer bir mikroservisiniz hacklenirse, saldırganın ilk yapacağı şey iç ağda tarama (scanning) yapmaktır.

127.0.0.1 üzerinde çalışan servislerinizi güvende sanmayın. Konteyner içi ağlarda segmentasyon yapmazsanız, bir frontend açığı üzerinden backend veritabanınıza sızılması işten bile değil. 'Custom network'ler oluşturun ve sadece konuşması gereken servisleri aynı ağa dahil edin.

Gerçek Dünyadan Bir Senaryo: testCompany Örneği

Geçenlerde bir test sırasında testCompany altyapısında bir konteynere sızdık. İmaj çok sıkıydı, Alpine Linux kullanılmıştı, içeride curl bile yoktu. Ama bir şeyi unutmuşlardı: Yazılabilir dosya sistemi (Writable Root FS).

Uygulama üzerinden bir dosya yükleme açığı bulduk ve /tmp dizinine kendi küçük binary'mizi yükleyebildik. Eğer konteyner read-only modda çalıştırılsaydı, hiçbir şey yazamayacaktık ve saldırı orada tıkanacaktı.

Çözüm basit:

docker run --read-only --tmpfs /tmp --tmpfs /run my-app:latest

Ne Yapmalı? (Pratik Tavsiyeler)

  1. Image Scanning: Snyk, Trivy veya Grype gibi araçları CI/CD sürecine entegre edin. Ama çıkan her 'Critical' sonuca da hemen atlamayın; gerçekten 'exploitable' mı ona bakın.
  2. No-Root: Konteynerlerinizi root dışında bir kullanıcıyla çalıştırın. Bu, güvenliğin %60'ıdır.
  3. Secrets Management: Şifreleri imajın içine gömmeyin. HashiCorp Vault kullanın veya en kötü ihtimalle Docker Secrets / K8s Secrets mekanizmalarını doğru yapılandırın.
  4. Capabilities: Konteynerin ihtiyacı olmayan tüm kernel yeteneklerini (capabilities) elinden alın. docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE ... gibi.
  5. Runtime Security: Falco gibi araçlarla konteynerlerinizde garip bir süreç (mesela bir Python script'inin aniden çalışmaya başlaması) olup olmadığını izleyin.

Konteyner güvenliği bir varış noktası değil, bir yolculuktur. Alpine kullanarak kendinizi güvende hissetmek yerine, o Alpine'ın içindeki uygulamanın nasıl davrandığına odaklanın.

Unutmayın, en küçük imaj bile içinde bir zafiyet barındırıyorsa, saldırgan için o koca bir dünyadır.

Stay secure, stay geeky!

İlgili yazılar