概述
在過去幾年裡,在各種容器平臺(包括Docker,Podman和Kubernetes)中發現了複製(cp)命令的的多個漏洞。其中最嚴重的一個是今年7月才暴露的CVE-2019-14271。CVE-2019-14271源於Docker cp命令實現中的安全bug,當被攻擊者利用時,該漏洞可能導致完全容器權限穿越。自從二月份發現嚴重的runC漏洞之後,第一個完全的容器穿越的漏洞。
如果容器已經被篡改(例如,通過任何其他漏洞,洩露的機密信息等),或者當用戶從不明途徑來源(第三方惡意註冊表或其他來源)運行惡意容器映像時,可能會引發漏洞。如果用戶隨後執行cp命令從受感染的容器中複製文件,則攻擊者可以逃脫並完全控制宿主機機以及該宿主機下的所有容器。
CVE-2019-14271漏洞已經在Docker版本19.33.1中被標記為關鍵項並且已修復。
Docker cp
copy命令可以從容器複製文件,複製文件到容器中,或者在容器之間複製文件。其語法與標準Unix cp命令非常相似。要從容器中複製/var/logs,語法為:
docker cp container_name:/var/logs 宿主機目錄
如您在下圖中所看到的,要將文件複製到容器外,Docker使用了一個名為docker-tar的幫助程序。
docker-tar的工作原理是切入容器(如下圖所示),將請求的文件和目錄打包成tar文件,然後將生成的tar文件傳遞迴Docker守護程序,該守護程序負責將其提取到目標目錄在主機上。
進行Chrooting大多是為了避免符號鏈接問題,當主機進程嘗試訪問容器上的文件時,可能會發生符號鏈接問題。如果這些文件中有一個是符號鏈接,則可能會無意中將其解析為主機根目錄。這為攻擊者控制的容器打開了大門,使他們可以嘗試誘使docker cp在主機而不是容器上讀取和寫入文件。去年,Docke和Podman中的幾CVE漏洞都是關於符號鏈接(CVE-2019-10152,CVE-2018-15664)相關的漏洞。通過切入容器的根目錄,docker-tar確保所有符號鏈接都將在其下有效解析。不幸的是,在從容器中複製文件時,Chrooting做法導致了更嚴重的問題。
漏洞介紹
Docker是使用Golang編寫的。這個漏洞源於Go v1.11版本編譯Docker。在這個版本中,某些包含嵌入式C代碼(cgo)的軟件包將在運行時動態加載共享庫。這些軟件包包括net和os/user,都被docker-tar使用,它們會在運行時加載多個libnss _ *.so的動態庫。通常,庫會從主機文件系統中加載,但是由於docker-tar被chroots到了容器中,因此它會從容器文件系統中加載這些動態庫。這樣docker-tar將加載並執行由容器發起和控制的代碼。
需要注意的是,除了被chroot到容器文件系統之外,docker-tar並未被容器化。它運行在具有所有根功能且不受cgroups或seccomp限制的主機名稱空間中。因此,通過將代碼注入docker-tar,惡意容器獲得了對主機全root權限。
可能的攻擊情形是Docker用戶從以下任一用戶複製一些文件:
運行帶有錯誤libnss _ *.so庫的惡意映像的容器。
受到攻擊的容器,攻擊者在其中替換了libnss _ *.so庫。
在這兩種情況下,攻擊者都可以獲得主機root執行權限。
有趣的是該漏洞實際上是首先從GitHub問題中發現的。
用戶試圖從debian:buster-slim容器中複製文件,docker cp反覆失敗。問題在於該特定鏡像不包含libnss庫。因此,當用戶運行docker cp且docker-tar進程嘗試從容器文件系統加載它們時,報錯崩潰了。
利用原理
CVE-2019-14271需要利用 libnss庫。任意選擇libnss_files.so。構造函數屬性(特定於GCC的語法)指示run_at_link函數在由進程加載時將作為庫的初始化函數執行。當docker-tar進程動態加載我們的惡意庫時,將執行run_at_link。下面是run_at_link代碼:
run_at_link首先驗證它是否在docker-tar上下文中運行,因為其他常規容器進程也可能會加載它。這是通過檢查/proc目錄來完成的。如果run_at_link在docker-tar的上下文中運行,則此目錄將為空,因為/ proc上的procfs掛載僅存在於容器掛接命名空間中。
接下來,run_at_link將libnss庫替換為原始庫。這樣可確保利用此漏洞運行的所有後續進程都不會意外加載惡意版本並重新觸發run_at_link的執行。
為簡化利用,run_at_link嘗試在容器中的路徑/breakout處運行可執行文件。
以下是視頻中使用的/breakout腳本的來源。為了獲得對主機根文件系統的引用,腳本通過/proc掛載了procfs。由於docker-tar在主機的PID名稱空間中運行,因此掛載的procfs將包含主機進程上的數據。然後,該腳本只需掛載主機PID 1r根。
漏洞修復
漏洞修復程序包括修補docker-tar的init函數從有問題的Go軟件包中調用任意函數。
迫使docker-tar在chroot到容器之前從主機文件系統加載libnss庫。
安全建議
允許在主機上執行根代碼的漏洞非常危險。確保運行的是Docker 19.03.1版或更高版本,其中包括針對此安全問題的修復程序。為了限制此類攻擊的攻擊面,強烈建議不要運行不受信任的映像。
此外,在不需要嚴格使用root用戶的情況下,強烈建議以非root用戶身份運行容器,這樣可以進一步提高了其安全性,並阻止了攻擊者利用容器引擎或內核中可能發現的許多缺陷。對於CVE-2019-14271,如果容器使用非root用戶運行,則你不會受漏洞影響。即使攻擊者破壞了容器,也無法覆蓋容器的libnss庫,因該庫為root擁有的,因此無法利用此漏洞。
閱讀更多 蟲蟲安全 的文章