如何通過終端快速訪問 Kubernetes 節點 Shell 的 Root 環境 (無需 SSH 權限 )
概述
這種場景下,我想要通過 kubectl 登錄到 K8S 集群里的 Node,可以實現嗎?
可以的!本質上是利用容器(runC)的弱隔離(共享內核,Cgruop 等實現進程隔離)實現的權限逃逸。
如果貴司使用的一些商業容器平臺(如:openshift,rancher)等,可能默認安裝時就會通過 PSP scc 或 policy 等預先屏蔽掉這層隱患。但是如果是原生的 Kubernetes, 往往下面的辦法是可行的。
原理概述
先說本質,本質上就是:
容器(runC)是弱隔離
?對于虛擬機來說,虛擬機是通過內核(kernel)級別的隔離,不同的虛擬機有不同的內核,所以安全性要高很多,從虛擬機逃逸到其所在的物理機上是非常困難的。?但是,容器(runC)是弱隔離,一臺機器上的所有容器都共享同一個內核,他們之所以默認互相看不見,是通過 Cgroup、net namespace 等實現的進程級別的隔離。
那么,加入你沒有對容器的權限做進一步的限制,我是可以通過運行一個特權容器,直接進入到其所在的 node 上的。
具體步驟
- 適用于 K8S 1.25 之前的版本。
步驟很簡單,就是創建上文說的這么一個特權容器,通過 nsenter command 進入 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 即可進入 node shell。
上面的 yaml,關鍵有這么幾點:
進入 node shell 的命令:nsenter --target 1 --mount --uts --ipc --net --pid -- bash -l,在 Linux 系統里, nsenter 是一個命令行工具,用于進入到另一個 namespace 。譬如, nsenter -n -t 1 bash 就是進入到 pid 為 1 的進程所在的網絡 namespace 里。
以及進入 node shell 的權限:
?hostPID: true 共享 host 的 pid
?hostNetwork: true 共享 host 的網絡
?privileged: true: PSP 權限策略是 privileged, 即完全無限制。
進入 node shell 的 pod 后, 效果如下:
node shell-可以切換 shell
node shell-可以查看所有的進程信息
node shell-可以執行 root 權限的 systemctl
實用工具 - 進入 node shell 更方便
這里推薦 2 個工具,可以更方便地進入 node shell。
krew node-shell
可以通過 kubectl 插件管理工具 krew[1] 安裝 node-shell.
如下:
# 安裝工具
kubectl krew install node-shell
# 進入 node shell
Kubectl node-shell <node-name>
Lens
Kubernetes 圖形化管理工具 - Lens[2] 也有相關功能。
具體使用方法如下:
Lens-選擇指定 node 進入 shell
Lens-實際上也是啟動個特權 pod,可以執行 root 命令
總結
上文介紹了通過 kubectl 命令以 root 權限進入 node shell 的方法,非常簡單,實際上在大多數的原生 Kubernetes 上都生效。
這個命令實際上是一定程度上利用了安全上的未加固配置。
這里最后還是建議大家除了對 OS 進行安全加固,對 Kubernetes 也要按照安全最佳實踐進行安全加固。(典型的就是起碼 PSP 等 policy 不要設置為 privileged, 而是設置為 Baseline 或 Restricted)
注意安全!??????