云計(jì)算時(shí)代容器安全綜述-增強(qiáng)容器隔離性(上)

咱們?cè)谇斑叺亩嗥恼轮性敿?xì)介紹過(guò)容器提供的所謂“隔離”具體含義,相信讀過(guò)文章的同學(xué)應(yīng)該能夠脫口而出:這是一種邏輯上的隔離,因?yàn)榈讓拥挠布筒僮飨到y(tǒng)內(nèi)核會(huì)在運(yùn)行在同一臺(tái)機(jī)器上的多個(gè)容器實(shí)例之間共享。沒(méi)錯(cuò),雖然說(shuō)這種隔離提升了硬件資源的使用度,但是這種邏輯隔離也有本身的問(wèn)題,比如惡意用戶(hù)逃逸攻擊,權(quán)限提升,默認(rèn)情況下容器實(shí)例以root權(quán)限運(yùn)行等,因此使用Kubernetes這樣的容器部署平臺(tái)之前,筆者建議大家還是需要掌握一些加固容器隔離性手段,而本篇文章的目的正是如此,希望大家通過(guò)這篇文章能夠重溫容器提供的這種邏輯隔離性存在的安全風(fēng)險(xiǎn),進(jìn)而對(duì)降級(jí)這種風(fēng)險(xiǎn)的機(jī)制,工具有個(gè)全面的學(xué)習(xí)。

應(yīng)用之間隔離部署這樣的需求并不是容器化應(yīng)用特有的,兩個(gè)應(yīng)用程序之間維持某種程度的隔離性是應(yīng)用部署的基本要求,特別是從安全的角度來(lái)看。在容器化部署模式之前,我們通??梢酝ㄟ^(guò)兩臺(tái)物理機(jī)器或者一臺(tái)物理機(jī)器上的兩臺(tái)虛擬機(jī)來(lái)實(shí)現(xiàn)。容器化本質(zhì)上也給應(yīng)用提供了邏輯上的邊界,因此如果配置得當(dāng),部署在兩個(gè)容器實(shí)例中的應(yīng)用程序,相互之間并不知道對(duì)方的存在。

當(dāng)然解決隔離性并不只有物理機(jī),虛擬機(jī)和容器化這三種方式,我們還可以通過(guò)約束應(yīng)用的行為來(lái)實(shí)現(xiàn),這樣當(dāng)一個(gè)應(yīng)用程序被黑客攻破,由于約束機(jī)制的存在,即便是應(yīng)用A知道應(yīng)用B和自己運(yùn)行在同一臺(tái)物理機(jī)器上并且持有敏感數(shù)據(jù),也無(wú)法通過(guò)常規(guī)手段來(lái)竊取敏感數(shù)據(jù),或者影響應(yīng)用B的正常運(yùn)行,我們通常情況下把這種通過(guò)約束機(jī)制來(lái)隔離應(yīng)用程序的機(jī)制稱(chēng)作“沙箱”(Sandboxing)。

理解了沙箱機(jī)制后,回過(guò)頭來(lái)看容器實(shí)例,是不是覺(jué)得容器實(shí)例就是一個(gè)沙箱,后者稍微擴(kuò)大一下概念,就是一個(gè)安全沙箱機(jī)制。每次我們啟動(dòng)一個(gè)容器實(shí)例的時(shí)候,結(jié)合鏡像的immutable機(jī)制,我們可以非常確定容器實(shí)例中運(yùn)行的應(yīng)用程序,并且如果應(yīng)用程序被攻破,惡意攻擊者可能會(huì)試圖通過(guò)這個(gè)被攻破的容器來(lái)提升權(quán)限,或者逃逸到物理機(jī)上來(lái)造成更大的破壞。因此我們需要針對(duì)容器實(shí)例來(lái)增強(qiáng)這個(gè)沙箱的安全機(jī)制,如我們可以約束容器實(shí)例可以執(zhí)行的系統(tǒng)調(diào)用,來(lái)縮減容器實(shí)例被攻破可能造成的攻擊面,接下來(lái)咱們來(lái)詳細(xì)介紹一下增強(qiáng)容器沙箱安全性的手段。

我們從seccomp機(jī)制開(kāi)始說(shuō)起?,F(xiàn)代操作系統(tǒng)都有非常清晰的優(yōu)秀的系統(tǒng)架構(gòu),而操作系統(tǒng)是我們?cè)L問(wèn)計(jì)算資源的入口,操作系統(tǒng)了系統(tǒng)調(diào)用(SYSCALL)來(lái)將系統(tǒng)資源的訪問(wèn)進(jìn)行抽象并提供出來(lái),而我們編寫(xiě)的應(yīng)用程序,比如訪問(wèn)阿里云的數(shù)據(jù)庫(kù)服務(wù)器,或者從阿里云提供的ACR服務(wù)拉取進(jìn)鏡像,以及將圖片上傳到OSS上來(lái)進(jìn)行全球加速,本質(zhì)上都需要系統(tǒng)調(diào)用的幫助來(lái)使用網(wǎng)絡(luò)接口資源。為了約束部署在容器實(shí)例中應(yīng)用程序的行為,特別是哪些變節(jié)后的應(yīng)用不至于對(duì)整個(gè)集群或者應(yīng)用造成毀滅性的損害,我們需要seccomp提供的這種約束應(yīng)用程序系統(tǒng)調(diào)用的安全機(jī)制。

seccomp的全稱(chēng)是secure computing mode,第一次被引入Linux內(nèi)核可以追溯到2005年,具體來(lái)說(shuō),當(dāng)一個(gè)進(jìn)程進(jìn)入secomp模式后,能夠進(jìn)行的系統(tǒng)調(diào)用就會(huì)受到約束(反過(guò)來(lái)說(shuō)如果運(yùn)行在容器實(shí)例中的進(jìn)程沒(méi)有任何約束,那么可以進(jìn)行的系統(tǒng)調(diào)用就不會(huì)受到約束,比如修改操作系統(tǒng)內(nèi)核的時(shí)間,卸載或者掛在操作系統(tǒng)內(nèi)核模塊這樣的高風(fēng)險(xiǎn)操作),在seccomp進(jìn)程可以執(zhí)行的系統(tǒng)操作如下:

- sigreturn,從signal handler返回

- 結(jié)束進(jìn)程(exit操作)

- 對(duì)進(jìn)入seccomp安全模式之前的文件描述符(file descriptor)的數(shù)據(jù)的讀寫(xiě)操作

進(jìn)程進(jìn)入seccomp安全模式后,我們?nèi)匀豢梢詧?zhí)行應(yīng)用代碼,前提是這些代碼只使用了被允許的系統(tǒng)調(diào)用。不過(guò)讀者應(yīng)該可以體會(huì)到,這種模式下本質(zhì)上沒(méi)有辦法執(zhí)行太多正常的業(yè)務(wù)操作,因?yàn)榧s束太強(qiáng)了,因此這種機(jī)制很快就被證明無(wú)法廣泛的被應(yīng)用在應(yīng)用程序開(kāi)發(fā)部署中。

科技行業(yè)的最基本的演進(jìn)方式就是現(xiàn)有問(wèn)題,然后有很多廠商跟進(jìn)給出解決方案,然后市場(chǎng)驗(yàn)證方案的可行性,不斷迭代。2012年一種稱(chēng)作是seccomp-bpf的機(jī)制被引入Linux內(nèi)核,了解操作系統(tǒng)的同學(xué)看到BPF是不是覺(jué)得很親切,全程是伯克利數(shù)據(jù)包過(guò)濾器,也是很多網(wǎng)絡(luò)調(diào)優(yōu)工具,抓包工具的基礎(chǔ),我們熟悉的tcpdump就基于BPF來(lái)實(shí)現(xiàn)對(duì)2層數(shù)據(jù)包的抓取和分析。

筆者不打算在這里詳細(xì)的聊BPF,后續(xù)關(guān)于容器和Kubenrnets網(wǎng)絡(luò)的文章會(huì)詳細(xì)介紹。具體來(lái)說(shuō),seccomp-bfp這種機(jī)制使用BPF來(lái)判斷某個(gè)系統(tǒng)調(diào)用是否被允許,而規(guī)則寫(xiě)在進(jìn)程專(zhuān)屬的被稱(chēng)作是seccomp profile配置文件中。具體原理其實(shí)很簡(jiǎn)單,BPF會(huì)截獲所有的系統(tǒng)調(diào)用,然后讀取系統(tǒng)調(diào)用方法名稱(chēng)和參數(shù),基于profile配置的規(guī)則來(lái)判斷系統(tǒng)調(diào)用是否被允許。事實(shí)上profile提供的能力遠(yuǎn)比上邊描述的復(fù)雜,當(dāng)系統(tǒng)調(diào)用命中某個(gè)規(guī)則(filter)之后,我們還可以配置命中后的規(guī)則,包括:返回錯(cuò)誤,終止調(diào)用或者調(diào)用tracer(可以理解為某個(gè)接口功能)。

不過(guò)對(duì)于容器化部署的應(yīng)用程序?qū)嵗齺?lái)說(shuō),只用到了返回錯(cuò)誤和允許系統(tǒng)調(diào)用這兩個(gè)功能,這其實(shí)和我們熟知的黑名單和白名單機(jī)制非常類(lèi)似,白名單放行,黑名單拒絕。seccomp-bpf這種機(jī)制提升了seccomp機(jī)制的靈活性,特別是對(duì)容器化部署的應(yīng)用程序具有極大的現(xiàn)實(shí)意義,因?yàn)閷?duì)于大部分的業(yè)務(wù)系統(tǒng)來(lái)說(shuō),其實(shí)很多系統(tǒng)調(diào)用我們都不會(huì)用到,除非是極端情況。咱么來(lái)舉幾個(gè)例子說(shuō)明一下:

- 我們一般情況下不會(huì)在運(yùn)行在容器應(yīng)用程序中修改宿主機(jī)內(nèi)核的時(shí)間,因此我們一般情況下根本不需要使用clock_adjtime和clock_settime這兩個(gè)系統(tǒng)調(diào)用

- 容器的最主要目的是運(yùn)行其中的應(yīng)用程序,因此我們一般情況下也不需要在應(yīng)用代碼中加載,初始化或者卸載操作系統(tǒng)內(nèi)核模塊,因此我們也不需要create_module,delete_module和init_module系統(tǒng)調(diào)用

- Linux內(nèi)核的秘鑰保留服務(wù)keyring機(jī)制,一般我們也用不著,因此系統(tǒng)調(diào)用request_key和keyctl也應(yīng)該被拒絕

對(duì)于Docker來(lái)說(shuō),默認(rèn)的seccomp profile已經(jīng)包含了40+系統(tǒng)調(diào)用服務(wù)黑名單,因此我們一般情況下不太需要對(duì)這個(gè)默認(rèn)profile進(jìn)行調(diào)整。不幸的是Kubernetes上并沒(méi)有默認(rèn)的seccomp profile,即便是我們選擇的容器運(yùn)行時(shí)為Docker(這句話(huà)可能有些同學(xué)無(wú)法理解,筆者稍微做一些解釋?zhuān)蠹叶贾雷钚掳姹镜腒8S上默認(rèn)容器運(yùn)行時(shí)已經(jīng)不是Docker,這說(shuō)明一個(gè)道理,Docker這樣的容器運(yùn)行時(shí)本質(zhì)上就是個(gè)插件,我們可以基于自己的需求來(lái)替換?;氐絧rofle的問(wèn)題,也就是K8S平臺(tái)上Docker運(yùn)行時(shí),并沒(méi)有默認(rèn)的seccomp profile)。

不過(guò)大家不需要擔(dān)心,Kubernets社區(qū)當(dāng)然知道這個(gè)安全問(wèn)題,已經(jīng)在著手解決這個(gè)問(wèn)題,支持seccomp的功能已經(jīng)進(jìn)入Alpha版本,相信很快就會(huì)和大家見(jiàn)面,到時(shí)我們就可以通過(guò)PodSecruityPolicy對(duì)象的annotation來(lái)實(shí)現(xiàn)實(shí)現(xiàn)profile機(jī)制,感興趣的同學(xué)可以關(guān)注一下。

注:Jess Frazelle通過(guò)容器+seccomp展示了一套非常堅(jiān)固的安全方案,到目前為止還沒(méi)有被攻破,大家可以訪問(wèn):https://contained.af/ 來(lái)獲取更新的信息。

作為架構(gòu)師的我們,肯定會(huì)問(wèn):那么有沒(méi)有什么機(jī)制能夠讓這個(gè)限制系統(tǒng)調(diào)用的粒度更細(xì),比如在應(yīng)用程序級(jí)別來(lái)限制應(yīng)用程序可以進(jìn)行哪些系統(tǒng)調(diào)用?這句話(huà)翻譯成安全需求就是我們是否可以有應(yīng)用程序級(jí)別的prole來(lái)準(zhǔn)確的控制應(yīng)用程序可以進(jìn)行哪些系統(tǒng)調(diào)用,背后的原因也非常直白,應(yīng)用程序的功能千差萬(wàn)別,細(xì)粒度的控制安全性更好,業(yè)界的確有如下羅列的方案供大家選擇:

- 我們可以借助于strace工具來(lái)追蹤和收集應(yīng)用程序全部功能需要的系統(tǒng)調(diào)用,然后通過(guò)這個(gè)清單來(lái)調(diào)整Docker的seccomp profile

- 咱們前邊介紹過(guò)seccomp-bpf機(jī)制,大家應(yīng)該對(duì)bpf這個(gè)工具可以用來(lái)控制系統(tǒng)調(diào)用是否被允許印象深刻,我們也可以用這個(gè)工具包來(lái)獲取應(yīng)用程序使用的系統(tǒng)調(diào)用清單

- 我們可以使用falco2seccomp和Tracee工具來(lái)產(chǎn)生容器實(shí)例使用到的系統(tǒng)調(diào)用清單

- 如果你覺(jué)得自己來(lái)管理profile太麻煩,不用擔(dān)心,阿里云的容器服務(wù)ACK提供了整套的安全手段,包括筆者這里提到的seccomp機(jī)制,大家可以訪問(wèn)阿里云ACK網(wǎng)站獲取更多詳細(xì)的信息。

介紹完seccomp之后,接著咱們來(lái)了解另外一個(gè)叫AppArmor的Linux安全模塊,全程是Application Armor。AppArmor機(jī)制為L(zhǎng)inux操作系統(tǒng)上的每個(gè)可執(zhí)行文件都提供了一個(gè)profile,我們可以在profile中配置可執(zhí)行文件被允許的能力(capabilities)和文件訪問(wèn)權(quán)限。

注:讀者可以查看文件/sys/module/apparmor/parameters/enabled來(lái)了解自己的Linux操作系統(tǒng)上是否開(kāi)啟了AppArmor安全模塊,如果返回值是y,那么就說(shuō)明已經(jīng)開(kāi)啟。

AppArmor采用一種稱(chēng)作強(qiáng)制訪問(wèn)控制的機(jī)制,具體來(lái)說(shuō)訪問(wèn)規(guī)則被集中管理,一旦訪問(wèn)規(guī)則被配置,用戶(hù)就沒(méi)有任何辦法來(lái)修改或者繞過(guò)訪問(wèn)規(guī)則。與這種模式相對(duì)應(yīng)的是被稱(chēng)作discrectionary access control自主訪問(wèn)控制的方式,通常用在文件權(quán)限訪問(wèn)控制。用戶(hù)可以按自己的意愿,有選擇的與其他用戶(hù)共享他的文件。

使用這種mandatory access control強(qiáng)制訪問(wèn)控制機(jī)制讓我們對(duì)系統(tǒng)調(diào)用有更強(qiáng)的控制,并且所有使用系統(tǒng)的用戶(hù)(客體)無(wú)法對(duì)默認(rèn)的規(guī)則進(jìn)行重寫(xiě)和修改,安全性得到的極大的提升。

在AppArmor模式下,我們首先要準(zhǔn)備好profile文件,有了這個(gè)文件后,我們就可以講profile安裝到目錄/etc/apparmor,然后在通過(guò)工具apparmor_parser來(lái)加載安全規(guī)則,我們可以通過(guò)目錄/sys/kernel/security/apparmor/profiles來(lái)查看系統(tǒng)加載的所有profiles。

另外我們也可以通過(guò)docker run --security-opt="apparmor:<profile name>" ...來(lái)顯示的在啟動(dòng)Docker容器實(shí)例的時(shí)候來(lái)加載profile,結(jié)果是容器實(shí)例的行為將受到profile中定義的安全規(guī)則約束。另外大家需要注意的是,Containerd和CRI-O也支持AppArmor機(jī)制。

同Seccomp類(lèi)似,Docker也為AppArmor提供了默認(rèn)的profile,但是Kubenretes默認(rèn)情況下不使用AppArmor機(jī)制,我們需要使用annotation來(lái)顯示的在POD上聲明AppArmor profile來(lái)開(kāi)啟這個(gè)安全機(jī)制。

接下來(lái)我們討論的這個(gè)功能由紅帽公司開(kāi)發(fā),可能很多同學(xué)都有所耳聞:SELinux,全稱(chēng)是Security-Enhanced Linux,這也是整個(gè)Linux內(nèi)核中一系列安全機(jī)制的一種(LSM,Linux Security module)。在寫(xiě)這些文字的時(shí)候,紅帽公司剛剛發(fā)布了最新版本Linux8.5,其中包含了很多對(duì)于跨云場(chǎng)景以及容器化部署場(chǎng)景的支持,特別是PODMAN這種運(yùn)行時(shí)方式的優(yōu)化,感興趣的讀者可以查看官方的release note:https://www.redhat.com/en/about/press-releases/red-hat-extends-foundation-multicloud-transformation-and-hybrid-innovation-latest-version-red-hat-enterprise-linux。

如果讀者的應(yīng)用運(yùn)行在Centos或者RHEL版本的操作系統(tǒng)上,那么有很大的概率SELinux功能已經(jīng)被打開(kāi)。具體來(lái)說(shuō),SELinux約束進(jìn)程能夠?qū)ξ募推渌M(jìn)程進(jìn)行的操作,每個(gè)進(jìn)程都運(yùn)行在SELinux領(lǐng)域中,不幸的是領(lǐng)域這個(gè)詞有出現(xiàn)了,這和我們說(shuō)的領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中的領(lǐng)域在某種程度類(lèi)似,描述的是進(jìn)程運(yùn)行的上下文環(huán)境。

咱們前邊介紹過(guò)DAC(自主訪問(wèn)控制)機(jī)制,而Linux操作系統(tǒng)中的文件權(quán)限就是典型的DAC機(jī)制。和DAC比起來(lái),SELinux機(jī)制中的權(quán)限最大的不同就是和用戶(hù)Identity無(wú)關(guān)性,SELinux的權(quán)限通過(guò)標(biāo)簽來(lái)工作,這兩種機(jī)制原理上可以同時(shí)工作,因此同一種操作可以被DAC和SELinux同時(shí)允許。

注:大家可以在自己的Linux操作系統(tǒng)上通過(guò)命令ls -lZ或者ps -Z來(lái)查看lable的情況,以下是筆者機(jī)器上Ubuntu虛擬上的輸出結(jié)果:

$ ps -Z

LABEL? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PID TTY? ? ? ? ? TIME CMD

kernel? ? ? ? ? ? ? ? ? ? ? ? ? ? 8059 pts/0? ? 00:00:00 bash

kernel? ? ? ? ? ? ? ? ? ? ? ? ? ? 9386 pts/0? ? 00:00:00 ps

為了讓操作系統(tǒng)上的文件被SELinux安全機(jī)制識(shí)別和管理,我們就必須為所有文件打標(biāo)(labeled),這樣我們就可以通過(guò)策略(policies)來(lái)約束進(jìn)程可以訪問(wèn)的文件類(lèi)型和文件。比如我們可以限制進(jìn)程只能訪問(wèn)自己所屬的文件,這樣當(dāng)進(jìn)程變節(jié)后,由于SELinux機(jī)制的存在,因此變節(jié)的進(jìn)程對(duì)系統(tǒng)的安全影響只限于這個(gè)進(jìn)程內(nèi),這是一種典型的控制爆炸半徑的機(jī)制。

本篇文章到目前為止介紹的三個(gè)機(jī)制:seccomp,apparmor以及selinux都是相對(duì)比較底層的安全機(jī)制,能否使用到自己的應(yīng)用程序中取決于是否有完整的profile配置文件,并且這個(gè)profile并不是靜態(tài)不變的,會(huì)隨著應(yīng)用的功能開(kāi)發(fā)變化需要不斷的更新,因此會(huì)對(duì)運(yùn)維造成巨大的負(fù)擔(dān),很容易出現(xiàn)問(wèn)題,造成結(jié)果是這些安全機(jī)制都是掩耳盜鈴式存在,甚至很多場(chǎng)合功能直接被關(guān)閉。

由于這些原因,我們只能寄希望于K8S提供對(duì)這些功能的默認(rèn)支持,比如默認(rèn)的seccomp profile等。好了, 這篇文章的內(nèi)容就這么多了,咱們?cè)冢ㄏ拢┢袝?huì)介紹稍微沒(méi)有那么底層的安全沙箱技術(shù),敬請(qǐng)期待!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容