
Kubernetes Goat 场景 3SSRF 漏洞在 Kubernetes 环境中的利用链——从云实例元数据到集群内部微服务【免费下载链接】kubernetes-goatKubernetes Goat is a Vulnerable by Design cluster environment to learn and practice Kubernetes security using an interactive hands-on playground 项目地址: https://gitcode.com/GitHub_Trending/ku/kubernetes-goat本篇基于 Kubernetes Goat 场景 3「SSRF in the Kubernetes world」编写带你以交互式靶场为载体完整复现一条真实云原生攻击链利用一个存在 Server Side Request ForgerySSRF的应用服务先后探测云实例元数据端点、同 Pod 内其他端口再借助 Kubernetes 原生 Service DNS 发现机制访问集群内部微服务最终从metadata-db服务中读取到目标 flag。读完后你将理解 SSRF 在容器化环境中为何危害被放大以及 Kubernetes 服务发现、链路本地地址link-local元数据这些原生特性如何被攻击者利用。一、场景背景与学习目标SSRF 已经成为云原生环境中最高效的攻击向量之一。在 Kubernetes Goat 的场景设定中场景 3 首页说明我们将看到一个像 SSRF 这样的应用漏洞如何被利用以获取云实例元数据instance metadata以及内部服务internal services的元数据信息尤其可以看到 Kubernetes 原生特性——服务发现service discovery——如何被利用来触达其他内部微服务。场景 3 完整文档guide/docs/scenarios/scenario-3/scenario-3.md给出了明确的四大学习目标如何在云环境中利用应用里的 SSRF 漏洞理解元数据查询机制获取云厂商提供的实例数据理解并滥用 Kubernetes 原生的 Service 发现能力与服务 DNS 查询获取集群内部in-cluster其他微服务的访问权限。通关目标Goal获取元数据 secrets 中的k8s-goat-FLAG值。官方文档还给出了两条提示Hints Spoilers若响应没有明显花样理解云厂商/平台学习查询元数据 API 与内部服务。例如 AWS 的http://169.254.169.254/latest/meta-data/集群内部服务则形如servicename.namespace.svc.cluster.local若能查询到metadata-db服务集群内还有一个运行在http://metadata-db/latest/的微服务把元数据当作服务对外提供其中可能含有有价值的信息。二、入口准备127.0.0.1:1232 是怎么来的场景说明统一要求访问http://127.0.0.1:1232。这个端口由仓库中的入口脚本 access-kubernetes-goat.sh 建立——它对标签为appinternal-proxy的 Pod 执行端口转发把本地1232映射到 Pod 的3000端口kubectl $KUBECTL_INSECURE port-forward $POD_NAME --address 0.0.0.0 1232:3000 /dev/null 21 Windows 版 access-kubernetes-goat.ps1 使用kubectl port-forward ... 1232:3000做同样的事。也就是说浏览器打开的1232页面实际落在 3000 端口的 SSRF 代理应用上。整个集群的部署由 setup-kubernetes-goat.sh 完成其中包含helm install metadata-db scenarios/metadata-db/等步骤把本场景需要的内部服务一次性部署进集群。三、SSRF 服务端源码一个不做 URL 校验的请求转发器理解利用链的前提是理解这个应用为什么存在 SSRF。它由 infrastructure/internal-api/code/server.js 实现核心逻辑非常直白app.post(/, function (req, res) { var endpoint req.body.endpoint, method req.body.method || GET, headers req.body.headers || {}; const child spawnSync(curl, [endpoint, -H, headers, -X, method]); if (child.stdout) { res.send(child.stdout) } else if (child.err) { res.send(child.err) } else { res.send(child.stderr) } })从源码结构看存在三个典型的 SSRF 成因用户可控的目标地址endpoint直接来自 POST 请求体没有任何 URL 白名单或协议过滤服务端代为发起请求应用使用spawnSync(curl, ...)在服务器Pod侧执行请求攻击者实际触达的是应用所在网络位置能访问的地址——这正是 SSRF 的本质借用受害者的网络身份响应原样回传child.stdout被完整写回 HTTP 响应攻击者可以读取元数据、内部接口返回的任意内容响应中带有换行时以 JSON 数组形式返回。代码中还保留了一段被注释掉的fetch(endpoint, ...)实现说明该 SSRF 点用 curl 或 Node 原生 fetch 都能构造漏洞根因在于服务端无条件转发用户指定 URL这一设计而非具体实现方式。四、利用路径 1云实例元数据端点 169.254.169.254官方文档对这条路径有专门说明169.254.169.254是一个动态配置的 IPv4 链路本地link-local地址仅在单一网络段有效且不可路由。大多数云厂商使用这个地址向实例提供计算元数据包括 AWS、GCP、Azure、DigitalOcean 等主流厂商。利用思路是先做枚举与侦察基于已知信息了解当前实例/网络里在运行什么服务用 SSRF 向http://169.254.169.254/latest/meta-data/发 GET 请求读取 IMDSInstance Metadata Service内容需要识别云厂商以使用对应的请求头与路径例如 AWS 的 IMDS 路径、GCP/Azure 的差异因为不同厂商的元数据服务接口并不相同。文档同时给出了一个重要限定如果当前环境并非运行在云厂商 VPC 中例如本地 Kind/Minikube 集群这条路径可能查询不到内容此时应跳过它直接转向查询 Kubernetes 集群内部的微服务与内部服务——这也是本地演练时真正能走通的主线。五、利用路径 2同 Pod 端口枚举发现 5000 端口的内网提示服务官方 WalkthroughMethod 1的第一步并不是直接打元数据 IP而是先探测当前容器自己可以通过查询不同端口与地址来确认当前容器/Pod 内是否还有其他服务在运行。对同一容器内的http://127.0.0.1:5000发起GET请求。对应截图 sc-3-2请求返回了 HTTP 响应。这个 5000 端口的服务来自 infrastructure/info-app/app.py一个 Flask 应用from flask import Flask app Flask(__name__) app.route(/) def hello_world(): Print welcome message as the response body. return {info: Refer to internal http://metadata-db for more information} if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)注意 infrastructure/info-app/Dockerfile 中该服务监听 5000 端口。它的唯一价值就是返回一句指向内部服务http://metadata-db的提示——这正是 SSRF 侦察中典型的顺藤摸瓜先拿到一个模糊的内部服务名再进行下一步服务发现查询。六、利用路径 3借 Kubernetes Service DNS 访问集群内部微服务拿到metadata-db这个服务名后利用点转向 Kubernetes 原生服务发现。在集群内任意 Service 都可以通过 DNS 名称访问格式为servicename.namespace.svc.cluster.local因此通过 SSRF 直接请求http://metadata-db默认命名空间下等价于metadata-db.default.svc.cluster.local请求就会由 Pod 网络路由到该 Service进而落到后端 Pod。metadata-db 的实现极其简单却足够说明问题。其入口 infrastructure/metadata-db/main.go 只有两行核心代码func main() { http.Handle(/, http.FileServer(http.Dir(./metadata))) http.ListenAndServe(:80, nil) }它把静态目录./metadata/当作元数据 API对外提供监听 80 端口见 infrastructure/metadata-db/Dockerfile 中的EXPOSE 80与COPY metadata /metadata。该目录的布局刻意模仿云厂商 IMDS 的目录结构infrastructure/metadata-db/metadata/ ├── 1.0/ # 模拟 IMDS 的 1.0 版本树 │ ├── events/list/{1,2,3} │ ├── secrets/{info, kubernetes-goat} │ ├── hostname │ └── latest └── latest/ # 指向 1.0 的最新版本视图 ├── events/list/{1,2,3} ├── secrets/{info, kubernetes-goat} ├── hostname └── latest该服务通过 Helm Chart 部署进集群Chart 位于 scenarios/metadata-db/deployment.yaml 定义容器与 80 端口的 TCP 存活/就绪探针service.yaml 创建 Service默认配置见 values.yamltype: ClusterIP、port: 80、镜像madhuakula/k8s-goat-metadata-db。ClusterIP 类型的服务只对集群内部可达——从集群外无法直接访问但通过集群内应用的 SSRF 就能借道进入。这就是文档强调的内部微服务看起来没有暴露实际上任何持有 SSRF 能力的 Pod 都能摸到。七、终点读取 secrets 并解码 k8s-goat-FLAG沿着http://metadata-db枚举全部键值后flag 藏在http://metadata-db/latest/secrets/kubernetes-goat端点对应截图 sc-3-4。该端点返回的内容对应仓库中的 infrastructure/metadata-db/metadata/1.0/secrets/kubernetes-goat 文件{metadata: static-metadata, data: azhzLWdvYXQtY2E5MGVmODVkYjdhNWFlZjAxOThkMDJmYjBkZjljYWI}data字段是 base64 编码官方文档给出的解码命令为echo -n azhzLWdvYXQtY2E5MGVmODVkYjdhNWFlZjAxOThkMDJmYjBkZjljYWI | base64 -d解码结果即形如k8s-goat-32位十六进制串的 Kubernetes Goat flagsc-3-5 展示了最终输出场景至此通关。八、复盘这条利用链映射到的防御要点把场景 3 的攻击链抽象出来是外部请求 → SSRF 应用internal-api:3000 → ① 云 IMDS 169.254.169.254若运行于云上 → ② 同 Pod 其他端口info-app:5000拿到内部服务名 → ③ K8s Service DNSmetadata-db → ClusterIP:80 → 读取 latest/secrets/kubernetes-goat 中的 flag对照仓库中的实现可以归纳出与该场景直接对应的防御方向URL 校验SSRF 代理必须对endpoint做协议与主机白名单校验拒绝file://、gopher://等非 HTTP 协议封禁内网地址段解析出目标 IP 后拒绝169.254.0.0/16含 IMDS 的 169.254.169.254、10/8、172.16/12、192.168/16以及svc.cluster.local域名解析出的 ClusterIP 网段并防范 DNS 重绑定与 302 跳转绕过元数据加固云上启用带认证令牌的 IMDSv2如 AWS并要求 Pod 元数据服务开启--address绑定限制最小化同 Pod 服务像 info-app 这类附带服务会泄露内部拓扑敏感组件不应与对外服务共享网络命名空间网络策略兜底即使存在 SSRF用 NetworkPolicy 限制应用 Pod 只能访问必要 Service可阻断metadata-db这类高价值目标的可达性。九、延伸阅读与仓库内相关文件场景 3 完整图文文档含每一步截图guide/docs/scenarios/scenario-3/scenario-3.mdSSRF 代理应用源码与前端infrastructure/internal-api/code/server.js、infrastructure/internal-api/README.md元数据模拟服务源码与数据目录infrastructure/metadata-db/main.go、infrastructure/metadata-db/metadata/部署清单scenarios/metadata-db/Helm Chart、scenarios/internal-proxy/deployment.yaml入口与拆除脚本access-kubernetes-goat.sh、setup-kubernetes-goat.sh、teardown-kubernetes-goat.sh。运行前提本机已安装 Docker 与 kubectl并通过 setup-kubernetes-goat.sh 将集群与全部基础设施拉起后再执行 access-kubernetes-goat.sh 建立 1232 端口的转发即可按上文路径在http://127.0.0.1:1232完成整个场景。【免费下载链接】kubernetes-goatKubernetes Goat is a Vulnerable by Design cluster environment to learn and practice Kubernetes security using an interactive hands-on playground 项目地址: https://gitcode.com/GitHub_Trending/ku/kubernetes-goat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考