張新義,武澤慧,賈 瓊,陳志浩
1(數(shù)學(xué)工程與先進計算國家重點實驗室,鄭州 450001) 2(北京計算機技術(shù)及應(yīng)用研究所,北京 100000)
近年來,云計算技術(shù)蓬勃發(fā)展,云計算技術(shù)依賴于共享計算資源來實現(xiàn)按需擴展,從而節(jié)約和降低了運營和維護成本.在云計算中,容器因其開發(fā)操作方便和資源利用率高被認為是向云中部署微服務(wù)和應(yīng)用程序的標(biāo)準,成為了當(dāng)前的主要趨勢.云原生計算基金會發(fā)布(CNCF)2021年的調(diào)查報告顯示[1],在企業(yè)實際生產(chǎn)部署中,容器的使用率已經(jīng)增加到93%,相比于2016年第1次調(diào)查時的23%,5年的時間里增加了近3倍.
傳統(tǒng)的虛擬機技術(shù)使用Hypervisor來創(chuàng)建硬件抽象層,相比之下,容器作為一種操作系統(tǒng)級的虛擬化技術(shù),依賴于由Linux內(nèi)核提供的NameSpace和Cgroup等內(nèi)核特性來實現(xiàn)容器之間的隔離.一個容器可以被認為是一組共享專用Linux內(nèi)核資源的進程,因此在容器中運行的應(yīng)用程序可以實現(xiàn)接近其宿主機的性能.然而,容器的隔離強度卻遠遠比不上虛擬機,容器與宿主機之間、以及同一主機上運行的容器之間的隔離完全由底層操作系統(tǒng)內(nèi)核在軟件中強制執(zhí)行,一個惡意容器可以利用宿主機上的內(nèi)核漏洞來進行特權(quán)升級類的攻擊,進而達到損害主機以及在該主機上運行的所有其他容器的目的.
容器鏡像是容器的基礎(chǔ),鏡像包含應(yīng)用程序以及其相關(guān)依賴的一個基礎(chǔ)文件系統(tǒng).容器鏡像通常在其他基礎(chǔ)鏡像上以層的方式構(gòu)建,在鏡像制作的過程中,通常對一些不會在容器運行中使用的資源進行了過度積累(如文件、程序等),進而導(dǎo)致容器鏡像的體積過度膨脹.此外,Linux內(nèi)核的代碼庫也一直在擴展,多年來公開的系統(tǒng)調(diào)用數(shù)量的增加表明了Linux內(nèi)核代碼的膨脹.Linux內(nèi)核中系統(tǒng)調(diào)用數(shù)從1991年第1個版本中的126個增加到5.11.0版本中的334個( x86_64(64-bit))[2].容器體量的增大和Linux系統(tǒng)調(diào)用的膨脹導(dǎo)致了容器攻擊面的增大.
作為一種緩解策略,容器攻擊面減少技術(shù)最近開始獲得關(guān)注,依據(jù)安全方面的最佳實踐:最小特權(quán)原則和特權(quán)分離原則,安全研究人員主要從兩個方面來減少容器的攻擊面:減少容器的資源或限制容器的功能.以前的許多工作都在不同層次上應(yīng)用了這個概念,如根據(jù)應(yīng)用程序的需求定制內(nèi)核代碼[3,4]、從共享庫中刪除使用不到的函數(shù)[5-9]以及限制容器或應(yīng)用程序的系統(tǒng)調(diào)用[10-15]等.
NIST容器安全指南[16]中的建議是最好通過限制容器可用的系統(tǒng)調(diào)用來減少攻擊面.盡管各種方法的形式的多樣的,但是所有這些方法的共同挑戰(zhàn)是如何準確的識別系統(tǒng)調(diào)用集.大部分工作依賴于動態(tài)分析和訓(xùn)練[10-12],使用現(xiàn)實的工作負載來對容器進行訓(xùn)練,之后刪除或者限制所有訓(xùn)練中沒有覆蓋到的代碼或系統(tǒng)調(diào)用.這種方法最大限度地提高了可以限制的系統(tǒng)調(diào)用數(shù)量,但是動態(tài)訓(xùn)練往往無法獲取全部工作負載所需的系統(tǒng)調(diào)用集,尤其是一些很少被執(zhí)行的部分,如錯誤處理、緩沖處理等,因為在訓(xùn)練期間沒有覆蓋到的功能無法保證永遠不會使用.一些工作依賴于靜態(tài)分析[13,17,18],通過靜態(tài)分析容器中的可執(zhí)行文件和庫來獲取系統(tǒng)調(diào)用集合,這種方法雖然可以彌補動態(tài)訓(xùn)練結(jié)果的不完備,但是靜態(tài)分析的范圍往往受限,而且會得到一個比實際情況更大的系統(tǒng)調(diào)用集,達不到理想的減少容器攻擊面的效果.
在本文中,容器可用性的概念主要指以下兩個方面:1)功能的完備性:受限容器需要能夠運行正常容器實現(xiàn)的所有功能;2)性能的穩(wěn)定性:受限容器的工作負載與正常容器的差異處于可接受的范圍之內(nèi).簡單來說,用戶在使用時,感覺不到受限容器與未受限容器之間的差異,受限容器不會因為運行正常的功能需求而報錯.
上面兩種方法都在尋求滿足容器運行的最小系統(tǒng)調(diào)用集合,假設(shè)前提是在分析階段沒有用到的系統(tǒng)調(diào)用在以后的實際運行中也不會用到,這在保護容器安全性的同時,卻忽略了容器的可用性,受限的容器僅僅運行極少的一部分功能,一旦在實際生產(chǎn)環(huán)境中部署,應(yīng)用程序的一個合規(guī)操作可能會由于觸發(fā)違規(guī)策略而被終止,導(dǎo)致嚴重影響.
鑒于以前學(xué)者們的工作,本文提出了AutoSec,一種容器限制策略自動生成和靈活配置的方法.AutoSec綜合考慮了容器的安全性與可用性的均衡,采用動靜態(tài)結(jié)合的方式來提取系統(tǒng)調(diào)用集合,并根據(jù)容器生命周期的不同階段動態(tài)的生成Seccomp BPF策略,在容器部署后可以實現(xiàn)策略的靈活配置.AutoSec主要分為兩個階段:策略提取階段和策略實施階段.策略提取階段由動態(tài)訓(xùn)練引擎和靜態(tài)分析引擎組成,給定一個應(yīng)用程序容器,動態(tài)訓(xùn)練引擎追蹤容器初始化階段的系統(tǒng)調(diào)用以及容器運行階段的應(yīng)用程序集合,靜態(tài)分析引擎再對應(yīng)用程序集合進行靜態(tài)分析來獲取應(yīng)用程序中系統(tǒng)調(diào)用的集合進而生成應(yīng)用程序與系統(tǒng)調(diào)用之間的映射.在策略實施階段,容器首先使用初始化時獲取的系統(tǒng)調(diào)用集合啟動;在運行時,為了實現(xiàn)靈活性的配置,根據(jù)容器的需求動態(tài)的生成Seccomp BPF的規(guī)則文件以限制容器的系統(tǒng)調(diào)用.實驗選取Docker hub上最為流行的4款功能型容器,驗證了AutoSec在減少容器攻擊面的有效性.
本文的主要工作包括以下幾個方面:
1)本文提出了一種動靜態(tài)結(jié)合的容器系統(tǒng)調(diào)用提取方法,可以有效的提取容器初始化階段所需的系統(tǒng)調(diào)用集合和生成應(yīng)用程序與系統(tǒng)調(diào)用之間的映射.
2)本文提出了一種需求驅(qū)動的系統(tǒng)調(diào)用調(diào)度方法,根據(jù)容器生命周期的不同階段,按需調(diào)度容器中可用的系統(tǒng)調(diào)用.
3)根據(jù)以上工作,本文設(shè)計了一種通用的系統(tǒng)AutoSec,并選取Docker hub上最為流行的4款容器,驗證了AutoSec在較少的性能損耗內(nèi)可以有效的減少70%以上的系統(tǒng)調(diào)用數(shù)量.
Linux容器是一種操作系統(tǒng)級的虛擬化方法,可在同一宿主機的內(nèi)核上運行多個用戶群組.Linux內(nèi)核使用Namespace[19]、Capabilities[20]、和Cgroup[21]來提供不同容器之間的隔離.
Namespace,即命名空間,Linux內(nèi)核通過實現(xiàn)命名空間機制來實現(xiàn)資源的隔離.命名空間為容器提供了最原始也是最簡單的隔離方式,保證一個容器中運行的進程看不到或者影響不到運行在另一個容器中的進程或者容器主機的進程.目前,Linux內(nèi)核提供了8種類型的命名空間,即IPC、Network、Mount、PID、Time、User、Cgroup和UTS,分被負責(zé)信號量、掛載點、進程號等資源的隔離.
Cgroup(Control group)是Linux內(nèi)核的另一個重要特性,主要用來實現(xiàn)對于資源的限制和審計.在容器技術(shù)的實現(xiàn)中,Cgroup提供了多種度量標(biāo)準來確保每個容器獲得公平的CPU、內(nèi)存和I/O等資源,同時,Cgroup限制某個容器的資源使用量,防止其資源耗盡致使系統(tǒng)性能降低.Cgroup目前支持13種資源,包括cpu,cpuacct,cpuset,freezer,perf event,memory,hugetlb,rdma,blkio,pid,device,net_cls和net_prio,每個資源類型都由相應(yīng)的Cgroup控制器管理.
Linux 還支持將部分root 的特權(quán)操作權(quán)限細分成 Capabilities,如果將某個權(quán)限賦給某進程,即使不是 root用戶也可以執(zhí)行該權(quán)限對應(yīng)的特權(quán)操作.該機制可加強容器內(nèi)部的權(quán)限管控,使容器內(nèi)外的 root 權(quán)限隔離.
系統(tǒng)調(diào)用是指運行在用戶空間的程序向操作系統(tǒng)內(nèi)核請求需要更高權(quán)限運行的服務(wù).系統(tǒng)調(diào)用提供了用戶程序與操作系統(tǒng)之間的接口,系統(tǒng)調(diào)用接口幾乎允許程序與網(wǎng)絡(luò)、文件系統(tǒng)和其他敏感系統(tǒng)資源的所有交互.
在容器環(huán)境中,盡管使用操作系統(tǒng)所提供的Capabilities、Namespace等嚴格的軟件隔離機制,但惡意容器仍然可以通過利用內(nèi)核漏洞來繞過這些隔離機制.與此同時,為了支持新的特性、協(xié)議和硬件,Linux內(nèi)核的代碼一直在擴展.盡管不同的應(yīng)用程序使用不同的系統(tǒng)調(diào)用,但幾乎都用不到內(nèi)核提供的全部系統(tǒng)調(diào)用,剩余的系統(tǒng)調(diào)用處于程序可用但是用不到的狀態(tài),但是可供攻擊者所利用,進而突破隔離機制達到訪問敏感資源甚至特權(quán)升級的效果.而且每個新的系統(tǒng)調(diào)用函數(shù)都是訪問整個內(nèi)核代碼的大部分的入口點,從而導(dǎo)致內(nèi)核的攻擊面增大[22].限制可用的系統(tǒng)調(diào)用數(shù)量是減少程序攻擊面的一種有效的方法,已經(jīng)存在大量的相關(guān)工作,一些系統(tǒng)調(diào)用限制工具,如Janus[23]、Systrace[24]、ETrace[25]以及Seccomp[26]等能有效的執(zhí)行系統(tǒng)調(diào)用限制策略.
Seccomp(Secure Computer)是Linux內(nèi)核的一個特性,用于限制阻塞進程的敏感系統(tǒng)調(diào)用和危險參數(shù).Seccomp支持兩種模式:嚴格模式和過濾模式.當(dāng)進程應(yīng)用嚴格模式時的Seccomp策略時,只能執(zhí)行4種系統(tǒng)調(diào)用,即read()、write()、exit()、sigreturn();過濾模式即Seccomp BPF,Seccomp BPF在Linux 3.5內(nèi)核版本中引入,支持通過使用Berkeley的數(shù)據(jù)包過濾器做過濾規(guī)則匹配,與嚴格模式不同,Seccomp BPF允許用戶指定需要限制的系統(tǒng)調(diào)用和參數(shù).
Docker默認支持使用Seccomp BPF來過濾容器可用的系統(tǒng)調(diào)用.目前,Docker提供的默認配置禁止了諸如bpf、mount、ptrace 等40多個系統(tǒng)調(diào)用[27],可有效防御針對CVE-2014-3519、CVE-2015-8660、CVE-2016-0728 等漏洞的攻擊.但是,最小特權(quán)原則[28]規(guī)定,程序應(yīng)該被限制只訪問完成其操作所必需的資源,對于某一個特定容器來說,其實用不到Docker默認允許的大多數(shù)系統(tǒng)調(diào)用.除了默認的策略外,Docker還允許用戶使用“--security-optseccomp”選項為Docker配置用戶自定義的Seccomp規(guī)則文件.
圖1顯示了AutoSec的基本架構(gòu),它由兩個主要的階段組成,策略提取階段和策略實施階段.
圖1 AutoSec架構(gòu)Fig.1 AutoSec architecture
策略提取階段負責(zé)提取滿足容器運行所需的系統(tǒng)調(diào)用集合,包括兩個主要的組件,動態(tài)訓(xùn)練引擎和靜態(tài)分析引擎.首先通過動態(tài)訓(xùn)練引擎獲取容器初始化時所需的系統(tǒng)調(diào)用集合以及在運行時使用的應(yīng)用程序集合;接著靜態(tài)分析引擎對應(yīng)用程序集合進行分析,得到每個程序在運行時所對應(yīng)的系統(tǒng)調(diào)用集合.最終得到容器在初始化階段和程序運行階段兩種不同階段的系統(tǒng)調(diào)用集合.策略實施階段負責(zé)為容器施加Seccomp BPF策略,包括3個主要的組件,監(jiān)控器、生成器和調(diào)度器.首先使用動態(tài)訓(xùn)練中獲取的容器初始化系統(tǒng)調(diào)用集合生成的Json格式的Seccomp配置文件來啟動容器;并在容器運行期間維護一個系統(tǒng)調(diào)用池,池中的初始系統(tǒng)調(diào)用集合為啟動容器所需的集合,并使用監(jiān)控器對容器的運行狀態(tài)進行監(jiān)控,根據(jù)容器運行不同應(yīng)用程序的系統(tǒng)調(diào)用需求,調(diào)度器會動態(tài)的改變的系統(tǒng)調(diào)用池中的內(nèi)容,并使用生成器生成相應(yīng)的Seccomp BPF策略來動態(tài)調(diào)度容器可用的系統(tǒng)調(diào)用.
策略提取階段目的是提取目標(biāo)容器的系統(tǒng)調(diào)用列表.鑒于前人的工作[10,11],動態(tài)訓(xùn)練使用系統(tǒng)可見性工具追蹤程序的執(zhí)行以發(fā)現(xiàn)程序在運行時所使用的系統(tǒng)調(diào)用,但是動態(tài)分析通常不能發(fā)現(xiàn)所有可能的執(zhí)行路徑;靜態(tài)分析[13,17]能夠更全面的發(fā)現(xiàn)程序中所使用的系統(tǒng)調(diào)用,但是往往得到的結(jié)果是一個比實際程序所使用系統(tǒng)調(diào)用大的多的集合.為了得到一個相對精確的系統(tǒng)調(diào)用集合,本文采用動靜態(tài)結(jié)合的方式,分階段和方式為容器提取系統(tǒng)調(diào)用集合.
2.2.1 動態(tài)訓(xùn)練
動態(tài)訓(xùn)練主要包括兩個目標(biāo):在容器啟動時獲得容器初始化所必須的系統(tǒng)調(diào)用,以及在容器運行時獲得必要的可執(zhí)行文件.
動態(tài)分析引擎使用Sysdig[29]對容器進行監(jiān)控.Sysdig是一款原生支持容器的通用性系統(tǒng)可見性工具,它支持多種輸出過濾模式來獲取系統(tǒng)內(nèi)容.當(dāng)使用dockerrun命令啟動一個容器時,容器會首先進行初始化,Docker引擎會調(diào)用多組系統(tǒng)調(diào)用,此時,動態(tài)訓(xùn)練引擎監(jiān)控捕獲其系統(tǒng)調(diào)用集合,該集合用作生成容器啟動時的安全策略基礎(chǔ).容器初始化完成后,基本服務(wù)啟動,開始進入正常運行階段,根據(jù)容器最初的設(shè)定的腳本開始執(zhí)行相應(yīng)的功能,動態(tài)分析引擎開始捕獲容器運行了哪些可執(zhí)行文件,獲取其在容器中使用的可執(zhí)行文件的集合.
1)獲取初始化系統(tǒng)調(diào)用
在Docker的體系架構(gòu)中,創(chuàng)建和啟動容器由docker daemon負責(zé),當(dāng)docker daemon收到來自與docker client的啟動容器的請求時,containerd會根據(jù)用戶的請求來執(zhí)行不同的操作,如掛載文件系統(tǒng)、初始化容器網(wǎng)絡(luò)等,但是containerd并不會直接去操作容器,而是創(chuàng)建一個containerd-shim的進程來對容器進行操作.在啟動一個新容器時,需要做一些 Namespace 和 Cgroup 的配置,以及掛載 root 文件系統(tǒng)、使Seccomp配置文件生效等,這些操作都有了標(biāo)準的規(guī)范,即OCI(開放容器標(biāo)準),runc 就是OCI的一個標(biāo)準實現(xiàn),containerd-shim會調(diào)用runc來執(zhí)行這一系列操作來啟動容器,此時runc已經(jīng)被施加Seccomp策略,所以動態(tài)分析引擎首先要記錄runc運行的系統(tǒng)調(diào)用.
此外,在大部分容器中,通常會有名稱類似于docker-entrypoint.sh的 shell腳本,它主要用于在啟動應(yīng)用程序之前做一些準備工作,如設(shè)置環(huán)境變量、設(shè)置配置文件等.如果存在這樣的腳本,那么在動態(tài)分析階段也需要記錄由該腳本執(zhí)行的系統(tǒng)調(diào)用.
2)獲取運行時應(yīng)用程序
容器初始化完畢后,容器對應(yīng)功能啟動,容器開始進入運行階段.容器中的應(yīng)用程序大體可以分為兩類,一類為容器功能相關(guān)的關(guān)鍵性應(yīng)用,如Mysql容器中的mysqld、mysql_conf、mysqlsh等相關(guān)程序,另一類為容器功能無關(guān)的輔助性應(yīng)用,如find、bash等.在容器運行的過程中,除了功能必須所需的應(yīng)用外,還存在一些輔助性工具來滿足容器的可操作性,因此動態(tài)訓(xùn)練需要引擎找出容器在運行時使用的多個應(yīng)用程序.
不同功能的容器類型、不同的執(zhí)行環(huán)境都會使得容器所使用的系統(tǒng)調(diào)用集合以及應(yīng)用程序存在差異.為了增加獲取應(yīng)用程序的覆蓋率,本文從兩個方面對容器進行訓(xùn)練,即容器命令和應(yīng)用程序命令.容器命令如dockerrun有很多的參數(shù),如--net指定容器的網(wǎng)絡(luò)連接類型、--volume指定掛載操作、--env-file指定文件讀入環(huán)境變量等功能,在容器運行中,根據(jù)用戶的需求進行設(shè)置會可能對容器的環(huán)境造成影響.本文從Docker hub中爬取對應(yīng)鏡像的文檔說明中容器命令執(zhí)行的部分,作為訓(xùn)練容器的命令之一.對于應(yīng)用程序命令,本文為不同的容器制定了功能覆蓋腳本以提高覆蓋到的應(yīng)用程序,確保能夠覆蓋絕大多數(shù)的容器功能,并在訓(xùn)練期間,通過手動輸入命令來覆蓋腳本無法觸及的應(yīng)用程序.
經(jīng)過動態(tài)訓(xùn)練,AutoSec得到了兩個集合:容器啟動時的系統(tǒng)調(diào)用集合和容器運行時的應(yīng)用程序集合.
2.2.2 靜態(tài)分析
Linux中的應(yīng)用程序大多為ELF可執(zhí)行文件,在經(jīng)過動態(tài)訓(xùn)練獲得容器運行時需要的應(yīng)用程序后,AutoSec通過靜態(tài)分析的方式來獲得應(yīng)用程序的在運行時所需的系統(tǒng)調(diào)用.直接通過動態(tài)訓(xùn)練監(jiān)控程序運行來獲取系統(tǒng)調(diào)用的結(jié)果是不健全的,因為無法保證在訓(xùn)練階段執(zhí)行路徑的覆蓋率,如Nginx中緩存管理機制,當(dāng)緩存滿時,Nginx會生成一個單獨的緩存管理進程,該進程使用unlink()系統(tǒng)調(diào)用來處理緩存,清除舊的緩存文件.但是,動態(tài)訓(xùn)練往往只是監(jiān)控到Nginx緩存管理程序初始化,可能無法捕獲緩存文件被刪除的過程,因此無法捕獲到unlink()系統(tǒng)調(diào)用的使用.而且,程序在正常運行期間,unlink()系統(tǒng)調(diào)用并不會在其他的地方使用,而且單純的延長訓(xùn)練時間也并不能很好的解決問題.所以,相比于動態(tài)捕獲程序在運行時使用的系統(tǒng)調(diào)用集合,直接對可執(zhí)行文件進行靜態(tài)逆向分析,往往能覆蓋程序較為全面的系統(tǒng)調(diào)用集合.
Linux為用戶程序提供了兩種系統(tǒng)調(diào)用的方法,即直接調(diào)用和庫函數(shù)調(diào)用.用戶程序可以調(diào)用函數(shù)syscall()來直接調(diào)用系統(tǒng)調(diào)用,而且程序可以通過將嵌入?yún)R編指令將系統(tǒng)調(diào)用號傳遞到EAX/RAX寄存器,觸發(fā)軟件中斷以切換到內(nèi)核空間的方式來直接調(diào)用系統(tǒng)調(diào)用.然而直接調(diào)用的方法有兩個主要的缺點:首先,當(dāng)直接調(diào)用系統(tǒng)調(diào)用時,程序可能會在用戶空間和內(nèi)核空間之間引入頻繁的上下文切換.例如,當(dāng)使用write()系統(tǒng)調(diào)用將字符串輸出到文件時,程序必須先切換到內(nèi)核空間,并為每個字符返回到用戶空間,這種切換可能會給程序帶來巨大的開銷;其次,由于系統(tǒng)調(diào)用在不同的操作系統(tǒng)中有所不同,因此直接調(diào)用的方式不容易在不同的操作系統(tǒng)中移植.
大多數(shù)應(yīng)用程序更多是通過調(diào)用標(biāo)準庫提供的庫函數(shù)來調(diào)用系統(tǒng)調(diào)用,如GNUC庫(gLibc),它是大多數(shù)容器中使用的最流行的Libc實現(xiàn),gLibc提供了一種通用、高效、安全的方式來調(diào)用不同操作系統(tǒng)上的系統(tǒng)調(diào)用.例如,當(dāng)使用printf()輸出一個字符串時,首先程序會緩沖所有字符,然后使用write()系統(tǒng)調(diào)用刷新到一個文件中.在這種情況下,只需要一次用戶空間到內(nèi)核空間的切換,這大大減少了用戶態(tài)與內(nèi)核態(tài)來回切換的開銷,由于庫函數(shù)的效率和方便性,幾乎所有的程序都使用庫函數(shù)來調(diào)用系統(tǒng)調(diào)用.
1)直接系統(tǒng)調(diào)用提取
Linux中進行系統(tǒng)調(diào)用最直接的方式就是使用syscall()函數(shù)或原生的syscall匯編指令,在調(diào)用Libc庫中沒有包裝函數(shù)的系統(tǒng)調(diào)用時,往往采用這種方式.分析這類調(diào)用需要獲得被傳遞給系統(tǒng)調(diào)用的參數(shù)的值.
靜態(tài)分析引擎使用二進制代碼分解來提取syscall指令分配給RAX/EAX寄存器和syscall()函數(shù)分配給RDI/EDI寄存器的值來識別系統(tǒng)調(diào)用號.系統(tǒng)調(diào)用號沒有在指令中編碼,而是在一個寄存器中提供,如x86_64上的RAX寄存器,靜態(tài)分析引擎通過推斷寄存器的內(nèi)容來獲得系統(tǒng)調(diào)用號.首先,引擎使用Objdump 將二進制文件反匯編,從找到syscall指令開始,利用反向符號執(zhí)行技術(shù)尋找RAX/EAX寄存器的值,最終返回包含系統(tǒng)調(diào)用號的符號值.之后將系統(tǒng)調(diào)用號映射到對應(yīng)的系統(tǒng)調(diào)用,得到直接系統(tǒng)調(diào)用的集合.
2)庫函數(shù)調(diào)用提取
使用庫函數(shù)進行系統(tǒng)調(diào)用是最為常用的一種方式,為了提取程序使用庫函數(shù)進行的系統(tǒng)調(diào)用,靜態(tài)分析引擎首先生成庫函數(shù)與系統(tǒng)調(diào)用之間的映射,之后通過提取應(yīng)用程序的函數(shù)列表,來生成應(yīng)用程序與系統(tǒng)調(diào)用的映射,具體步驟如下:
·生成庫函數(shù)與系統(tǒng)調(diào)用之間的映射
對于程序調(diào)用的每個庫,靜態(tài)分析引擎首先構(gòu)建一個函數(shù)調(diào)用樹(FCT)來表示庫中的函數(shù)調(diào)用關(guān)系.然后結(jié)合所有文件中的FCT,構(gòu)建一個有向無環(huán)函數(shù)調(diào)用圖(FCG),FCG表示庫函數(shù)之間的所有函數(shù)調(diào)用關(guān)系.此外,由于系統(tǒng)調(diào)用不會調(diào)用其他庫函數(shù),因此系統(tǒng)調(diào)用總是出現(xiàn)在FCG的結(jié)束節(jié)點上.因此,可以通過遍歷FCG中的所有路徑來構(gòu)建從庫函數(shù)到系統(tǒng)調(diào)用的映射表.
·提取二進制文件的函數(shù)列表
給定一個ELF可執(zhí)行文件,函數(shù)提取器提取每個程序中所有被調(diào)用的庫函數(shù).利用包含所有全局變量和函數(shù)信息的ELF符號表來派生出被調(diào)用的函數(shù).具體來說,分析器首先使用工具Readelf[30]獲取ELF文件的可讀的ELF符號表,然后根據(jù)庫到系統(tǒng)調(diào)用的映射表提取庫函數(shù).
·生成二進制文件與系統(tǒng)調(diào)用的映射
在獲得程序的所有調(diào)用庫函數(shù)之后,將標(biāo)識的函數(shù)列表與庫到系統(tǒng)調(diào)用的映射表進行交叉檢查,最終生成應(yīng)用程序與系統(tǒng)調(diào)用之間的映射.
策略實施階段負責(zé)啟動容器并實時監(jiān)控容器的執(zhí)行情況,在不同的執(zhí)行階段動態(tài)地更改一個容器內(nèi)的所有進程的可用系統(tǒng)調(diào)用列表,限制容器在不同的階段中只使用該階段允許的系統(tǒng)調(diào)用,并按照容器內(nèi)運行的程序動態(tài)的改變可用系統(tǒng)調(diào)用的數(shù)量.
2.3.1 Seccomp BPF策略的實現(xiàn)形式
BPF在1992年的Tcpdump[31]程序中首次提出,Tcpdump是一個網(wǎng)絡(luò)數(shù)據(jù)包的監(jiān)控工具,但是由于數(shù)據(jù)包的數(shù)量很大,而且將內(nèi)核空間捕獲到的數(shù)據(jù)包傳輸?shù)接脩艨臻g會帶來很多不必要的性能損耗,所以要對數(shù)據(jù)包進行過濾,只保留感興趣的那一部分,而在內(nèi)核中過濾感興趣的數(shù)據(jù)包比在用戶空間中進行過濾更有效.BPF就是提供了一種進行內(nèi)核過濾的方法,因此用戶空間只需要處理經(jīng)過內(nèi)核過濾的后感興趣的數(shù)據(jù)包.
Seccomp 過濾模式允許開發(fā)人員編寫 BPF 程序來確定是否允許給定的系統(tǒng)調(diào)用,基于系統(tǒng)調(diào)用號和參數(shù)(寄存器)值進行過濾.在Linux內(nèi)核中,一個進程可以被附加到多個Seccomp過濾器中,并且所有的Seccomp過濾器都被組織在一個單向鏈表中,每個Seccomp過濾器都被實現(xiàn)為一個由Seccomp指令組成的程序代碼,即一個bpf_prog結(jié)構(gòu),bpf_prog解析sock_filter的指令,如圖2所示.
圖2 Seccomp BPF的內(nèi)核實現(xiàn)Fig.2 Kernel implementation of Seccomp BPF
在得到策略提取階段對應(yīng)的系統(tǒng)調(diào)用列表之后,生成器根據(jù)不同的使用階段生成不同的形式的Seccomp BPF策略,包括兩種形式,一種是作為限制容器啟動時容器引擎所用的安全策略,一種作為容器運行時程序所需的安全策略.
2.3.2 使用Seccomp BPF保護容器安全
通過提取容器運行時的系統(tǒng)調(diào)用來生成Seccomp BPF策略來對容器進行限制,雖然在一定程度上可以有效的減少來自于內(nèi)核系統(tǒng)調(diào)用的威脅.但是動態(tài)分析得到的系統(tǒng)調(diào)用集合往往會使得受限容器的可用性不足;靜態(tài)分析得到的系統(tǒng)調(diào)用集合過大,達不到減少容器攻擊面的理想效果.綜合考慮前人的工作,AutoSec根據(jù)容器運行的不同階段,以容器內(nèi)應(yīng)用程序為粒度,動態(tài)的來調(diào)度容器可用的系統(tǒng)調(diào)用.
Docker在啟動時,允許用戶使用自定義的Seccomp策略啟動,如表1所示,該策略表示默認禁止所有系統(tǒng)調(diào)用,以白名單的方式允許chdir()系統(tǒng)調(diào)用的使用.但是容器一旦啟動,就無法通過Docker 客戶端對策略進行更改.雖然Linux內(nèi)核提供了兩個系統(tǒng)調(diào)用prctl()和seccomp()用來更改某個進程的Seccomp過濾規(guī)則,但是在本文中卻不可取.因為它們只能在容器內(nèi)部的進程上配置Seccomp過濾器,但是本文需要從容器外部更改容器內(nèi)部的進程的Seccomp過濾器.而且,在添加了一個Seccomp過濾器后,在進程運行時不能刪除或更改,即這兩個系統(tǒng)調(diào)用來添加新的Seccomp過濾規(guī)則,但不能刪除已添加的Seccomp規(guī)則.因此調(diào)度器選擇定位Seccomp過濾器指針的內(nèi)存地址,然后將指針指向每一個對應(yīng)的應(yīng)用程序生成的bpf_prog結(jié)構(gòu)體以實現(xiàn)動態(tài)的策略部署.具體來說,分為以下4個步驟,如圖3所示.
表1 Docker Seccomp 規(guī)則文件實例Table 1 Example of a Docker Seccomp ruleset file
圖3 動態(tài)調(diào)度容器的系統(tǒng)調(diào)用的工作流Fig.3 Workflow of dynamically schedule the container′s system call
1)使用Seccomp策略啟動容器
首先根據(jù)動態(tài)分析得到的系統(tǒng)調(diào)用列表生成表1格式的Seccomp限制策略,策略默認禁止所有系統(tǒng)調(diào)用,并使用白名單的形式賦予可用的系統(tǒng)調(diào)用.在容器啟動時,使用-security-opt指定該文件.接著容器引擎開始進行一系列的初始化工作,containerd-shim在調(diào)用runc時,Seccomp開始生效,并作用于所有容器的所有的進程,此時,容器內(nèi)所有的進程都被施加了Seccomp策略.
此外,AutoSec開始維護一個系統(tǒng)調(diào)用池,此時池中的元素為動態(tài)分析所得到的系統(tǒng)調(diào)用集合.
2)監(jiān)控容器運行并動態(tài)更新調(diào)用池
容器開始運行后,此時系統(tǒng)調(diào)用池中可用的系統(tǒng)調(diào)用可能不能滿足容器內(nèi)程序所運行的需求.AutoSec基于Sysdig實現(xiàn)了一個監(jiān)控器來捕獲容器想要執(zhí)行的程序,接著,對于捕獲到特定程序,監(jiān)控器根據(jù)靜態(tài)分析中得到的二進制文件與系統(tǒng)調(diào)用的映射,導(dǎo)出執(zhí)行該程序所需的系統(tǒng)調(diào)用集合,并將其更新到系統(tǒng)調(diào)用池中,如算法1所示.
算法的輸入為狀態(tài)變動任務(wù)Task和系統(tǒng)調(diào)用池Syscall_pool;輸出為更新過的Syscall_pool.當(dāng)監(jiān)控器檢測到一個任務(wù)狀態(tài)的變化,會根據(jù)應(yīng)用程序與系統(tǒng)調(diào)用的映射圖將程序映射到對應(yīng)的系統(tǒng)調(diào)用Syscalls(1~2行),接著調(diào)度器檢查任務(wù)的行為,若為啟動狀態(tài),則遍歷Syscalls并將其加入系統(tǒng)調(diào)用池中,并將加入池中的系統(tǒng)調(diào)用的使用數(shù)(Syscall.use_num)加1,代表當(dāng)前有多少任務(wù)在使用該系統(tǒng)調(diào)用(3~12行);若任務(wù)的狀態(tài)為結(jié)束,則對于Syscalls中的每一個系統(tǒng)調(diào)用,將其系統(tǒng)調(diào)用的使用數(shù)(Syscall.use_num)減1,當(dāng)使用數(shù)等于0時,則代表該系統(tǒng)調(diào)用沒有程序正在使用,調(diào)度器將其從池中刪除(13~20行).
3)Seccomp BPF規(guī)則構(gòu)造與更新
系統(tǒng)調(diào)用池中更新后,生成器需要根據(jù)系統(tǒng)調(diào)用池中的集合從新生成結(jié)構(gòu)體.具體來說分為兩個步驟.首先,生成器使用libseccomp[32]庫將一個系統(tǒng)調(diào)用轉(zhuǎn)換為BPF過濾器指令,使用libseccomp庫中的seccomp_rule_add()方法來添加所有可用的系統(tǒng)調(diào)用,并使用seccomp_export_bpf()方法來導(dǎo)出生成的BPF過濾程序.接著使用內(nèi)核函數(shù)bpf_prog_create_from_user()將在用戶空間生成的BPF過濾程序傳遞的內(nèi)核空間,并在內(nèi)核空間中生成bpf_prog.函數(shù)bpf_prog_create_from_user()有兩個參數(shù),一個指向用戶空間的bpf程序指針和一個指向內(nèi)部內(nèi)核函數(shù)seccomp_check_filter()的函數(shù)指針,首先將用戶空間過濾器緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū)中,然后調(diào)用傳入seccomp_check_filter()函數(shù),將經(jīng)典的BPF過濾器程序轉(zhuǎn)換為Seccomp BPF過濾器程序,最后,生成包含帶有新指令集的bpf_prog結(jié)構(gòu).
算法1.動態(tài)調(diào)度算法
輸入:Task:任務(wù),Sycall_pool:系統(tǒng)調(diào)用池
輸出:Syscall_pool:系統(tǒng)調(diào)用池
1.Syscalls←[] //初始化映射
3.ifTask.action==Startthen
4.forSyscallinSyscallsdo
5.ifSyscallinSyscall_poolthen
6.Syscall.ued_num++
7.continue;
8.Syscall_pool.add(syscall)
9.Syscall.ued_num++
10.endif
11.endfor
12.endif
13.ifTask.action==Stopthen
14.forSyscallinSyscallsdo
15.Syscall.ued_num--
16.ifSyscall.use_num==0
17.Syscall_pool.delete(syscall)
18.endif
19.endfor
20.endif
21.returnSycall_pool
4)動態(tài)改變Seccomp 過濾器
使用新生成的bpf_prog結(jié)構(gòu)體,調(diào)度器可以動態(tài)的更改所有容器內(nèi)進程的Seccomp 過濾器.如圖3所示,當(dāng)容器使用“dockerrun-itd-security-optseccomp” 命令啟動容器時,容器中的第1個進程(PID=1)被施加了Seccomp過濾器,它是容器內(nèi)所有進程的父進程,它的子進程都會繼承該過濾器,并包含指向bpf_prog結(jié)構(gòu)的相同指針,當(dāng)更改容器中一個進程的bpf_prog結(jié)構(gòu)時,所有進程的Seccomp過濾器都會被更改.調(diào)度器通過(PID=1)的進程的task_struct來定位bpf_prog在內(nèi)存中位置,然后修改內(nèi)存的內(nèi)容,將seccomp_filter中的filter指針指向新生成的bpf_prog結(jié)構(gòu).
實驗使用一臺16g內(nèi)存的x86_64計算機,英特爾酷睿i7-10700 CPU和Ubuntu 20.04主機操作系統(tǒng)來對AutoSec進行驗證.不同操作系統(tǒng)的系統(tǒng)調(diào)用數(shù)量不同,在本文的實驗環(huán)境中,主機操作系統(tǒng)總共有334個系統(tǒng)調(diào)用.Docker 在默認情況下禁止44個系統(tǒng)調(diào)用,所以在本文的實驗環(huán)境中,Docker默認允許的系統(tǒng)調(diào)用數(shù)量是290個.本文使用的Docker版本是20.10.18,在動態(tài)監(jiān)控階段,使用Sysdig 0.29.3來跟蹤系統(tǒng)調(diào)用.實驗選取了Docker hub上下載量超過10億的Linux官方容器進行了系統(tǒng)的統(tǒng)計分析,并選取4款最流行的容器對AutoSec進行測試.
根據(jù)容器的用途,可以將Docker hub上的官方鏡像分為基礎(chǔ)環(huán)境性容器和特定服務(wù)型容器.其中基礎(chǔ)環(huán)境性容器可分為操作系統(tǒng)型(如Ubuntu)和編程語言型容器(如Python),特定服務(wù)型容器主要包括web服務(wù)型和數(shù)據(jù)庫服務(wù)型,還有一些其他特定功能的容器,如表2所示.
表2 Docker hub 熱門鏡像Table 2 Docker hub popular images
操作系統(tǒng)型容器主要為作為構(gòu)建其他容器的鏡像基礎(chǔ),其鏡像大小受其功能的影響有較大差距,Busybox僅有1.24MB大小,而Centos的鏡像超過了231MB.編程語言型容器同樣經(jīng)常作為用戶構(gòu)建自身容器的基礎(chǔ)容器,Docker hub中使用最多的3個編程語言容器為Python、Golang和Openjdk(Java),其平均鏡像大小是所有類別中最大的,將近800MB.以Nginx為代表的web服務(wù)型容器以及Mysql為代表的數(shù)據(jù)庫服務(wù)型容器是Docker在實際生產(chǎn)部署中使用最多的容器類型.
基礎(chǔ)環(huán)境型容器由于其目的是作為用戶在構(gòu)建鏡像或?qū)嶒灥幕A(chǔ),在實際運行中會盡量的保持其功能的完整性.在本文的實驗中,選取了具有代表性的4款功能型容器進行測試,分別為Nginx、Httpd、Mysql和Postgres.其中Nginx和Httpd(Apache)是在實際生產(chǎn)部署中使用最多的Web服務(wù)器,數(shù)據(jù)庫服務(wù)器選擇Mysql和Postgres.
3.2.1 動態(tài)訓(xùn)練
動態(tài)分析引擎監(jiān)控容器的初始化和運行共30秒,得到容器在初始化階段的系統(tǒng)調(diào)用以及運行階段時用到的可執(zhí)行文件集合.動態(tài)分析的結(jié)果如表3所示,可以發(fā)現(xiàn)在初始化階段,Web服務(wù)型容器使用的系統(tǒng)調(diào)用數(shù)目較多余數(shù)據(jù)庫服務(wù)型,Nginx最多,使用了98個系統(tǒng)調(diào)用;但在容器運行的過程中,數(shù)據(jù)庫服務(wù)型容器中用到的可執(zhí)行文件數(shù)目往往多于Web服務(wù)型,其中Mysql最多,達到了57個,這也驗證了數(shù)據(jù)庫型容器鏡像的大小往往大于web服務(wù)型容器.
表3 動態(tài)分析結(jié)果Table 3 Result of dynamic analysis
在容器初始化運行的過程中,系統(tǒng)調(diào)用執(zhí)行的數(shù)量會達到成百數(shù)千個,圖4展示了每個容器中調(diào)用最頻繁的前20個系統(tǒng)調(diào)用,可以發(fā)現(xiàn)頻率最高的幾個系統(tǒng)調(diào)用為rt_sigaction()、read()、opennat()、mmap()等,rt_sigaction()用于更改進程在接收到特定信號時采取的行為,read()用于讀取文件,opennat()用于打開文件,mmap()能夠?qū)⑽募成涞絻?nèi)存空間,然后可以通過讀寫內(nèi)存來讀寫文件.可以看出,在容器初始化階段,大多數(shù)系統(tǒng)調(diào)用用于對文件系統(tǒng)的訪問以及信號的處理上.
圖4 每個容器中使用頻率最多的系統(tǒng)調(diào)用使用次數(shù)Fig.4 Most frequently used syscall usage per container
3.2.2 靜態(tài)分析
靜態(tài)分析引擎分析每個容器中提取的可執(zhí)行文件的系統(tǒng)調(diào)用數(shù),部分結(jié)果如表4 顯示,在容器運行過程中,除了容器功能相關(guān)的程序之外,一些環(huán)境相關(guān)的程序也會經(jīng)常用到,如find、env等.其中,對于每一個可執(zhí)行文件,在運行時用到的系統(tǒng)調(diào)用數(shù)基本都在70以下,最多的為nginx,用到了62個系統(tǒng)調(diào)用,最少是env,僅僅用了15個系統(tǒng)調(diào)用.
表4 靜態(tài)分析結(jié)果Table 4 Static analysis results
3.3.1 系統(tǒng)調(diào)用數(shù)減少
以前在攻擊面減少的領(lǐng)域的工作主要集中在減少代碼的數(shù)量作為改進的主要措施.相比之下,AutoSec不刪除任何代碼,而只是限制惡意容器可以調(diào)用的系統(tǒng)調(diào)用,它通過減少(潛在惡意)應(yīng)用程序暴露的系統(tǒng)調(diào)用數(shù)量來減少來自于主機內(nèi)核的攻擊面.
實驗通過監(jiān)控容器運行時系統(tǒng)調(diào)用池的數(shù)量驗證減少系統(tǒng)調(diào)用方面的有效性,如圖5所示,在監(jiān)控的60s內(nèi),容器啟動時的前幾秒,系統(tǒng)調(diào)用池的數(shù)量會上升,之后逐漸下降到一個穩(wěn)定的范圍內(nèi),大多數(shù)容器系統(tǒng)調(diào)用池里面的數(shù)量維持在60~100之間,與容器默認允許的將近300個系統(tǒng)調(diào)用相比,AutoSec可以有效的減少容器中70%以上的系統(tǒng)調(diào)用數(shù)量.
圖5 系統(tǒng)調(diào)用池中的數(shù)量波動Fig.5 Number in the syscall pool fluctuates
3.3.2 有效阻止CVE
為了進一步驗證AutoSec在減少容器攻擊面方面的有效性,本文收集了近5年內(nèi)可以通過系統(tǒng)調(diào)用進行漏洞利用的CVE,一共有75個.如CVE-2022-0185使用了fsconfig()系統(tǒng)調(diào)用,CVE-2022-0847使用了splice()系統(tǒng)調(diào)用,其中大約75%的系統(tǒng)調(diào)用只對應(yīng)于1個CVE,19%的系統(tǒng)調(diào)用存在過兩個CVE,7%的系統(tǒng)調(diào)用出現(xiàn)在3個CVE中.
Docker默認的Seccomp策略可以減少25個CVE利用威脅,應(yīng)用AutoSec可以有效的緩解51個CVE對容器的安全威脅.
3.4.1 功能的完備性
為了進一步驗證受限容器功能的完備性,模擬真實場景下一個受限容器與外界的交互的情況,在容器啟動后,AutoSec使用基準測試工具對容器進行測試.CloudSuite[33]的網(wǎng)絡(luò)服務(wù)基準測試是基于開源的社交網(wǎng)站Elgg[34].Elgg是一個基于PHP的應(yīng)用程序,它使用MySQL作為數(shù)據(jù)庫服務(wù)器,提供了一個運行在Web服務(wù)器上的流媒體服務(wù)器,本文使用CloudSuite來對Nginx和Httpd進行功能測試;對于MySQL和Postgres,實驗分別選取了Sysbench[35]和Pgbench[36]對其進行基準測試.
除了基準測試外,本文還同時對容器進行手動的命令調(diào)試,以測試容器是否因為合法的命令執(zhí)行而崩潰.在對容器一周的運行測試中,容器沒有因為意外的命令執(zhí)行而崩潰.使用AutoSec對容器進行安全加固基本不會影響容器功能的完備性.
3.4.2 性能的穩(wěn)定性
對容器施加Seccomp策略,會對容器的性能產(chǎn)生一定的負面影響.由于容器默認啟用了Seccomp過濾器,因此過濾規(guī)則的更改幾乎不會影響應(yīng)用程序的性能.此外,一個容器中的所有進程共享同一組Seccomp過濾器,因此在更新系統(tǒng)調(diào)用池時,只需要生成一個新的BPF程序結(jié)構(gòu)來記錄BPF指令,并刪除舊的BPF程序結(jié)構(gòu)即可.
本文使用上面提到的基準測試工具來測量容器的每秒服務(wù)數(shù)量TPS(Transaction per Second),圖6展示了與不施加Seccomp策略相比,施加Docker默認的Seccomp策略與Autosec的策略在TPS上的減少百分比.可以發(fā)現(xiàn),與不施加任何Seccomp策略相比,使用Seccomp策略導(dǎo)致容器的TPS都略有減少,Autosec的策略會略高于Docker默認的策略,原因是Docker默認的Seccomp策略雖然包含更多的Seccomp規(guī)則,但是AutoSec在運行中對系統(tǒng)調(diào)用的調(diào)度以及BPF策略的生成會增加系統(tǒng)的開銷.但是與默認的策略相比,開銷增加都在2%之內(nèi),基本不會對容器的正常運行產(chǎn)生負面影響,可以認為是能夠接受的系統(tǒng)開銷.
圖6 施加Seccomp策略導(dǎo)致TPS減少的百分比Fig.6 Percentage reduction in TPS due to application of Seccomp policy
容器的安全性近年來備受關(guān)注,學(xué)者們做了不少的相關(guān)工作.在減少容器攻擊面方面,Cimplifier[37]依賴于動態(tài)識別資源,然后根據(jù)分析的結(jié)果,在滿足用戶自定義約束的前提下將一個復(fù)雜容器分離為單一用途的容器,然后通過遠程過程調(diào)用(RPC)實現(xiàn)分離容器之間的通信.Lic-Sec[39]結(jié)合了LicShield[40]和Docker-Sec[38]的工作,并在其基礎(chǔ)上進行了改進,首先通過SystemTap動態(tài)跟蹤內(nèi)核操作,之后將所有的追蹤結(jié)果轉(zhuǎn)換為AppArmor規(guī)則,基于強制訪問控制來增強Docker容器的安全性.
正如前文所描述的,所有必需的系統(tǒng)調(diào)用都不能單獨通過動態(tài)分析來提取,特別是對于處理異常和錯誤的情況,它們通常不是公共執(zhí)行路徑的一部分.因此動態(tài)分析不能保證完全覆蓋每個應(yīng)用程序所需的所有系統(tǒng)調(diào)用.后來,Confine[13]、Chestnut[15]、RSDS[17]等工作將靜態(tài)分析融入到系統(tǒng)調(diào)用的提取中,以補充動態(tài)分析覆蓋率不足的問題,這在一定程度上緩解了容器運行時的意外崩潰情況.但是靜態(tài)分析的結(jié)果受限于分析范圍的把控,分析范圍過大,得到的系統(tǒng)調(diào)用集合起不到很好的安全保護作用,分析范圍過小,則無法彌補動態(tài)分析的短板.此外,無論是動態(tài)還是靜態(tài)分析,受限容器的可用性都無法得到很好的滿足,調(diào)試工具和一些應(yīng)用程序無法使用,除了滿足基本功能之外,容器內(nèi)的程序幾乎無法被調(diào)試.
AutoSec強調(diào)容器的安全性與可用性的均衡,主要靈感來自于Face-change[41]、AutoArmor[42]等按需調(diào)度所需功能進而減少攻擊面的方式,相比于Cimplifier、Confine等工作,AutoSec不盲目的尋求最小的系統(tǒng)調(diào)用集合,而是使用動靜態(tài)結(jié)合的方式盡可能的獲取多的容器運行狀態(tài),之后使用按需調(diào)度的方式再賦予給容器系統(tǒng)調(diào)用,旨在保護安全性的同時,使用戶感覺不到受限容器與普通容器的區(qū)別,仍然能夠滿足容器的大部分功能需求.
為了保護容器的安全,減少容器的攻擊面,本文基于Seccomp BPF提出了一種容器系統(tǒng)調(diào)用限制策略自動生成和按需調(diào)度方法,并實現(xiàn)了該方法實現(xiàn)了系統(tǒng)原型AutoSec,AutoSec通過動態(tài)訓(xùn)練和靜態(tài)分析相結(jié)合的方式來提取容器的系統(tǒng)調(diào)用,進而生成不同的Seccomp BPF規(guī)則,在容器生命周期的不同階段,根據(jù)容器的功能需求動態(tài)的調(diào)度可用的系統(tǒng)調(diào)用.實驗選取了Docker Hub中最為流行的4款容器,通過安全性和可用性兩個方面對AutoSec進行驗證,結(jié)果表明在能夠接受的性能損耗內(nèi),并不損傷容器原有的功能下,可以有效的減少暴露在容器中70%以上的系統(tǒng)調(diào)用,有效的保護容器安全.