如何通过 kubectl 进入 node shell

饭宝  金牌会员 | 2022-11-27 14:45:30 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 898|帖子 898|积分 2694

概述

假设这样一个场景:
生产环境中,Node 都需要通过堡垒机登录,但是 kubectl 是可以直接在个人电脑上登录的。
这种场景下,我想要通过 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 如下:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   labels:
  5.     run: nsenter-v0l86q
  6.   name: nsenter-v0l86q
  7.   namespace: default
  8. spec:
  9.   containers:
  10.   - command:
  11.     - nsenter
  12.     - --target
  13.     - "1"
  14.     - --mount
  15.     - --uts
  16.     - --ipc
  17.     - --net
  18.     - --pid
  19.     - --
  20.     - bash
  21.     - -l
  22.     image: docker.io/library/alpine
  23.     imagePullPolicy: Always
  24.     name: nsenter
  25.     securityContext:
  26.       privileged: true
  27.     stdin: true
  28.     stdinOnce: true
  29.     tty: true
  30.   hostNetwork: true
  31.   hostPID: true
  32.   restartPolicy: Never
  33.   tolerations:
  34.   - key: CriticalAddonsOnly
  35.     operator: Exists
  36.   - effect: NoExecute
  37.     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 更方便

这里推荐 2 个工具,可以更方便地进入 node shell。
krew node-shell

可以通过 kubectl 插件管理工具 krew 安装 node-shell.
如下:
  1. # 安装工具
  2. kubectl krew install node-shell
  3. # 进入 node shell
  4. Kubectl node-shell <node-name>
复制代码
Lens

Kubernetes 图形化管理工具 - Lens 也有相关功能。
具体使用方法如下:


总结

上文介绍了通过 kubectl 命令以 root 权限进入 node shell 的方法,非常简单,实际上在大多数的原生 Kubernetes 上都生效。
这个命令实际上是一定程度上利用了安全上的未加固配置。
这里最后还是建议大家除了对 OS 进行安全加固,对 Kubernetes 也要按照安全最佳实践进行安全加固。(典型的就是起码 PSP 等 policy 不要设置为 privileged, 而是设置为 Baseline 或 Restricted)

注意安全!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

饭宝

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表