Domain IP Lookup

SSRF 会让服务器沦为不知情的代理

攻击者

构造请求 URL

存在漏洞的服务器

被 SSRF 诱骗而发起请求

169.254.169.254

元数据端点

凭据

返回给攻击者

安全

云元数据端点:隐蔽的攻击面

3 分钟阅读

各大云服务商都会为运行在其平台上的虚拟机提供实例元数据服务,通常通过链路本地地址 169.254.169.254 访问。在实例内部,只需向该地址发起一次简单的 HTTP 请求,就能获得实例的配置、网络详情,而在许多默认配置下,还能拿到分配给该实例的角色或身份所对应的临时安全凭证。

为什么它与 SSRF 结合时尤其危险

元数据端点本应只能由实例自身访问,并不对公网开放。但如果服务端进程被诱导向攻击者指定的地址发起 HTTP 请求(典型的 SSRF),而这个地址恰好就是元数据端点,攻击者就能让服务器取回它自己的云凭证,并通过响应原样交出。攻击者无需从外部直接访问元数据端点,因为存在漏洞的服务器会代为完成请求。

  • 169.254.169.254 属于范围更大的 169.254.0.0/16 链路本地地址段,这个地址段永远不应被当作合法的公网 DNS 解析目标。
  • 部分服务商已改用需要令牌的元数据服务版本,专门用来抬高简单 SSRF 的攻击门槛,但在应用层彻底阻止该地址,依然是更稳妥的防御方式。
  • 这正是任何需要解析用户提供的域名的工具,都应当把链路本地地址与私有地址、环回地址段放在同一份拦截名单中的原因:它并不是某种次要的风险类别。

实践中的要点

任何代表用户解析并请求某个 URL 的系统,都必须把 169.254.169.254 以及它所在的整个链路本地地址段视为严格禁区,并且在发起实际请求的那一刻、每一次都要检查,无论这个地址是如何得到的(直接输入,还是通过一条直接指向它的 DNS 记录)。

这并非某一家云服务商独有

169.254.169.254 具体来说是 AWS、Google Cloud 和 Azure 采用的约定,但其背后的模式,即用一个链路本地地址向实例自身开放实例身份和凭证,几乎在所有主流云平台和容器平台上都以某种形式存在,有时是同一个地址,有时是服务商专用的地址。Kubernetes 集群通常也有各自的内部端点,类似元数据服务,可从 Pod 内部访问。常见云服务商的具体地址值得记住,但真正具有普适性的是这条原则:无论运行在哪个平台上,凡是会解析并抓取用户提供的 URL 的程序,都应把所有元数据类端点视为禁区。

IMDSv2:真正的缓解措施,而不只是过滤

多年来这种利用方式层出不穷,AWS 的应对是推出元数据服务的第二个版本 IMDSv2:读取任何元数据之前,必须先通过一次特殊的 PUT 请求获取会话令牌。关键在于,大多数有漏洞的代码路径所发出的 SSRF 触发式 GET 请求,无法复现这个 PUT 请求。

IMDSv1IMDSv2
请求类型简单的 GET先用 PUT 获取令牌,再带着令牌发起 GET
是否会被基本的 SSRF GET 利用?是否:仅能发起 GET 的 SSRF 无法获取令牌
采用情况许多账户上的旧版默认设置可选启用或强制启用,取决于账户设置

这是一项有实质意义的改进,但出于向后兼容,许多账户上它仍需手动启用,而且它只保护元数据端点本身,对 SSRF 仍可能触达的其他所有私有地址和内部地址毫无作用。无论使用哪个版本的元数据服务,对解析出的地址进行应用层过滤依然是必不可少的。

需要查看某个域名的公网 DNS 地址?使用 Domain IP Lookup 工具。