如何通過(guò)終端快速訪問(wèn) Kubernetes 節(jié)點(diǎn) Shell 的 Root 環(huán)境 (無(wú)需 SSH 權(quán)限 )
概述
這種場(chǎng)景下,我想要通過(guò) kubectl 登錄到 K8S 集群里的 Node,可以實(shí)現(xiàn)嗎?
可以的!本質(zhì)上是利用容器(runC)的弱隔離(共享內(nèi)核,Cgruop 等實(shí)現(xiàn)進(jìn)程隔離)實(shí)現(xiàn)的權(quán)限逃逸。
如果貴司使用的一些商業(yè)容器平臺(tái)(如:openshift,rancher)等,可能默認(rèn)安裝時(shí)就會(huì)通過(guò) PSP scc 或 policy 等預(yù)先屏蔽掉這層隱患。但是如果是原生的 Kubernetes, 往往下面的辦法是可行的。
原理概述
先說(shuō)本質(zhì),本質(zhì)上就是:
容器(runC)是弱隔離
?對(duì)于虛擬機(jī)來(lái)說(shuō),虛擬機(jī)是通過(guò)內(nèi)核(kernel)級(jí)別的隔離,不同的虛擬機(jī)有不同的內(nèi)核,所以安全性要高很多,從虛擬機(jī)逃逸到其所在的物理機(jī)上是非常困難的。?但是,容器(runC)是弱隔離,一臺(tái)機(jī)器上的所有容器都共享同一個(gè)內(nèi)核,他們之所以默認(rèn)互相看不見(jiàn),是通過(guò) Cgroup、net namespace 等實(shí)現(xiàn)的進(jìn)程級(jí)別的隔離。
那么,加入你沒(méi)有對(duì)容器的權(quán)限做進(jìn)一步的限制,我是可以通過(guò)運(yùn)行一個(gè)特權(quán)容器,直接進(jìn)入到其所在的 node 上的。
具體步驟
- 適用于 K8S 1.25 之前的版本。
步驟很簡(jiǎn)單,就是創(chuàng)建上文說(shuō)的這么一個(gè)特權(quán)容器,通過(guò) nsenter command 進(jìn)入 node shell。示例 yaml 如下:
apiVersion: v1
kind: Pod
metadata:
labels:
run: nsenter-v0l86q
name: nsenter-v0l86q
namespace: default
spec:
containers:
- command:
- nsenter
- --target
- "1"
- --mount
- --uts
- --ipc
- --net
- --pid
- --
- bash
- -l
image: docker.io/library/alpine
imagePullPolicy: Always
name: nsenter
securityContext:
privileged: true
stdin: true
stdinOnce: true
tty: true
hostNetwork: true
hostPID: true
restartPolicy: Never
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- effect: NoExecute
operator: Exists
直接 kubectl apply -f node-shell.yaml 即可進(jìn)入 node shell。
上面的 yaml,關(guān)鍵有這么幾點(diǎn):
進(jìn)入 node shell 的命令:nsenter --target 1 --mount --uts --ipc --net --pid -- bash -l,在 Linux 系統(tǒng)里, nsenter 是一個(gè)命令行工具,用于進(jìn)入到另一個(gè) namespace 。譬如, nsenter -n -t 1 bash 就是進(jìn)入到 pid 為 1 的進(jìn)程所在的網(wǎng)絡(luò) namespace 里。
以及進(jìn)入 node shell 的權(quán)限:
?hostPID: true 共享 host 的 pid
?hostNetwork: true 共享 host 的網(wǎng)絡(luò)
?privileged: true: PSP 權(quán)限策略是 privileged, 即完全無(wú)限制。
進(jìn)入 node shell 的 pod 后, 效果如下:
node shell-可以切換 shell
node shell-可以查看所有的進(jìn)程信息
node shell-可以執(zhí)行 root 權(quán)限的 systemctl
實(shí)用工具 - 進(jìn)入 node shell 更方便
這里推薦 2 個(gè)工具,可以更方便地進(jìn)入 node shell。
krew node-shell
可以通過(guò) kubectl 插件管理工具 krew[1] 安裝 node-shell.
如下:
# 安裝工具
kubectl krew install node-shell
# 進(jìn)入 node shell
Kubectl node-shell <node-name>
Lens
Kubernetes 圖形化管理工具 - Lens[2] 也有相關(guān)功能。
具體使用方法如下:
Lens-選擇指定 node 進(jìn)入 shell
Lens-實(shí)際上也是啟動(dòng)個(gè)特權(quán) pod,可以執(zhí)行 root 命令
總結(jié)
上文介紹了通過(guò) kubectl 命令以 root 權(quán)限進(jìn)入 node shell 的方法,非常簡(jiǎn)單,實(shí)際上在大多數(shù)的原生 Kubernetes 上都生效。
這個(gè)命令實(shí)際上是一定程度上利用了安全上的未加固配置。
這里最后還是建議大家除了對(duì) OS 進(jìn)行安全加固,對(duì) Kubernetes 也要按照安全最佳實(shí)踐進(jìn)行安全加固。(典型的就是起碼 PSP 等 policy 不要設(shè)置為 privileged, 而是設(shè)置為 Baseline 或 Restricted)
注意安全!??????