Announcement

👇Official Account👇

Welcome to join the group & private message

Article first/tail QR code

Skip to content

kubectl cp Windows 路径穿越 RCE 深度分析:客户端漏洞为何总是补丁盲区 ​

一、事件速览 ​

2026 年 10 月初,Kubernetes 官方披露 kubectl 在 Windows 平台上的 kubectl cp 存在路径穿越漏洞,可导致远程代码执行。修复版本为:

分支修复版本
v1.361.36.5 及以上
v1.351.35.9 及以上
v1.341.34.12 及以上
更早分支已停止维护,必须升级到上述版本

这个漏洞的关键词是"客户端"。它不影响集群控制面,不需要任何集群权限提升,攻击目标就是运行 kubectl 的那台 Windows 机器——而 Windows 机器恰恰是三类高危场景的宿主:

  1. 管理员跳板机:运维人员从这里直连生产集群
  2. Windows CI/CD Runner:大量企业 CI 用 Windows 节点跑构建
  3. 开发者工作站:本身就是攻击者梦寐以求的代码资产仓库

二、漏洞原理:tar 协议 + Windows 路径语义的错配 ​

2.1 kubectl cp 的工作机制 ​

kubectl cp 并不是一条专用协议。它实际上是在本地打一个 tar 包,然后通过 kubectl exec 往容器里流式解包。等价于:

bash
tar cf - local-file | kubectl exec -i <pod> -- tar xf - -C /target/dir

远端的 tar 解包时,文件名里写的什么路径就解到什么路径。本地侧 kubectl 从容器往外拷贝时,同样按 tar 条目中的路径写本地文件。

信任前提:tar 条目里的路径是"受控的"。但 tar 条目由对端的 tar 输出产生——从容器拷文件出来时,容器内的攻击者完全可以伪造一个包含恶意路径的 tar 流。

2.2 路径穿越如何变成 RCE ​

在 Linux 上,../ 穿越最坏的结局通常是覆盖本地文件——严重,但有权限体系兜底。Windows 上多了一层 NTFS 特性,让穿越直接升级为 RCE:

  • NTFS 交换数据流(ADS):形如 file.txt:Zone.Identifier 的附加流
  • 用户可写的启动相关位置:配合穿越写入用户目录下的特定路径
  • \. \ 与绝对设备路径的解析差异:Go 的 path/filepath 在 Windows 上对反斜杠、盘符、UNC 路径(\\server\share)的规范化行为与 POSIX 不同,历史版本校验逻辑主要按 POSIX 语义写,无法拦截 Windows 特有的逃逸形式

一个示意化的攻击 tar 条目(容器内攻击者构造):

 evil.tar 条目:
   name:  "..\\..\\Users\\victim\\AppData\\Roaming\\Microsoft\\
          Windows\\Start Menu\\Programs\\Startup\\update.cmd"
   data:  powershell -enc <base64 payload>

当 Windows 上的 kubectl cp 从这个容器往外拷贝目录时,恶意条目穿越出目标目录,落入启动文件夹——下次登录即执行。这就是从"路径穿越"到"RCE"的完整链条:

攻击者控制容器(或恶意镜像 / 被入侵的业务 Pod)
        │
        ▼
诱导/等待 Windows 用户执行 kubectl cp <pod>:./evil/ ./local/
        │
        ▼
容器端 tar 输出携带恶意路径条目(穿越逃逸 / 启动目录投放)
        │
        ▼
Windows kubectl 解包时未充分规范化 → 写入任意路径
        │
        ▼
开机自启 → RCE → 窃取 kubeconfig / 云凭证 / 源码

2.3 修复思路 ​

官方修复的核心是在 Windows 上强化路径校验:对 tar 条目名做平台感知的规范化与 containment 检查——用 filepath.Clean + filepath.Rel 确认解析后的路径仍在目标目录内,并拦截盘符、UNC、ADS 冒号等 Windows 特有语义。凡是解析后逃出目标根的条目一律拒绝并告警。

自检脚本(判断你本机的 cp 是否可被利用的保守检查):

powershell
# 检查 Windows kubectl 版本是否在修复范围内
$kv = (kubectl version --client -o json | ConvertFrom-Json)
$v = $kv.clientVersion.gitVersion -replace '^v',''
$parts = $v.Split('.') | ForEach-Object { [int]$_ }
$ok = ($parts[0] -gt 1 -and $parts[1] -ge 36 -and $parts[2] -ge 5) `
   -or ($parts[1] -eq 35 -and $parts[2] -ge 9) `
   -or ($parts[1] -eq 34 -and $parts[2] -ge 12)
if ($ok) { "OK: $v 已修复" } else { "VULNERABLE: $v 需要升级" }

三、为什么客户端漏洞总是补丁盲区 ​

这个漏洞值得写的真正原因不是技术多复杂,而是它再次验证了一个规律:基础设施安全预算几乎全部投在服务端,客户端工具成为永远的盲区。

3.1 三个结构性原因 ​

  1. 没有统一的补丁分发机制。控制面组件有 K8s 发布体系、有云厂商自动升级;而 kubectl 是一个散落在几万台机器上的独立二进制,没有任何机制保证它更新。
  2. "客户端没有价值"的错误威胁模型。运维潜意识里认为攻击目标是集群,不是自己的笔记本。但 kubeconfig、云 CLI 凭证、CI Runner 的服务账号 token——客户端机器上躺着的恰恰是最值钱的横向移动素材。
  3. 信任边界被错误延长。kubectl cp 的设计隐含假设"容器里的 tar 输出是可信的"。客户端工具与对端之间的每一次数据交换,都应该按不可信输入对待——这条原则在 HTTP 时代早就是常识,在 devops 工具链里却经常缺席。

3.2 本站相关案例对照 ​

这不是孤例。本站此前分析过的 CVE-2026-106059(GitAhead macOS 命令注入:恶意仓库文件名被未转义插入 AppleScript,8.5 分)与本次 kubectl cp 是同一类问题——开发者工具把对端数据当作可信输入直接使用。再把时间轴拉长:2026 年 10 月 AI 编码助手泄露 1.3 万张内部截图、恶意 npm 包伪装 AI 开发工具投放 RAT,开发者终端已经成为供应链攻击的主战场。

四、分层修复方案 ​

4.1 紧急项(今天完成) ​

  1. 升级 Windows kubectl 到 1.34.12 / 1.35.9 / 1.36.5+
  2. 盘点跳板机与 Windows CI Runner——它们往往被普通开发者工作站的补丁管理遗忘:
powershell
# 在一台管理机上批量探测内网 Windows 机器的 kubectl 版本
$hosts = Get-Content .\win-hosts.txt
Invoke-Command -ComputerName $hosts -ScriptBlock {
    $k = Get-Command kubectl -ErrorAction SilentlyContinue
    if ($k) { "$env:COMPUTERNAME :: " + (kubectl version --client=true) }
}
  1. CI Runner 加固:Windows Runner 上禁止在不可信项目流水线中执行 kubectl cp;确需拷贝的,固定使用升级后的 runner 镜像并在流水线日志中保留版本记录。

4.2 架构项(本周内) ​

  1. 把"从容器拷出的内容视为不可信输入"写进团队规范。不只是 cp:kubectl logs、kubectl exec 输出、CSI 卷里的文件,都按外部输入处理。
  2. 跳板机最小化:跳板机上不放云凭证明文(用 session token + 短有效期),关闭用户启动目录的写权限执行告警:
powershell
# 审计启动目录近期新增的可执行文件
Get-ChildItem "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup" |
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-30) } |
    Select-Object Name, LastWriteTime
  1. 用更窄的替代方案。能走 kubectl exec + 明确文件参数的场景,不要整目录 cp;大文件分发交给制品库(OCI artifact / S3 + 签名校验),绕开 tar 协议的信任问题。

4.3 长期项 ​

  1. 把客户端工具版本纳入补丁 SLA。与 KEV 漏洞的"必须修补"清单同等对待:kubectl、helm、aws/gcloud/az CLI、docker CLI、git。每月巡检一次版本矩阵。
  2. 对 Go 客户端工具开发者的提醒:任何处理 tar/zip 条目名的代码,Windows 路径语义必须单独测试(盘符、反斜杠、UNC、ADS)。Go 的 filepath 是平台感知的,但你的校验逻辑不写就是 POSIX 的。

五、结语 ​

kubectl cp 的这颗雷埋了多年才在 Windows 上炸出来,修复本身不难——难的是让几万台跳板机、CI Runner 和开发终端在漏洞披露后的窗口期内完成升级。服务端漏洞有完整的响应体系,客户端漏洞的响应体系就是你自己的运维纪律。本周先把 Windows kubectl 版本盘一遍,这比读十篇漏洞分析都有用。

参考资料 ​

上次更新于: