The Route to Host:從內核提權到容器逃逸
前言
目前Linux內核代碼已經達到了2700萬行量級[2],僅每年通報的Linux內核漏洞就多達數十個。Linux內核主要使用C語言編寫,由于C語言不是類型安全語言,而且偏底層,所以各種內存破壞類漏洞層出不窮。攻擊者利用內核漏洞可以達到本地提權的目的。容器技術本身依賴于Linux內核提供的Namespaces和Cgroups機制,利用內核漏洞,攻擊者可以繞過Namespaces對資源的隔離,達到逃逸的目的。相比于容器引擎漏洞造成的逃逸,Linux內核漏洞危害更大、威脅更廣。
本文接下來會首先介紹利用內核漏洞進行逃逸的思路,重點不在于內核漏洞的利用手法,而是在于提權過后如何進行容器的逃逸。在實踐中我們也注意到一部分內核漏洞的利用方法和經典思路不同,后文會對這些漏洞進行梳理。基于以上的了解,本文提出了一套流程以輔助攻擊者利用內核漏洞進行容器逃逸。同時,進一步思考利用Linux內核漏洞進行逃逸能否實現工程化利用,這其中的難點是什么。最后,本文將從防御的角度進行探討,哪些防御機制可以幫助我們保護容器系統的機密性、完整性和可用性。
聲明:本文內容僅供合法教學及研究使用,不得將相關知識、技術應用與非法活動!
一、如何利用內核漏洞進行容器逃逸
為了能夠更好地展示利用內核漏洞進行容器逃逸的原理,本文將以經典的內核提權漏洞CVE-2017-7308進行闡述。對于此漏洞的完整利用方法可以參考ExP原作者的博客[3]。
CVE-2017-7308是一個整數溢出漏洞,由于內核在判斷收到數據長度時存在整數溢出,攻擊者可以控制函數指針實現內核代碼的任意執行。攻擊者利用漏洞執行了內核代碼以關閉SMEP和SMAP保護機制,為ret2usr[4]提供了方便。再次利用該漏洞,將控制流劫持到位于用戶地址空間的代碼中,CPU則以內核模式執行以下代碼:
void *g = find_task_by_vpid(1);switch_task_namespaces(g,(void*)init_nsproxy);commit_creds(prepare_kernel_cred(0));long mnt_fd = do_sys_open(AT_FDCWD,"/proc/1/ns/mnt", O_RDONLY,0);sys_setns(mnt_fd,0);long pid_fd = do_sys_open(AT_FDCWD,"/proc/1/ns/pid", O_RDONLY,0);sys_setns(pid_fd,0);
對于這段代碼的理解需要首先從著名的數據結構task_struct說起:Linux內核中通過task_struct(/include/linux/sched.h)結構體管理進程(任務),task_struct是一個非常復雜的結構體,其中一個域為struct nsproxy *nsproxy。
struct task_struct{ ... struct nsproxy *nsproxy; ...}
nsproxy指針指向了一個struct nsproxy結構體,該結構體的如下所示。
* A structure to contain pointers to all per-process* namespaces - fs(mount), uts, network, sysvipc, etc.** The pid namespace is an exception -- it's accessed using* task_active_pid_ns. The pid namespace here is the* namespace that children will use.** 'count' is the number of tasks holding a reference.* The count for each namespace, then, will be the number* of nsproxies pointing to it, not the number of tasks.** The nsproxy is shared by tasks which share all namespaces.* As soon as a single namespace is cloned or unshared, the* nsproxy iscopied.*/struct nsproxy { atomic_t count; struct uts_namespace *uts_ns; struct ipc_namespace *ipc_ns; struct mnt_namespace *mnt_ns; struct pid_namespace *pid_ns_for_children; struct net *net_ns; struct time_namespace *time_ns; struct time_namespace *time_ns_for_children; struct cgroup_namespace *cgroup_ns;};extern struct nsproxy init_nsproxy;
這里出現了容器技術所需要的各種namespaces,由不同的指針指向不同的結構體。通過內核中的注釋可以了解到:
1. struct nsproxy結構體中的指針指向了進程的namespaces;
2. 位于相同namespaces的進程會共享同一個struct nsproxy結構體。
可以自然地想到,宿主機上沒有經過容器化的進程,它們位于同一組namespaces中,所以會共享同一個struct nsproxy結構體。Linux系統中,PID為1的進程被稱為init進程,系統中的所有進程都是通過init進程直接或者間接fork而來的。所以所有沒有被修改namespaces的進程都和init進程共享同一組namespaces,即它們擁有同一個struct nsproxy結構體。
如上文中代碼所示,init進程的struct nsproxy結構體有一個特殊的名字init_nsproxy。init_nsproxy在內核中實現如下:
struct nsproxy init_nsproxy ={ .count = ATOMIC_INIT(1), .uts_ns =&init_uts_ns,#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC) .ipc_ns =&init_ipc_ns,#endif .mnt_ns = NULL, .pid_ns_for_children =&init_pid_ns,#ifdef CONFIG_NET .net_ns =&init_net,#endif#ifdef CONFIG_CGROUPS .cgroup_ns =&init_cgroup_ns,#endif#ifdef CONFIG_TIME_NS .time_ns =&init_time_ns, .time_ns_for_children =&init_time_ns,#endif};
于是可以得出這樣的結論,如果可以將容器中進程的nsproxy結構體替換成init_proxy,那么就可以突破namespaces的限制,進而達到逃逸的目的。恰好,內核提供了這樣的函數switch_task_namespaces:
void switch_task_namespaces(struct task_struct *p,struct nsproxy *new){ struct nsproxy *ns;
might_sleep();
task_lock(p); ns = p->nsproxy; p->nsproxy = new; task_unlock(p);
if(ns) put_nsproxy(ns);}
這個函數在內核中的實現非常簡單,該函數接受task_struct和nsproxy結構體指針作為參數,將task_struct中nsproxy指針指向了傳進來的參數。
對于容器中進程來說,它們位于相同的PID namespaces中。容器中所有的進程都是通過該PID namespaces中的1號進程直接或間接fork而來的。可以通過內核函數find_task_by_vpid(1)獲取容器內init進程的task_struct
void *g = find_task_by_vpid(1);switch_task_namespaces(g, (void*)init_nsproxy);
通過調用這兩個函數,成功將容器內的init進程切換到了init_nsproxy。至此,逃逸已經完成了一半。最后只需要將漏洞利用進程切換到和init進程相同的namespaces中去即可完成逃逸。這需要使用到setns系統調用[5],該系統調用的功能就是將進行此系統調用的進程切換到指定的namespaces中。
#define _GNU_SOURCE /*See feature_test_macros(7) */#include int setns(int fd,int nstype);
只有擁有CAP_SYS_ADMIN權限的進程才能進行setns系統調用,如果想要切換mnt namespaces還額外需要CAP_SYS_CHROOT權限。參數fd是一個指向/proc/[pid]/ns/目錄下文件的文件描述符;參數nstype指定了想要切換的namespaces,如果指定為0內核會根據fd指向的文件切換對應的namespaces。例如 setns(/proc/1/ns/mnt, 0),其中[pid]為1,即剛剛切換的容器內init進程的進程號,這樣可以切換mnt namespaces以訪問宿主機上的文件系統,同理可以切換PID namespaces以查看運行在宿主機上的進程。
每個進程都有一個/proc/[pid]/ns/子目錄,以軟鏈接的方式展示可以使用setns系統調用的namespaces。在宿主機中查看進程的namespaces:
$ ls -al /proc/self/nstotal 0dr-x--x--x 2 xsw xsw 0 Feb 22 23:14 .dr-xr-xr-x 9 xsw xsw 0 Feb 22 23:14 ..lrwxrwxrwx 1 xsw xsw 0 Feb 22 23:15 cgroup ->cgroup:[4026531835]lrwxrwxrwx 1 xsw xsw 0 Feb 22 23:15 ipc ->ipc:[4026531839]lrwxrwxrwx 1 xsw xsw 0 Feb 22 23:15 mnt ->mnt:[4026531840]lrwxrwxrwx 1 xsw xsw 0 Feb 22 23:15 net ->net:[4026531957]lrwxrwxrwx 1 xsw xsw 0 Feb 22 23:15 pid ->pid:[4026531836]lrwxrwxrwx 1 xsw xsw 0 Feb 22 23:15 user ->user:[4026531837]lrwxrwxrwx 1 xsw xsw 0 Feb 22 23:15 uts ->uts:[4026531838]
啟動一個容器,再次查看:
# ls -al /proc/self/nstotal 0dr-x--x--x 2 root root 0 Feb 23 07:15 .dr-xr-xr-x 9 root root 0 Feb 23 07:15 ..lrwxrwxrwx 1 root root 0 Feb 23 07:15 cgroup ->'cgroup:[4026531835]'lrwxrwxrwx 1 root root 0 Feb 23 07:15 ipc ->'ipc:[4026532758]'lrwxrwxrwx 1 root root 0 Feb 23 07:15 mnt ->'mnt:[4026532756]'lrwxrwxrwx 1 root root 0 Feb 23 07:15 net ->'net:[4026532816]'lrwxrwxrwx 1 root root 0 Feb 23 07:15 pid ->'pid:[4026532814]'lrwxrwxrwx 1 root root 0 Feb 23 07:15 user ->'user:[4026531837]'lrwxrwxrwx 1 root root 0 Feb 23 07:15 uts ->'uts:[4026532757]'
可以發現對應的ipc、mnt、net、pid和uts發生了變化,說明容器創建了對應的namespaces。利用漏洞進行提權、逃逸,在彈出的root shell中再次查看:
# ls -al /proc/self/nstotal 0dr-x--x--x 2 root root 0 Feb 22 23:16 .dr-xr-xr-x 9 root root 0 Feb 22 23:16 ..lrwxrwxrwx 1 root root 0 Feb 22 23:16 cgroup ->cgroup:[4026531835]lrwxrwxrwx 1 root root 0 Feb 22 23:16 ipc ->ipc:[4026532758]lrwxrwxrwx 1 root root 0 Feb 22 23:16 mnt ->mnt:[4026531840]lrwxrwxrwx 1 root root 0 Feb 22 23:16 net ->net:[4026532816]lrwxrwxrwx 1 root root 0 Feb 22 23:16 pid ->pid:[4026532814]lrwxrwxrwx 1 root root 0 Feb 22 23:16 user ->user:[4026531837]lrwxrwxrwx 1 root root 0 Feb 22 23:16 uts ->uts:[4026532757]

為了不讓完整的漏洞利用功虧一簣,由于我們已經通過漏洞利用實現了任意內核代碼執行,可以考慮直接調用系統調用對應的內核函數完成namespaces的切換。sys_setns即為setns系統調用在內核中調用的函數,同理do_sys_open是open系統調用對應的內核函數。
long mnt_fd = do_sys_open(AT_FDCWD,"/proc/1/ns/mnt", O_RDONLY,0);sys_setns(mnt_fd,0);long pid_fd = do_sys_open(AT_FDCWD,"/proc/1/ns/pid", O_RDONLY,0);sys_setns(pid_fd,0);
值得注意的是,K8s在1.19版本中才正式引入了Seccomp[8]。在沒有Seccomp限制的版本仍然可以使用setns進行切換。
通過以上分析,我們總結出以下結論:在利用內核漏洞達到執行任意內核代碼后,可以首先通過switch_task_namespaces(find_task_by_vpid, init_nsproxy)切換容器中init進程的namespaces,然后調用commit_creds(prepare_kernel_cred(0))進行提權以獲取全部的Capabilities。在拿到CAP_SYS_ADMIN后,通過setns(open("/proc/1/ns/mnt",O_RDONLY), 0)可以成功完成容器逃逸。
二、內核提權,不止于此
通常情況下,對于內核漏洞來說,通過一些漏洞利用的手法,最終可以覆蓋函數指針或者覆蓋棧上的函數返回地址,劫持控制流到攻擊者控制的內存區域(ret2usr)或者進行ROP,獲取執行任意內核代碼的能力,接著執行commit_creds(prepare_kernel_cred(0))進行提權。在實踐的過程中,我們注意到還有一些內核漏洞及利用手法,采用了不同的提權方式,而這些漏洞也可能為容器逃逸提供便利。
1CVE-2016-5195
CVE-2016-5195即為大名鼎鼎的DirtyCoW漏洞,該漏洞利用Linux內核的寫時復制(Copy-on-write)機制創建了條件競爭場景,成功繞過了vDSO對于內存權限的限制,攻擊者可以實現本地提權。vDSO是一個共享庫,內核會將其加載到所有進程的用戶地址空間中。vDSO主要解決一些對于執行時間敏感的系統調用執行時間過長的問題。當root進程調用vDSO地址空間的函數時,注入的shellcode將會被執行。將反彈shell的代碼寫入到shellcode中,那么則會向指定IP和端口反彈一個root shell。
該原理也可用于容器逃逸,由于shellcode的調用者是宿主機上的進程,即使在沒有切換namespaces的條件下也可以實現容器的逃逸。
vDSO的內存區域被設置為不可寫,如果想要修改權限需要用到set_memory_rw 內核函數,其利用過程依然需要實現內核任意代碼的執行。但是CVE-2016-5195利用Linux內核的Copy-on-Write機制的漏洞繞過了權限檢查,最終實現了向vDSO中注入代碼。
2CVE-2018-18955
CVE-2018-18955是一個邏輯漏洞,在這里不展開介紹其漏洞原理,有興趣的讀者可以從exploit-db[9]獲取完整ExP進行復現,利用Metarget[10]輔助進行環境搭建。該漏洞恰好位于user namespaces的實現中,攻擊者在容器內讀取到宿主機中的密碼文件等敏感文件,間接實現了容器逃逸。這里的逃逸沒有突破namespaces的限制,但是客觀上對宿主機的機密性造成了破壞。
如果一個漏洞發生在和權限管理以及容器實現機制相關的代碼中,那么利用手段通常會和常見的內存類漏洞有所不同。對于這類漏洞,只能具體問題具體分析,這要求攻擊者對內核有更加深入的了解。
3CVE-2022-0185
CVE-2022-0185[11]是一個“新鮮出爐”的Linux內核提權漏洞,綠盟科技研究通訊已經發布文章《Linux內核漏洞——CVE-2022-0185分析與思考》對此漏洞進行了介紹。這里主要想要介紹該漏洞依賴的另一種常見的提權手段:modprobe_path。CVE-2022-0185利用fsconfig系統調用實現上的漏洞,可以溢出任意字節。在覆蓋了內核中的指針后,實現了內核任意讀和內核任意寫。攻擊者覆蓋了內核中變量modprobe_path,使得內核會以root權限執行用戶指定的腳本,達到提權的目的。
modprobe_path變量保存著一個文件路徑,每當加載或卸載內核模塊、執行內核不識別的可執行程序時,modprobe_path指定路徑的程序將會以root權限運行。提權準備一個腳本程序,該程序會設置/bin/bash的suid位。利用任意寫等漏洞將modprobe_path覆蓋為腳本程序的路徑,然后執行一個錯誤的格式的文件。此時,/bin/bash會被設置為suid為,然后執行/bin/bash -p啟動一個root權限的shell,即可達到提權的目的。
但是,通過modprobe_path只能完成容器內的提權操作。即使獲得了完整的Capabilities,所有的操作也會受到Namespaces和Cgroups的限制,無法逃逸。而且,針對modprobe_path在提權中的濫用,內核實現了STATIC_USERMODEHELPER機制。在開啟了STATIC_USERMODEHELPER的系統上,無法通過覆蓋modprobe_path實現提權。
繼續利用CVE-2022-0185,攻擊者泄露了堆地址,最終通過ROP實現了內核代碼任意執行,按照本文第一節的思路實現了容器逃逸。
本節以三個實際的漏洞案例展示了區別于經典commit_creds(prepare_kernel_cred(0))的Linux提權方式,除此以外,還有劫持prctl等提權方案。同時也可以看到,提權和逃逸操作并不完全等同,劫持vDSO的手段可以實現容器逃逸,而由于modprobe_path指向的文件是受到mnt namespaces隔離的,劫持modprobe_path不能實現容器的逃逸。
一個內核漏洞是否能夠實現容器提權,除了漏洞本身外,很大程度也取決于漏洞利用的手法,這要求分析者不僅要對容器的實現原理了然于心,而且還需要對內核有充分的理解、對內核漏洞利用有足夠的經驗。這對分析人員提出了非常高的要求。下一節將從逃逸的角度給出內核漏洞的分析思路,不聚焦于漏洞利用的手段,而是主要關注內核漏洞和容器逃逸的關系。
三、分析思路
在驗證漏洞利用程序可以進行本地提權后,應當如何進行容器逃逸?分析思路不是一成不變的,應當根據具體情況靈活選擇。下面的步驟僅僅是一個參考,在實踐時還需要結合實際進行考量。
1 判斷漏洞利用前提
和宿主機的環境相比,容器環境往往存在更多的防御機制。我們應當首先判斷Capabilities和Seccomp限制情況。對于實驗環境,尤其需要關注權限的限制。不同的容器引擎對于權限的默認配置也不同,構造什么樣的環境取決于漏洞利用的目的。
構造實驗環境時,我們還需要關注一些隱性條件。例如,該漏洞或利用程序是否依賴于開啟某個編譯選項、利用程序是否假設了一些防御機制未開啟等。
2判斷提權漏洞利用的方法
首先應當對漏洞提權利用程序有初步的了解,判斷漏洞利用程序所需的Capabilities權限和需要的系統調用。如果漏洞的觸發需要特殊的Capabilities,利用程序通常會進行unshare系統調用以創建user namespaces。除了unshare系統調用,漏洞利用程序可能還會使用到一些敏感的系統調用。例如上文提到的CVE-2016-5195漏洞利用程序在進行代碼注入時,使用了ptrace系統調用。
接下來,需要判斷提權的方法:
利用commit_cred(prepare_kernel_cred(0))進行提權
可以初步判斷,漏洞利用程序是通過執行內核代碼實現的內核提權。對于這種情形可以考慮直接構造逃逸的利用鏈[12]。
覆蓋modprobe_path或劫持prctl實現的提權
基于modprobe_path和劫持prctl的提權方式不能直接應用于容器的逃逸。對于這種情況,需要繼續構造利用鏈。CVE-2022-0185利用程序的作者首先使用modprobe_path的方式進行本地提權,對于容器逃逸,作者繼續利用溢出漏洞構造了ROP利用鏈,最終實現了內核代碼任意執行。
覆蓋vDSO進行提權
上文已經進行了分析,利用vDSO可以實現容器的逃逸。對于這種情形可以考慮直接進行漏洞利用。
邏輯漏洞導致的提權
相關權限管理和容器實現機制產生的漏洞,需要深入挖掘內核相關的機制,具體案例具體分析。
3逃逸利用
最后即為漏洞利用過程,需要構造payload。在構造payload時,仍然有一些問題需要考慮。例如,繞過KALSR需要考慮使用相對于內核的偏移量+內核基址進行調用、漏洞利用是否對內存布局有限制等問題。只有將所有問題考慮周全,才能構造出一個可用的漏洞利用程序。
四、進一步思考:自動化利用
漏洞自動化利用(AEG)如火如荼的今天,容器逃逸如果可以工具化、工程化將大大提高漏洞利用的效率。本節將展望利用Linux內核漏洞的容器自動化逃逸,并梳理其實現的技術難點,希望對感興趣的讀者有所啟發。
假設已經通過一些漏洞利用手段獲得了內核代碼任意執行的能力,自動化利用需要將逃逸代碼注入到payload中。程序的輸入是內核漏洞利用程序的源代碼,輸出則是容器逃逸的漏洞利用程序。自動化利用的程序面臨著以下難點:
1. 識別內核漏洞提權所使用的方法。如上文所述,提權具有多種方法。即使輸入的漏洞利用代碼是通過執行內核代碼commit_creds(prepare_kernel_cred(0))進行提權,也需要考慮是通過ret2usr或者ROP甚至是直接注入shellcode進行的。從編譯器的角度看,其都以數據的形式存在,想要進行區分需要識別具體的特征。
2. 識別payload。和難點1相同,payload總是以代碼和數據形式存在的。只有定位了payload,才能將提權的代碼注入到payload中。除識別payload外,還需要識別注入點在payload的偏移量。
3. 生成正確形式的payload。由于KASLR的存在,對于內核中函數或者變量的引用都需要使用內核基址+相對于內核基址的偏移量。首先需要確認利用源碼中繞過KASLR的代碼,識別出內核基址保存在哪個變量中。同時還需要搭建本地環境,在本地環境中計算出其相對于內核基址的偏移量。
以上難點頻繁提到了“識別”,實際上“識別”的操作實際已經超出了編譯相關知識的范疇,筆者認為,應當結合NLP、AEG相關知識進行輔助。
五、防御手段
前文主要站在攻擊者角度進行討論,本節將站在防御者的角度,主要介紹針對于內核漏洞導致的逃逸的防御手段。
1 最小權限原則
針對利用內核漏洞的容器逃逸手法最好的防御思路就是最小權限原則[13]。該概念最早由Peter J. Denning在1976年提出,指計算機中的每個主體(進程)只能訪問當下所需要的客體(資源)。
Capabilities
Capabilities[14]在2.2版本引入內核,主要解決root權限過于集中的問題。Capabilities將內核的root權限劃分為若干的能力,子進程會按照一定的規則繼承父進程的能力。
多個漏洞的利用都會受到Capabilities的限制,CVE-2017-7308需要CAP_SYSLOG權限以繞過KASLR,CVE-2021-22555需要CAP_NET_ADMIN以觸發漏洞。
如果一個容器只被賦予了所需的Capabilities,那么會顯著增加漏洞的利用難度。
Seccomp
Seccomp[15]最早在3.16版本引入內核,其主要功能是限制進程使用特定的系統調用,子進程會繼承父進程的seccomp限制。上文提到的Capabilities限制可以通過創建一個user namespaces進行繞過,在新的user namespaces中用戶會被授予完整的Capabilities,但是僅局限于受限的環境中。創建user namespaces需要使用unshare系統調用,正如上文所提及的一樣,作為敏感的系統調用unshare被docker的默認seccomp配置所限制。如果一個容器只賦予了程序所需的Capabilities和系統調用,那么大多數的內核漏洞都將無法被利用。
Seccomp和Capabilities共同作用,完成對容器安全的守護。
LSM
LSM,指Linux安全模塊,例如SELinux[16]、AppArmor等。通過強制訪問控制,限制進程可以訪問的資源。相比于Capabilities和Seccomp,LSM可以進行更加細粒度的訪問控制,包括可以訪問文件、套接字等。但是,如何寫出良好的LSM配置文件則是問題的難點。對于此問題,有多篇研究論文[17-19]。主流的方式是利用動態分析的方法,獲取容器應用所需要的權限全集。或者使用靜態的分析手段,結合程序分析的方法,自動生成配置文件。
Non-root containers
由于容器的創建需要使用namespaces,而namespaces的創建時需要特權操作,所以使用容器時默認情況下會得到一個root權限的環境。以Docker為例,默認會得到一個被Capabilities和Seccomp限制的rootshell。Non-root containers實際上是最小權限原則在容器環境中的應用。同樣以Docker為例,Docker提供了三種不同形式Non-root containers:
1. Userns-remap[20]
2. Rootless mode[21]
3. USER containers[22]
Userns-remap是指容器的創建位于一個新的User namespaces中。利用User namespaces可以使用普通用戶權限啟動一個容器。Rootless mode的實現同樣依賴于User namespaces,相比于Userns-remap,Docker的守護進程和容器都沒有運行在root權限下。USER containers則是通過user映射實現的,在容器中能夠以普通用戶的權限執行程序。
2 安全防護系統
上文提供了多種防御機制,在啟用上述機制的容器系統上逃逸已經變得困難重重。但是,網絡安全沒有銀彈,為了避免百密一疏,還應配備安全防護系統提供專業防護。例如,通過漏洞掃描,及時發現并修復系統存在的安全漏洞;通過配置核查,及時找出并加固系統薄弱項;通過運行時入侵檢測,及時發現異常攻擊、漏洞利用行為等。
云原生時代,安全不可缺席。綠盟科技星云實驗室將持續輸出云原生安全研究成果,最新成果直接賦能綠盟科技云原生安全產品NCSS-C,為您的云原生業務保駕護航。
六、總結
本文分別從namespaces實現原理、典型逃逸漏洞、通用逃逸方法和防御手段等角度,就利用Linux內核漏洞進行逃逸做進行了深入的探討。盡管每個漏洞各有各的不同,但是就容器逃逸來講還是遵循了一些固定的步驟。無論是攻擊者還是防御者,都應當盡可能深入了解其背后的原理,做到知其然更知其所以然。
同時也可以注意到,容器安全攻防博弈演進的特性,這也是整個信息安全領域的基本特征。攻擊和防御手段的進步是相輔相成的,防御機制會促進新型攻擊手法的誕生,新型攻擊手法則又會對防御機制提出更高的要求。本文的重點在攻擊,但也是想幫助防御者理解容器逃逸的攻擊方法,畢竟,未知攻,焉知防?
最后,向大家推薦由綠盟科技星云實驗室編寫的《云原生安全:攻防實踐與體系構建》一書,本書系統梳理云原生安全可能面臨的威脅與風險,給出切實可行的防護方案,隨書附帶豐富的配套實驗。云原生從業者以及對云原生安全感興趣的同學一定不要錯過!
參考文獻
1. https://mp.weixin.qq.com/s/_GwGS0cVRmuWEetwMesauQ
2. GitStats - linux(phoronix.com)
3. ProjectZero: Exploiting the Linux kernel via packet sockets(googleprojectzero.blogspot.com)
4. Kemerlis V P, Portokalidis G, Keromytis A D.{kGuard}: Lightweight Kernel Protection against {Return-to-User}Attacks[C]//21st USENIX Security Symposium (USENIX Security 12). 2012: 459-474.
5. setns(2) - Linuxmanual page (man7.org)
6. namespaces(7) -Linux manual page (man7.org)
7. Seccomp securityprofiles for Docker | Docker Documentation
8. Restrict aContainer's Syscalls with seccomp | Kubernetes
9. Linux - Broken uid/gid Mappingfor Nested User Namespaces - Linux local Exploit (exploit-db.com)
10. Metarget/metarget:Metarget is a framework providing automatic constructions of vulnerableinfrastructures. (github.com)
11. Will's Root:CVE-2022-0185 - Winning a $31337 Bounty after Pwning Ubuntu and EscapingGoogle's KCTF Containers (willsroot.io)
12. Routeto Root: Container Escape Using Kernel Exploitation (cyberark.com)
13. P. J. Denning. Fault tolerant operating systems.ACM Computing Surveys (CSUR). December 1976, 8 (4): 359 – 389. ISBN 0360-0300.
14. capabilities(7)- Linux manual page (man7.org)
15. seccomp(2) - Linuxmanual page (man7.org)
16. selinux(8) - Linuxmanual page (man7.org)
17. Ghavamnia S, Palit T, Benameur A, et al.Confine: Automated system call policy generation for container attack surfacereduction[C]//23rd International Symposium on Research in Attacks, Intrusionsand Defenses (RAID 2020). 2020: 443-458.
18. Mattetti M, Shulman-Peleg A, Allouche Y, et al.Securing the infrastructure and the workloads of linux containers[C]//2015 IEEEConference on Communications and Network Security (CNS). IEEE, 2015: 559-567.
19. LeiL, Sun J, Sun K, et al. SPEAKER: Split-phase execution of applicationcontainers[C]//International Conference on Detection of Intrusions and Malware,and Vulnerability Assessment. Springer, Cham, 2017: 230-251.
20. Isolate containerswith a user namespace | Docker Documentation
21. Run the Docker daemonas a non-root user (Rootless mode) | Docker Documentation
22. Dockerfilereference | Docker Documentation