Merhaba;

Konteyner güvenliği bölüm 1’de kısaca “docker” komutlarını hatırladık. “Cgroup” ve “Namespaces” kavramlarından bahsettim. Bir örnek ile, “docker engine host” üzerindeki “root” kullanıcısı ile konteynerde çalışan “root” kullanıcısının ne şekilde farklılaştırılacağını gösterdim. Konteynere geçiş yapan bir saldırganın “docker engine host” üzerine geçebilmesini engelleyecek tüm önlemleri almamız çok önemli. Elbette konteynere sızmaları da önlememiz çok kritik. Diğer taraftan saldırgan, “host” üzerine geçiş yaptığında daha çok zarar verebilir.

Herkes tarafından bilinen güvenlik açığı olan imajlardan uzak durmamız gerekiyor. Konteyner oluştururken kullanılan imajların içerebilecekleri zaafiyetler açısından kontrol edilmesi son derece önemli. Bu anlamda, güvenlik açıklarını saptamak için proaktif yaklaşım sağlayabilecek çözümlerin kullanılması gereklidir. Konteynerlerde üretim öncesi görünürlük elde etmek ve bu görünürlülüğün sonucu olarakta konteyner uygulamalar dağıtılmadan önce potansiyle riskleri belirlemek kritik bir öneme sahiptir. DevOps ekiplerinin, geliştirme sürecinin mümkün olan en erken döneminde, detaylı görünürlük raporlarından, güvenlik açıklarını görebilmesi, kötü amaçlı yazılımları fark edebilmesi ve böylece bu problemleri düzeltmek için ihtiyaç duydukları bilgileri edinerek riski azaltacak aksiyonlar alabilmesi elzemdir. Konteyneri oluşturan katmanlı imajların her birinin derinlemesine görününürlülüğünü sağlayabilmek, çalışan konteynerler içinde güvenlik açıklarını tespit edebilmek, konteynerlerin, organizasyonun belirlediği güvenlik kurallarını ihlal etmesi durumunda, oluşturulmalarını engelleyebilmek organizasyonların olmaz ise olmazları arasında olmalıdır.

Ilk örneğimizde, CVE-2014-6271 güvenlik açığına sahip imajı kullanacağız.

No alt text provided for this image

Şekil 1. Güvenlik açığı olan imajın çalıştırılması.

Ardından, localhost’a 8080 portundan bağlandığımızda, gelen web sayfasını şekil 2.’den görebilirsiniz.

No alt text provided for this image

Şekil 2. Localhost’un 8080 portundan bağlandığımızda karşımıza gelen sayfa.

https://hub.docker.com/r/vulnerables/cve-2014-6271 sayfasından yapacaklarımızı takip edebiliriz. Örneğin, tek bir komut ile “/etc/passwd” dosyasını görüntüleyebiliriz. “curl -H “user-agent: () { :; }; echo; echo; /bin/bash -c ‘cat /etc/passwd'” http://localhost:8080/cgi-bin/vulnerable” komutunu başka bir oturum açarak, shell’den çalıştırdığımızda, “docker engine host” üzerindeki “/etc/passwd” dosyasını görüntüleyebildik.

No alt text provided for this image

Şekil 3. “curl -H “user-agent: () { :; }; echo; echo; /bin/bash -c ‘cat /etc/passwd'” komutu ile “docker engine host” üzerinde “/etc/passwd” dosyasının güvenlik açığı kullanılarak görüntülenebilmesi.

No alt text provided for this image

Şekil 4. Güvenlik açığı içeren konteyner.

https://www.electricmonk.nl/log/2017/09/30/root-your-docker-host-in-10-seconds-for-fun-and-profit/

adresinde, eğer “docker” grubun bir üyesi iseniz, “host” üzerinde ne kadar kolay “root” kullanıcısına geçiş yapabileceğinizi anlatıyor. Incelemenizi öneririm. Açıkcası, internet, güvenlik açıklarının kullanılarak “docker host” üzerinde “root” kullanıcısna nasıl kolayca geçiş yapılabileceğini anlatan örneklerle dolu. Bizim görevimiz tüm bu açıklardan haberdar olmak ve sistemimizi güvenli bir hale getirebilmektir. Şekil 5.’de “ubuntu” kullanıcısının “docker” grubuna ait olduğunu, diğer taraftan “docker host” üzerine “/etc/shadow” dosyasının görüntülemeye yetkisi olmadığını görüyoruz.

No alt text provided for this image

Şekil 5. “Ubuntu” kullanıcısının dahil olduğu gruplar ve “ubuntu” kullanıcısının “/etc/shadow” dosyasını görüntüleyemediğini görüyoruz.

Üç basit dosya ile bu amacı gerçekleştirmek çok kolay. “gcc” ile “shell.c” programcığını derlememiz gerekiyor.

No alt text provided for this image

Şekil 6. Dockerfile, shell.c ve shellscript.sh.

No alt text provided for this image

Şekil 7. “shell.c” nin derlenmesi.

“shellscript.sh” ın (Şekil 6.) ne yaptığına dikkat edin. Derlediğimiz “shell”i, konteyner içine kopyalıyor ve “setuid” bitini aktif hale getiriyor. Konteyneri derlemek için herşey hazır durumda. Komutumuzu çalıştıralım (şekil 8.).

No alt text provided for this image

Şekil 8. “sudo docker build –rm -t privilege_esc .” komutunun çalıştırılması.

“privilege_esc” imajından konteyneri oluşturuyoruz ve konteynerin, “shellscript.sh”ı çalıştırmasını sağlıyoruz (Şekil 9.).

No alt text provided for this image

Şekil 9. “sudo docker run –v /tmp/shared:/shared privilege_esc /bin/sh shellscript” komutunun çalıştırılması.

No alt text provided for this image

Şekil 10. “docker” grup yetkimizi kullanarak “host” üzerinde “root” yetkisi aldığımızı görüyoruz.

Şekil 10.’dan “docker” grubuna ait olan “ubuntu” kullanıcısının ne kadar kolay “root” hakkı aldığını ve “/etc/shadow” dosyasını görüntülediğini görüyoruz.

“/var/run/docker.sock” dosyasından bahsetmek istiyorum. “Docker Hub”dan indirdiğiniz bazı konteynerler bu dosyanın, konteynere bağlanmasını gerekli kılabilir. Bu dosya, “docker daemon”ın dinlediği unix soketidir. Konteynerin, “docker daemon” ile iletişim kurması için kullanılır. Bu dosya saldırgan tarafından kötü amaçla kullanılabilir. En basit şekli aşağıdaki gibi olabilir. Konteyner içinde, host’un root dosya sistemini “mount” edeceğiz.

“host”un root dosya sistemine ulaştığından emin olmak için / dizininde bir dosya oluşturdum (Şekil 11.).

No alt text provided for this image

Şekil 11. Konteynerden, “host”un root dosya sistemine eriştiğimizden emin olmak için oluşturduğumuz bir dosya.

No alt text provided for this image

Şekil 12. “/var/run/docker.sock” dosyasının oluşturulan konteynere “mount” edilmesi.

Konteyneri çalıştırarak bir shell alalım ve /var/run/docker.sock’ın gerçekten konteyner içinde olup olmadığını anlayalım (Şekil 13.). Bu dosyayı kullanmak için konteynere “docker client” yükleyelim.

No alt text provided for this image

Şekil 13. Konteyner üzerinden “docker client” yüklenmesi.

No alt text provided for this image

Şekil 14. Konteyner üzerinden “docker -H unix” opsiyonunu kullanarak oluşturduğum konteynere “host”un / dosya sistemini mount edebildim.

Az önce oluşturduğumuz konteyneri, “docker engine host” üzerinden de görüyoruz (Şekil 15.).

No alt text provided for this image

Şekil 15. Konteyner üzerinden oluşturulan yeni konteynerin “docker engine host” üzerinde görüntülenmesi.

“–privileged flag” özelliği ile konteynere pek çok yetkilendirme verebilirsiniz. Ama dikkat edin bu yetkiler saldırgan tarafından kullanılabilir.

No alt text provided for this image

Şekil 16. “—privileged” flag kullanılmadan konteynerin oluşturulması ve “capsh” ile gelen varsayılan özelliklerin görüntülenmesi.

Şekil 16.’da komutlarla adım adım, konteynerin oluşturulması, konteynere shell alınarak “capsh” ile gelen varsayılan özelikleri görebiliriz.

Gelen varsayılan özellikleri aşağıdaki şekilde not edelim.

“Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip

Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap”

Şimdi ise “–privileged” flagini kullanarak bir konteyner oluşturalım (Şekil 17.).

No alt text provided for this image

Şekil 17. “–privileged” flagin kullanılarak konteyner oluşturulması.

Şekil 17.’den görüldüğü gibi, “–privileged” flagi kullanıldıktan sonra “capsh –print” komutu ile ne kadar fazla imtiyaz geldiğini görebiliriz. Aşağıya ekledim. Önceki ile karşılaştırabilirsiniz. Neden önemli bu durum? Eğer siz, konteynerin ihtiyaç duyduğundan daha fazla özelliği açarsanız, saldırgan bu özellikleri kullanarak kötü amaçları için kullanabilir. “cap_sys_module” modül ile bakın neler yapabiliyoruz?

“Current: = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read+eip

Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read”

Bu amaç ile iki tane dosya kullanacağız: Makefile ve docker_module.c (Şekil 18.).

No alt text provided for this image

Şekil 18. “docker_module.c” ve “Makefile” dosyası.

Kullanılan kernel modül dosyası basit bir dosya. Göstermek istediğim, eğer cap_sys_module özelliği açık ise, konteyner içinden bu dosyayı“host” üzerine yükleyebileceğimizdir. Bu amaç ile Şekil 19.’da gördüğünüz gibi, “make” komutuyla “Makefile” dosyasını kullanarak derleme işlemini yaptıktan sonra, dizin altında pek çok dosya oluştuğunu gördük.

No alt text provided for this image

Şekil 19. “make” komutu ile derleme işleminin yapılması.

Saldırganın, konteyner içinde “shell”i almış olduğunu düşünüyoruz bu örneği yaparken. Şekil 19’da gördüğünüz dosyalardan ilgilendiğim dosya, “docker_module.ko”. Gerçek kernel modül dosyasıdır. Bu amaç ile yeni bir konteyner oluşturduk ve “shell” ile bağlantı yaptık (Şekil 20.).

No alt text provided for this image

Şekil 20. Yeni bir konteyner oluşturulması.

Saldırganın, kötü amaçla kullanacağı kernel modül dosyasını konteynere aldığını düşünelim. Şekil 21.’de “base64” komutu ile dosya içeriğini alıyor ve Şekil 22’de konteynere aktarıyoruz.

No alt text provided for this image

Şekil 21. “docker_module.ko” nun “host” üzerinden alınması.

No alt text provided for this image
No alt text provided for this image

Şekil 22. Kernel modül dosyasının konteynere aktarılması.

Kernel modülü yüklediğimizi görebilmek için “host” üzerinde, “tail –f /var/log/kern.log” komutunu çalıştırıyoruz (Şekil 23).

No alt text provided for this image

Şekil 23. “host” üzerinde, “tail –f /var/log/kern.log” komutunu çalıştırıyoruz.

Konteynerde, ilgili modülü yüklüyoruz, (Şekil 24).

No alt text provided for this image

Şekil 24. “docker_module.ko” nun konteynerden yüklenmesi.

“Host” üzerinden “docker_model.ko” nun yüklendiğini görüyoruz (Şekil 25.).

No alt text provided for this image

Şekil 25. Konteyner üzerinden “docker_modul.ko”nun yüklendiğini görüyoruz.

“Host” üzerinden “lsmod” komutuyla da modülün yüklü olduğunu görebiliriz, (Şekil 26.).

Konteyner üzerinden yüklediğimiz modülü geri alırsak, (Şekil 26.), “host” üzerinden de alındığı mesajını görebiliriz (Şekil 27.).

No alt text provided for this image

Şekil 26. “docker_module.ko” nun geri alınması.

No alt text provided for this image

Şekil 27. “Host” üzerinden modülün geri alındığının görüntülenmesi.

Saldırganın birinci ve ikinci bölümde anlattığım açıkların dışında kullanabileceği farklı açık noktalarda elbette var. Yazım çok uzadığı için aktaracaklarımı 3.bölüme saklıyorum. Ama gün geçtikçe yeni atak türleri mutlaka çıkıyor. Araştırıcı olmanızı öneriyorum. Aslında bu amaç ile bu konuya özel çözümlerin yapılandırılması mantıklı olur.

Yazımı tamamlamadan önce “Trivy”den bahsedeceğim. https://github.com/aquasecurity/trivy#debianubuntu  adresinde bulunan kurulum yönergelerini aşağıdaki gibi takip ettim. “Trivy”nin güvenlik açıklarını bulduğunu gösterebilmek için özellikle “python:3.4-alpine” imajını kullandım. https://github.com/aquasecurity/trivy#debianubuntu adresindeki yönergeleri aşağıya kopyaladım. Bu komutların terminalde çalıştığı ekran görüntülerini aynı şekilde aşağıda kopyaladım.

$ sudo apt-get install wget apt-transport-https gnupg lsb-release

$ wget -qO – https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add –

$ echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list

$ sudo apt-get update

$ sudo apt-get install trivy

No alt text provided for this image

Şekil 28. Trivy yüklenmesi adım-1.

No alt text provided for this image

Şekil 29. Trivy yüklenmesi adım-2.

No alt text provided for this image

Şekil 30. Trivy yüklenmesi adım-3.

No alt text provided for this image

Şekil 31. Trivy yüklenmesi adım-4.

No alt text provided for this image

Şekil 32. Trivy yüklenmesi adım-5.

No alt text provided for this image

Şekil 33. Trivy’nin uygulanacağı python:3.4-alpine imajının “pull” edilmesi.

Şekil 34.’de Trviy’nin “python:3.4-alpine” imajını kontrol etmesi sonucu oluşturduğu raporu görüyoruz. Okunabilirlik açısından çıktının bir kısmını ekledim.

No alt text provided for this image

Şekil 34. Trivy raporunun görüntülenmesi.

Konteyner yapıları üretim ortamınızda kullanmayı planlıyorsanız mutlaka, Radboud Universitesinde Bilgisayar Bilimleri öğrencilerinin hazırladığı aşağıdaki lisans tezini okumanızı öneriyorum. Öncelikle anlaşılır bir şekilde konteyner kavramından, bileşenlerinden bahsettikten sonra iki saldırgan modeli üzerinde duruyor: konteyner kaçışları ve Docker daemon atakları.

https://www.cs.ru.nl/bachelors-theses/2020/Joren_Vrancken___4593847___A_Methodology_for_Penetration_Testing_Docker_Systems.pdf

Açıkcası, geleceğin konteyner yapılarla şekillendiği bir ortamda, gerçekten çok da eğlenceli olan konteyner güvenliği konularında gençlerin uzmanlık geliştirmeye başlamasını öneriyorum. Faydalı bulduğum linkleri aşağıya ekledim. Gençlerden bu dökümanları okumalarını ve Linkedin’de güzel bir yazı yayınlamalarını gördüğümde gerçekten çok mutlu olacağım.

Asiye Yiğit – 13 Haziran 2020 Cumartesi

Kaynaklar:

https://www.cs.ru.nl/bachelors-theses/2020/Joren_Vrancken___4593847___A_Methodology_for_Penetration_Testing_Docker_Systems.pdf

https://www.electricmonk.nl/log/2017/09/30/root-your-docker-host-in-10-seconds-for-fun-and-profit/

https://github.com/aquasecurity/trivy#debianubuntu

https://info.aquasec.com/hubfs/Aqua_Security_2017_Container_Security_Survey%20.pdf

https://securosis.com/assets/library/reports/Securosis_BuildingContainerSecProgram_2018.pdf

https://devops.com/wp-content/uploads/2018/02/0118_ContainerSecurity_DevOps_v4.pdf

https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-190.pdf

https://www.redhat.com/en/topics/security/container-security

https://www.tripwire.com/state-of-security/devops/guide-container-security/