混淆代理人问题 - AWS Identity and Access Management

混淆代理人问题

混淆代理问题是一个安全问题,即没有执行操作权限的实体可能会迫使更具权限的实体执行该操作。为了防止这种情况,如果您为账户中的资源提供第三方(称为跨账户)或其他 AWS 服务(称为跨服务)的访问权限,则 AWS 会提供用于保护您账户的工具。

有时,您需要向第三方提供对您的 AWS 资源的访问权 (提供访问权)。例如,假设您决定聘请一家名为 Example Corp 的第三方公司来监控您的 AWS 账户并帮助优化成本。为跟踪您的日常开支,Example Corp 需要访问您的 AWS 资源。Example Corp 也可监控其他客户的很多其他 AWS 账户。您可使用 IAM 角色在您的 AWS 账户和 Example Corp 账户之间建立信任关系。此方案的一个重要方面是外部 ID,外部 ID 是一条可选信息,您可在 IAM 角色信任策略中使用该信息来指定谁能代入该角色。外部 ID 的主要功能是解决并防止混淆代理人问题。

在 AWS 中,跨服务模拟可能会导致混淆代理问题。一个服务(呼叫服务) 调用另一项服务(所谓的服务)时,可能会发生跨服务模拟。可以操纵调用服务以使用其权限对另一个客户的资源进行操作,否则该服务不应有访问权限。

跨账户混淆代理人预防

下图阐明了跨账户混淆代理人问题。


                混淆代理人问题的描述。

此场景假定:

  • AWS1 是您的 AWS 账户 ID。

  • AWS1:ExampleRole 是您账户中的一个角色。该角色的信任策略通过将 Example Corp 的 AWS 账户指定为可担任该角色的账户来信任 Example Corp。

将发生以下情况:

  1. 在您开始使用 Example Corp 的服务时,您将向 Example Corp 提供 AWS1:ExampleRole 的 ARN。

  2. Example Corp 使用该角色 ARN 获取临时安全凭证以访问您的 AWS 账户中的资源。这样一来,您将信任 Example Corp 作为可代表您执行操作的“代理人”。

  3. 另一个 AWS 客户也开始使用 Example Corp 的服务,而且此客户还为 Example Corp 提供了 AWS1:ExampleRole 的 ARN 以供其使用。另一个客户可能已了解或猜到已不是机密信息的 AWS1:ExampleRole

  4. 当另一个客户要求 Example Corp 访问(它声称的)其账户中的 AWS 资源时,Example Corp 使用 AWS1:ExampleRole 访问您的账户中的资源。

这就是其他客户可对您的资源进行未授权访问的方式。由于此客户能够诱使 Example Corp 无意中操作您的资源,因此 Example Corp 现在是一个“混淆代理人”。

Example Corp 可以通过在角色信任策略中加入 ExternalId 条件检查来解决混淆的代理问题。Example Corp 为每个客户生成唯一的 ExternalId 值,并在其请求中使用该值来承担该角色。在 Example Corp 的客户中,ExternalId 值必须是独一无二的,并由 Example Corp 而不是其客户控制。这就是您从 Example Corp 获取该 ID 且不能自行提供该 ID 的原因。这可以防止 Example Corp 成为一个混淆代理人,以及授予对另一个账户的 AWS 资源的访问权。

在我们的方案中,假设 Example Corp 为您提供的唯一标识符是 12345,而为另一个客户提供的标识符是 67890。这些标识符已针对此方案进行简化。通常,这些标识符为 GUID。假定这些标识符在 Example Corp 的客户之间是唯一的,它们将是用于外部 ID 的有意义的值。

Example Corp 将向您提供外部 ID 值 12345。然后,您必须将一个 Condition 元素添加到角色的信任策略,该策略要求 sts:ExternalId 值为 12345,如下所示:

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "AWS": "Example Corp's AWS Account ID" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "12345" } } } }

此策略中的 Condition 元素允许 Example Corp 仅在 AssumeRole API 调用包括外部 ID 值 12345 时代入该角色。Example Corp 确保,只要它代表客户担任角色,就会始终在 AssumeRole 调用中包括客户的外部 ID。即使另一个客户向 Example Corp 提供您的 ARN,也无法控制 Example Corp 包括在其发送给 AWS 的请求中的外部 ID。这有助于防止未经授权的客户获取对您的资源的访问权限。

下图阐明了此过程。


                如何缓解混淆代理人问题。
  1. 和之前一样,在您开始使用 Example Corp 的服务时,您将向 Example Corp 提供 AWS1:ExampleRole 的 ARN。

  2. 在 Example Corp 使用该角色 ARN 来代入角色 AWS1:ExampleRole 时,Example Corp 将在 AssumeRole API 调用中包含您的外部 ID(12345)。该外部 ID 与角色的信任策略匹配,因此 AssumeRole API 调用将成功,并且 Example Corp 将获取用于访问您的 AWS 账户中的资源的临时安全凭证。

  3. 另一个 AWS 客户也开始使用 Example Corp 的服务,而且如之前一样,此客户还为 Example Corp 提供了 AWS1:ExampleRole 的 ARN 以供其使用。

  4. 但这一次,在 Example Corp 尝试代入角色 AWS1:ExampleRole 时,它提供了与另一个客户关联的外部 ID(67890)。另一个客户无法更改此外部 ID。Example Corp 这样做是因为另一个客户请求使用该角色,因此 67890 表示 Example Corp 正在其中操作的环境。由于您已将具有您自己的外部 ID(12345)的条件添加到 AWS1:ExampleRole 的信任策略,因此 AssumeRole API 调用将失败。而且将阻止另一个客户对您账户中的资源进行未经授权的访问(由图中的红色“X”表示)。

外部 ID 有助于防止任何其他客户欺骗 Example Corp 不知不觉地访问您的资源。

防止跨服务混淆代理

我们建议在基于资源的策略中使用 aws:SourceArnaws:SourceAccount 全局条件上下文密钥,以限制对特定资源的权限。如果您只希望将一个资源与跨服务访问相关联,请使用 aws:SourceArn。如果您想允许该账户中的任何资源与跨服务使用操作相关联,请使用 aws:SourceAccount

防止代理问题的最有效方法是在基于资源的策略中使用 aws:SourceArn 全局条件上下文密钥和资源的完整 ARN。如果您不知道资源的完整 ARN,或者您正在指定多个资源,请针对 ARN 未知部分使用带有通配符 (*) 的 aws:SourceArn 全局条件上下文密钥。例如:arn:aws:servicename:*:123456789012:*

如果 aws:SourceArn 值不包含账户 ID,例如 Amazon S3 存储桶 ARN,您必须使用两个全局条件上下文密钥来限制权限。

针对 AWS Security Token Service 的防止跨服务混淆代理

许多 AWS 服务要求您使用角色来允许该服务代表您访问其他服务的资源。由一项服务担任、代表您执行操作的角色称为服务角色。角色需要两个策略:一个角色信任策略,用于指定允许代入角色的主体,另一个权限策略用于指定可以对角色执行的操作。角色信任策略是 IAM 中唯一基于资源的策略类型。其他 AWS 服务采用基于资源的策略,例如 Amazon S3 存储桶策略。

当服务代表您担任角色时,必须允许服务主体在角色信任策略中执行 sts:AssumeRole 操作。当服务调用 sts:AssumeRole 时,AWS STS 返回一组临时安全凭证,服务主体使用该凭证访问角色的权限策略所允许的资源。当服务在您的账户中担任角色时,您的角色信任策略中可以包含 aws:SourceAccountaws:SourceArn 全局条件上下文密钥,以将对角色的访问限制为仅由预期资源生成的请求。

例如,在 AWS Systems Manager Incident Manager 中,您必须选择一个角色,以允许事件管理器代表您运行 Systems Manager 自动化文档。自动化文档可以包括由 CloudWatch 警报或 EventBridge 事件发起的事件的自动响应计划。在以下角色信任策略示例中,您可以使用 aws:SourceArn 条件密钥,用于根据事件记录 ARN 限制对服务角色的访问。只有从响应计划资源 myresponseplan 创建的事件记录才能使用此角色。

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "Service": "ssm-incidents.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "ArnLike": { "aws:SourceArn": "arn:aws:ssm-incidents:*:111122223333:incident-record/myresponseplan/*" } } } }