从安全角度理解 AWS IMDSv1 和 IMDSv2

在运营 AWS EC2 时,您会经常看到 IMDSv1 和 IMDSv2 这两个术语。

IMDS 是 Instance Metadata Service 的缩写,它是一种允许 EC2 实例从内部查询自身元数据的服务。

例如,在 EC2 内部可以查询以下信息:

  • 实例 ID
  • AMI ID
  • 区域
  • 可用区
  • 网络信息
  • IAM 角色名称
  • IAM 角色临时凭证

其中,从安全角度来看最重要的是 IAM 角色临时凭证。

如果 EC2 附加了 IAM 角色,应用程序就不需要将 Access Key 直接存储在代码或环境变量中。

相反,它可以通过 IMDS 获取临时凭证来调用 AWS API。

这种结构本身是一个非常好的安全设计。

但是,如果应用程序存在 SSRF 等漏洞,情况就会有所不同。


1. IMDS 位于何处?

在 EC2 实例内部,可以通过以下链接本地地址访问 IMDS:

http://169.254.169.254/latest/meta-data/

例如,要查询实例 ID,可以执行以下操作:

curl http://169.254.169.254/latest/meta-data/instance-id

如果实例附加了 IAM 角色,可以通过以下路径查看角色名称:

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/

知道角色名称后,就可以查询该角色的临时凭证。

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME

此处返回的信息包括以下值:

  • AccessKeyId
  • SecretAccessKey
  • Token
  • Expiration

也就是说,在 EC2 内部运行的应用程序可以通过 IMDS 获取调用 AWS API 所需的临时凭证。


2. IMDSv1 的工作方式

IMDSv1 的结构非常简单。

无需单独的令牌,只需通过 HTTP GET 请求即可查询元数据。

示例如下:

curl http://169.254.169.254/latest/meta-data/

IAM 角色临时凭证也可以如下查询:

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/

IMDSv1 的优点是简单性和兼容性。

它可以在旧版 AWS SDK、旧版代理和旧版脚本中轻松运行。

但是,从安全角度来看,这种简单性可能会成为问题。


3. IMDSv1 的安全问题

IMDSv1 最大的问题是请求不需要单独的令牌。

IMDS 最初是只能从 EC2 实例内部访问的服务。

因此,外部用户无法直接从互联网访问 169.254.169.254。

但是,如果 Web 应用程序存在 SSRF 漏洞,攻击者可以使应用程序服务器代表其访问 IMDS。

例如,假设某个 Web 服务具有一项功能,当您输入 URL 时,服务器会代为获取该 URL。

https://example.com/fetch?url=http://example.org/image.png

如果此功能在没有 URL 验证的情况下运行,攻击者可以发出如下请求:

https://example.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

在这种情况下,外部攻击者并非直接访问 IMDS,而是 EC2 内部的 Web 应用程序代为访问 IMDS。

这是 SSRF 与 IMDSv1 结合时变得危险的典型场景。


4. SSRF 与 IMDSv1 结合为何危险?

如果攻击者可以通过 SSRF 访问 IMDS,以下信息可能会被泄露:

  • 附加到 EC2 的 IAM 角色名称
  • 临时 Access Key
  • 临时 Secret Key
  • Session Token
  • 凭证过期时间

此时,如果 EC2 角色被授予了过多的权限,损害范围就会扩大。

例如,如果角色包含以下权限,则非常危险:

  • S3 完全访问
  • Secrets Manager 完全查询
  • DynamoDB 完全访问
  • EC2 创建/删除权限
  • IAM PassRole
  • 管理员权限

归根结底,问题不仅仅是“是否使用了 IMDSv1”。

从实际安全事件的角度来看,以下因素共同作用:

  • 应用程序是否存在 SSRF 漏洞?
  • EC2 是否允许 IMDSv1?
  • EC2 角色权限是否过多?
  • 是否未在网络或应用程序级别阻止对元数据地址的访问?

5. IMDSv2 的工作方式

IMDSv2 是为了减少 IMDSv1 的安全弱点而引入的方式。

核心是基于令牌的会话。

在 IMDSv2 中,不能直接查询元数据。

首先,必须通过 PUT 请求获取令牌。

TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" 
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

然后,必须在元数据请求中将令牌作为标头包含。

curl -H "X-aws-ec2-metadata-token: $TOKEN" 
  http://169.254.169.254/latest/meta-data/instance-id

IAM 角色凭证查询也是如此。

ROLE_NAME=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" 
  http://169.254.169.254/latest/meta-data/iam/security-credentials/)

curl -H "X-aws-ec2-metadata-token: $TOKEN" 
  http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME

也就是说,IMDSv2 需要以下两个步骤:

  1. 通过 PUT 请求获取令牌
  2. 将获取到的令牌放入标头并查询元数据

6. IMDSv2 增强安全性的方式

IMDSv2 通过以下方式提高攻击难度:

1) 阻止简单的 GET 请求

在 IMDSv1 中,只需通过 GET 请求即可获取元数据。

curl http://169.254.169.254/latest/meta-data/

但在 IMDSv2 Required 状态下,没有令牌的请求会失败。

这意味着,如果 SSRF 漏洞仅允许操纵 URL,则很难绕过 IMDSv2。

2) 需要 PUT 请求

IMDSv2 令牌是通过 PUT 请求获取的。

许多 SSRF 漏洞只允许简单的 GET 请求,或者不允许更改 HTTP 方法。

在这种情况下,攻击者很难获取令牌。

3) 需要自定义标头

在 IMDSv2 中,查询元数据时需要以下标头:

X-aws-ec2-metadata-token: <TOKEN>

对于仅允许操纵 URL 的 SSRF 漏洞,很难添加此标头。

4) 跳数限制控制

IMDSv2 具有 HttpPutResponseHopLimit 设置。

此值限制了 IMDSv2 令牌响应可以经过的网络跳数。

在典型的独立 EC2 环境中,可以使用 1。

但在容器环境中,网络路径可能会增加一个跳数,因此可能需要 2。


7. IMDSv1 与 IMDSv2 比较

类别 IMDSv1 IMDSv2
元数据查询方式 GET 请求 PUT 获取令牌后进行 GET 请求
是否需要令牌
SSRF 防御能力 相对较高
是否需要自定义标头
HTTP 方法 主要是 GET PUT + GET
操作建议 用于旧版兼容 建议用于生产环境
设置值 可在 HttpTokens=optional 下使用 可通过 HttpTokens=required 强制执行
主要优点 简单性、兼容性 增强安全性
主要缺点 可能容易受到 SSRF 攻击 需要检查与旧版 SDK/Agent 的兼容性

8. EC2 元数据选项主要设置

设置 说明 建议
HttpEndpoint 是否使用 IMDS 不需要则 disabled
HttpTokens 是否要求 IMDSv2 令牌 建议 required
HttpPutResponseHopLimit IMDSv2 令牌响应跳数限制 普通 EC2 为 1,容器环境考虑 2
InstanceMetadataTags 是否将实例标签作为元数据公开 不需要则 disabled

在生产环境中,通常建议遵循以下方向:

  • 不需要 IMDS 的实例:HttpEndpoint disabled
  • 需要 IMDS 的实例:HttpTokens required
  • 普通 EC2:考虑 Hop Limit 1
  • ECS/EKS/容器环境:考虑 Hop Limit 2
  • 如果不需要查询实例标签:InstanceMetadataTags disabled

9. 检查当前 EC2 的 IMDS 设置

您可以使用 AWS CLI 检查当前实例的元数据选项。

aws ec2 describe-instances 
  --query 'Reservations[].Instances[].{
    InstanceId:InstanceId,
    State:State.Name,
    HttpEndpoint:MetadataOptions.HttpEndpoint,
    HttpTokens:MetadataOptions.HttpTokens,
    HopLimit:MetadataOptions.HttpPutResponseHopLimit,
    MetadataTags:MetadataOptions.InstanceMetadataTags
  }' 
  --output table

查看结果中的 HttpTokens 值。

  • optional: 允许 IMDSv1 和 IMDSv2
  • required: 仅允许 IMDSv2

因此,如果 HttpTokens=optional,则从安全角度来看是需要考虑转换的对象。


10. 将现有 EC2 更改为 IMDSv2 Required

要将现有 EC2 实例更改为 IMDSv2 Required,可以使用以下命令:

aws ec2 modify-instance-metadata-options 
  --instance-id i-xxxxxxxxxxxxxxxxx 
  --http-tokens required 
  --http-endpoint enabled

更改后,使用以下命令进行确认:

aws ec2 describe-instances 
  --instance-ids i-xxxxxxxxxxxxxxxxx 
  --query 'Reservations[].Instances[].MetadataOptions' 
  --output json

如果在容器环境中需要将跳数限制设置为 2,可以按如下方式应用:

aws ec2 modify-instance-metadata-options 
  --instance-id i-xxxxxxxxxxxxxxxxx 
  --http-tokens required 
  --http-put-response-hop-limit 2 
  --http-endpoint enabled

11. 为新 EC2 实例默认应用 IMDSv2

在生产环境中,最好从一开始就配置新实例要求 IMDSv2,而不是在创建后进行修改。

您可以在启动模板中指定以下设置:

{
  "MetadataOptions": {
    "HttpTokens": "required",
    "HttpEndpoint": "enabled",
    "HttpPutResponseHopLimit": 2
  }
}

您还可以使用 AWS CLI 设置账户/区域范围的默认值。

但是,如果现有应用程序、代理或 SDK 不支持 IMDSv2,可能会发生故障。

因此,在生产环境中,不应立即强制执行,而应首先检查 IMDSv1 的使用情况。


12. 检查 IMDSv1 使用情况

在转换为 IMDSv2 之前,需要确认是否存在仍在使用的 IMDSv1 进程。

典型的检查方法如下:

检查 CloudWatch MetadataNoToken 指标

MetadataNoToken 指标用于识别未经令牌访问 IMDS 的请求。

简而言之,它是一个可以确认是否发生了 IMDSv1 方式请求的指标。

如果此指标持续增长,则表示仍有应用程序或代理在使用 IMDSv1。

使用 IMDS Packet Analyzer

使用 AWS 提供的 IMDS Packet Analyzer 可以检查实例内部哪些进程正在调用 IMDSv1。

在转换之前,建议检查以下项目:

  • 旧版 AWS CLI
  • 旧版 AWS SDK
  • 旧版 SSM Agent
  • 旧版 CloudWatch Agent
  • 手动编写的 curl 脚本
  • 旧版应用程序库

13. 从安全角度推荐的转换流程

在生产环境中,按照以下顺序进行转换是安全的:

  1. 在整个 EC2 列表中识别 HttpTokens=optional 的实例
  2. 检查 CloudWatch MetadataNoToken 指标
  3. 使用 IMDS Packet Analyzer 确认调用 IMDSv1 的进程
  4. 更新 AWS CLI、SDK、SSM Agent、CloudWatch Agent
  5. 在开发环境中测试 IMDSv2 Required
  6. 应用于预发布环境
  7. 按顺序应用于生产实例
  8. 在启动模板、Auto Scaling 组、AMI 构建管道中反映 IMDSv2 Required
  9. 将新实例的默认值设置为 IMDSv2 Required
  10. 如果需要组织范围的强制执行,请审查 SCP 或账户默认值

14. 仅靠 IMDSv2 是否足够?

IMDSv2 是一个非常重要的防御机制。

但是,仅应用 IMDSv2 并不能消除所有风险。

从安全角度来看,应同时采取以下对策:

IAM 角色最小权限

通过 IMDS 可能被窃取的最重要信息是 IAM 角色临时凭证。

因此,EC2 角色应仅授予最小权限。

一个不好的示例如下:

{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}

一个好的示例是仅限制必要的服务和资源。

{
  "Effect": "Allow",
  "Action": [
    "s3:GetObject"
  ],
  "Resource": [
    "arn:aws:s3:::example-bucket/app/*"
  ]
}

SSRF 防御

Web 应用程序中接受外部 URL 并由服务器直接请求的功能应谨慎处理。

以下地址通常是阻止目标:

  • 169.254.169.254
  • fd00:ec2::254
  • 127.0.0.1
  • localhost
  • RFC1918 私有 IP 范围
  • 链接本地地址
  • 内部 DNS 名称
  • 云元数据端点

此外,如果发生重定向,最终目的地也必须再次验证。

还应考虑 DNS Rebinding 攻击。

容器环境权限分离

在 ECS 或 EKS 环境中,应检查容器是否可以使用 EC2 节点的实例配置文件权限。

如果可能,建议使用以下结构:

  • ECS: 使用任务角色 (Task Role)
  • EKS: 使用 IRSA 或 EKS Pod Identity
  • 最小化节点角色权限
  • 审查 Pod 或容器访问 IMDS 的必要性

如果容器可以访问节点的 IMDS 且节点角色权限过多,则容器被攻陷时可能会导致 AWS 账户权限的升级。


15. 从 CIS 基准角度看 IMDSv2

CIS AWS Foundations Benchmark 和云安全检查标准将 EC2 元数据服务设置视为重要的安全项。

特别是,可以从以下角度进行检查:

  • 是否允许 IMDSv1?
  • 是否应用了 IMDSv2 Required?
  • EC2 角色是否被授予了过多的权限?
  • 是否需要公开实例元数据标签?
  • 容器工作负载中是否存在节点角色权限泄露的可能性?

自动化诊断脚本通常会检查 describe-instances 结果中的 MetadataOptions 值。

例如,可以根据以下标准进行诊断:

HttpTokens == required 이면 양호
HttpTokens == optional 이면 취약 또는 개선 필요

但是,在生产环境中,应用程序兼容性检查优先于简单地通过命令更改设置。


16. 实践结论

IMDSv1 是一种旧方法,仅通过简单的 GET 请求即可查询元数据。

因此,当与 SSRF 漏洞结合时,EC2 IAM 角色临时凭证可能会被泄露。

IMDSv2 使用基于令牌的会话。

首先,必须通过 PUT 请求获取令牌,然后后续请求中必须包含令牌标头。

由于这种结构,通过简单的 SSRF 攻击窃取元数据变得更加困难。

在生产环境中,建议遵循以下标准:

  • 尽可能应用 IMDSv2 Required
  • 对于不需要 IMDS 的实例,禁用 IMDS
  • 以最小权限设计 EC2 IAM 角色
  • 应用 SSRF 防御逻辑
  • 在容器环境中,使用任务角色 (Task Role)、IRSA 或 EKS Pod Identity
  • 在转换前,检查 MetadataNoToken 指标和代理兼容性

一句话总结如下:

IMDSv1 是一种以兼容性为中心的旧版方式,而

IMDSv2 是一种旨在降低 SSRF 和元数据窃取风险的安全增强方式。

在生产环境中,如果没有特殊原因,将 IMDSv2 Required 设置为默认值是更安全的。


参考链接

AWS EC2 User Guide – Instance Metadata Service

AWS EC2 User Guide – Configure instance metadata options

AWS Security Blog – Add defense in depth against SSRF vulnerabilities

AWS Security Blog – Get the full benefits of IMDSv2 and disable IMDSv1


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注