Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
POC-2020-8558 — 关于 Kubernetes CVE-2020-8558 的信息,包括概念验证漏洞利用。 | Kitploit
工具/GitHubGitHub/tabbysable/poc-2020-8558
容器安全漏洞分析漏洞利用信息收集网络安全渗透测试云安全红队
GitHubtabbysable/poc-2020-8558

POC-2020-8558

关于 Kubernetes CVE-2020-8558 的信息,包括概念验证漏洞利用。

查看仓库
4376年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

概述

CVE-2020-8558 是一个 Kubernetes 漏洞,它之所以被公布,是因为 kube-proxy 意外地 让绑定到 localhost 的主机服务对网络上的其他节点可用。我特意强调"意外地",是因为这个漏洞源于设计缺陷(疏忽),而非实现缺陷(bug)。代码确实做了它声称要做的事,但我们所有人都未能认识到这一决定的安全影响。

为了让主机进程能够通过 127.0.0.1(localhost)地址访问 NodePort 服务,kube-proxy 会设置 net.ipv4.conf.all.route_localnet=1 这个 sysctl 设置。根据内核文档,该设置会使内核"不将回环地址视为火星地址(martian)"——其后果是,这些地址可能被网络上的其他节点访问。如果你有敏感且未经认证的服务,其唯一保护就是绑定在 localhost 上,那这就是个大问题!

截至撰写本文时,Kubernetes 社区仍在研究解决 CVE-2020-8558 的最佳方案。两个显而易见的选择是:一开始就不再设置 route_localnet sysctl,或者使用 iptables 阻止被不当路由的 localnet 数据包。采用后一种策略的修复已随 kubelet >= 1.18.4、1.17.7 或 1.16.11 发布。你也可以参考下方链接的 Kubernetes issue 自行应用该修复。

历史与背景

为什么设置 net.ipv4.conf.all.route_localnet=1 值得一个 CVE 编号?主要是因为它违背了我们对 IP 网络的直觉。

至少从 1989 年的 RFC 1122 开始,来自 localhost 网络 127.0.0.1/8 的数据包就一直被特殊对待,被禁止"出现在主机之外"。(如果你知道更早提及 127/8 特殊属性的文献,请在 Twitter 上联系我。)任何符合 RFC 的主机本质上都有一条隐式的、不可移除的防火墙规则,阻止外部访问绑定到 127.0.0.1(以及该网络中的其他 IP——如果你从未试过,不妨 ping 一下 127.127.127.127!)上的服务。我们早已依赖并期待这种行为。我们经常在没有认证或加密的情况下运行敏感服务,并将它们绑定到 localhost 以求安全。例如,明文 HTTP 后端、redis 键值存储,以及遗留的 Kubernetes api-server 不安全端口,通常都是靠这种方式来防范入侵的。我们对此行为如此习以为常,以至于它已成为我们对"IP 主机意味着什么"的直觉中根深蒂固的一部分。从这个角度来看,众多专家长期忽略这一缺陷也就情有可原了。

它是如何工作的?

我们把任何拥有 IP 地址的实体都称为"节点"。IP 数据包通过包头中的源 IP 和目标 IP 地址来标识,从一个节点发送到另一个节点。每个 IP 节点要么是路由器(RFC 1122 中称为网关),要么是主机。主要区别在于:当主机收到目标地址为他人地址的数据包时,会将其忽略;而路由器会查询其路由表并重新传输(转发)数据包,试图让它们更接近最终目的地。主机会感知到一些本地直连的节点;要访问其他节点,它必须将数据包发送给本地直连的路由器。这些本地连接可能是点对点的(如 PPP 链路或某些虚拟网络),也可能是共享介质的(如以太网)。

你的邮箱可以被概念化为你家与当地邮局之间的点对点链路。要在点对点链路上路由数据包,主机只需填上正确的目标地址并发出数据包即可。(这发生在 OSI 模型的第 3 层。)要在共享介质链路上路由数据包,主机必须先在共享介质上构建一条虚拟的点对点电路。在以太网/IP 网络中,这是通过 OSI 模型第 2 层的 ARP 完成的。本质上,如果你能发送一个 ARP 数据包,你就能告诉另一台主机"嘿,我在这里",而它会相信你。(当这种行为被不正当使用时,就被称为 ARP 缓存投毒。)然后,你就可以在数据包上添加相应的以太网源地址和目标地址来进行通信。

普通节点永远不会发送目标地址为 127.0.0.1 的数据包,因为 RFC 1122 的规定。如果普通节点收到目标地址为 127.0.0.1 的数据包,它也会忽略(丢弃)它,同样是因为 RFC 1122。设置 net.ipv4.conf.all.route_localnet=1 改变了这一点——它允许 127.0.0.1 数据包被发送和接收,仿佛它们并不特殊。

因此,如果攻击者与设置了 net.ipv4.conf.all.route_localnet=1 的目标节点有本地连接,攻击者就可以向它发送目标地址为 127.0.0.1 的数据包,而目标节点会像对待一个完全正常的地址那样做出响应。如今,与目标节点建立本地连接的两种最常见方式是:与目标处于同一以太网网络(广播域)中,或是作为运行在目标上的容器。

请注意,在正常配置下,Linux 不会允许攻击者节点发送目标为 127.0.0.1 的正常数据包。这个问题可以通过重新配置攻击者的 Linux 节点(如果拥有 root 权限)来绕过,也可以通过原始套接字伪造数据包来解决。原始套接字只需要 Linux 内核能力 CAP_NET_RAW,而该能力默认授予非特权容器。这意味着,攻击者控制的非特权容器就能利用 CVE-2020-8558。

评估

简而言之,如果你在使用 kube-proxy,或者正在利用 net.ipv4.conf.*.route_localnet 做一些巧妙的配置,那么你就暴露在风险之中。你应该花一些时间进行威胁建模,以确定这种暴露对你来说有多大风险,并规划适当的缓解策略。

从根本上说,每个设置了 net.ipv4.conf.all.route_localnet=1 的 Linux 主机都有漏洞。这个漏洞对攻击者是否有价值,取决于几个因素:

  1. 攻击者能否访问该主机?
  2. 数据包是否被过滤?
  3. 是否有任何有价值的服务绑定在 localhost 上?

要评估 CVE-2020-8558,你必须设想具有各种能力的攻击者,并从这些攻击者的角度回答这些问题。(Adam Shostack 的著作《威胁建模:为安全而设计》非常详细地描述了这一过程。)有两个相关的攻击者你当然应该考虑:一个是在你的以太网中拥有节点的攻击者,另一个是能在你的主机上以非特权 Pod 运行代码的攻击者。根据你的环境和需求,可能还有其他值得考虑的攻击者。

为了说明问题,这里有一个部分完成的示例:

主机对这两种攻击者来说当然都是可访问的;我们在每种情况下都已经这样假设了。

数据包是否被过滤则视情况而定,你需要自行检查。在许多云环境和严格管理的本地网络中,如果数据包的 IP 目标地址与网络所期望的以太网目标地址不匹配,数据包就会被阻止。这本身就可能让"拥有节点的攻击者"出局。如果你所有的节点都有适当的本地防火墙规则(例如由更新过的 kubelet 提供的规则),那么这两种攻击者都会失败。

有价值的服务可能比你想象的更多。显然,Kubernetes api-server 不安全端口是一个极具诱惑力的目标,如果可能的话你应该禁用它。调查所有绑定到 127.0.0.0/8 网络中 IP 地址的进程:它们有可靠的认证吗?如果没有,它们就可能通过 CVE-2020-8558 暴露。即使你所有常规的 localhost 服务都是安全的,临时服务也可能成为问题。例如,SSH 端口转发经常被用来为临时的、经授权的目的绕过网络限制。默认情况下,SSH 转发的端口绑定到 localhost,以便临时访问只对授权用户开放。而在 CVE-2020-8558 面前,这些"安全"的端口转发对你的攻击者同样可用。

工具

Linux

假设你在与目标处于同一广播域的一台 Linux 机器上拥有 root 权限,以下配置设置将使你能够利用 CVE-2020-8558:

root@kitploit:~
ip addr add 127.0.0.2/8 dev lo
ip addr del 127.0.0.1/8 dev lo
ip route add 127.0.0.1/32 via YOUR-TARGET-HERE
sysctl net.ipv4.conf.all.route_localnet=1

因为一些重要服务(咳咳,systemd-resolved)运行在 127.0.0.0/8 地址上,所以我们新增一个地址以免破坏主机。然后,主机必须忘掉它默认的 127.0.0.1/8 地址。接下来,我们指示内核将发往 127.0.0.1 的流量通过线路路由到你的目标,而目标知道如何访问 127.0.0.1。最后,我们设置那个臭名昭著的 sysctl,否则这个配置将无法生效。

tst-2020-8558.py

一个通过发送原始数据包来测试 CVE-2020-8558 的简单 Python 脚本。这本来可以写成 scapy 单行命令,但我想让它更舒适便利一些。它通过你的目标向 127.0.0.1 发送一个数据包,然后查看是否有回复。

poc-2020-8558.py

一个利用 CVE-2020-8558 的 Python 脚本,它通过伪造数据包让普通的 TCP 或 UDP 客户端应用程序能够与远程的 localhost IP 通信。运行此脚本,然后使用任何普通的 TCP 或 UDP 客户端(如 kubectl 或 nc)连接到你的伪造目标(默认 198.51.100.1)。

请注意,伪造目标需要是一个从不响应数据包的 IP 地址,并且你到它的路由必须与访问目标时使用同一个接口。在通常情况下,伪造目标和目标都可以通过你的默认网关接口访问,因此这不会是什么大问题。

由于该脚本使用原始套接字发送和接收"localhost"数据包,它在普通的非特权容器中也能正常工作。

参考资料

Kubernetes 关于此 CVE 的 GitHub issue

内核 IP sysctl 文档

RFC 1122

维基百科:OSI 模型

Adam Shostack:威胁建模

鸣谢 Ian Coldwater、Brad Geesaman、Duffie Cooley 和 Laurent Bernaille。感谢你们的想法、建议和欢笑,各位。Honk the planet!

下载工具