洞察策略风险,用自然语言提问策略问题。 申请演示 →

Published:

打破 AWS 中的攻击者杀伤链:IAM 角色

by FireMon

在过去的一年里,我看到人们对以云原生技术处理云内安全事件的具体建议兴趣大增。随着各组织将生产工作负载迁移到云端,安全专业人员很快就会意识到,那些基本原理虽然在概念上相似,但在实践中却大不相同。其中一个核心概念就是杀伤链,这一术语最早由 Lockheed Martin 提出,用于描述攻击者的行动过程。打断其中任何一环即可挫败攻击,因此它非常契合将纵深防御与事件响应的主动环节相结合的做法。

在云部署中,攻击主要分为四大类,每一类都有不同的杀伤链:

  1. 针对云平台本身的攻击。 撇开云服务商本身被彻底攻陷的情形(这不在云客户的掌控范围内)不谈,这类攻击通常集中在云服务的错误配置上。如果您将某个 S3 存储桶设为公开、未在 API Gateway 上设置授权方,或在 GitHub 上泄露了您的 AWS 凭证,都属于这一类。
  2. 针对客户在云中部署的资源和应用程序的攻击。 这类传统攻击与针对您数据中心发起的攻击并无二致。常见的例子包括 Web 应用程序中的 SQL 注入,以及向互联网开放了错误端口的存在漏洞的服务器。假如您使用账户/订阅/项目以及 VPC 或虚拟网络来限制爆炸半径,这类攻击的影响范围往往会比在数据中心中更受限。
  3. 针对您的云管理员和开发人员的攻击。 下次进行渗透测试时,请务必让攻击方尝试对您的开发人员和管理员发起钓鱼。这是横向进入云环境的最佳途径之一,因为对攻击者而言,获取开发人员系统的访问权限往往比攻破云应用程序本身容易得多。我们将在日后专门讨论这一点,现在先记住一句话:“MFA 是我的好帮手。”
  4. 混合式攻击。 这正是我们今天要重点讨论的一类。在这类攻击中,威胁行为者先攻入部署在云中的某个对象,再借此横向进入云管理平面。(有人认为针对开发人员的攻击也属于混合式,但我倾向于将其单独归类。)

作为一条经验法则,我始终假定任何层面上的任何一次成功攻击都可能升级或演变为混合式攻击,届时您的管理平面安全和事件响应就是最有力的防线。

今天我将聚焦于最常见的混合式攻击流程之一,并概述一套检测性与预防性控制措施的组合,以帮助打断这条杀伤链。在进入细节之前,请勿将本文视为对一个复杂问题的过度简化。即便您深谙其道,要在规模化环境中管理我接下来所讨论的内容也极为困难。

在接下来的几周内,我们将向抢先体验客户推出首批专门针对这些问题设计的 Ops,之后不久便会正式投入生产环境。

AWS 混合式攻击:窃取 IAM 角色凭证

在混合式攻击中,威胁行为者先攻破较为传统的目标,再借此横向进入云管理平面。这主要通过三种方式发生。在每一种方式中,攻击者都会窃取静态存储的凭证或临时性的 IAM 角色凭证,我们稍后会作出解释。

  1. 直接攻陷实例或容器。例如,如果您开放了 22 端口,攻击者就可能入侵或以其他方式获得 shell 访问权限。
  2. 服务端请求伪造(SSRF)。攻击者利用(通常是)Web 服务器/服务的漏洞,无需获得 shell 访问权限即可执行命令。
  3. 攻陷 Lambda 函数。虽然无法在 Lambda 上获得 shell,但它仍可能受到代码执行漏洞的影响,若存在应用程序缺陷,甚至可能被任意代码执行。其具体影响可能与 SSRF 类似。

在每一种情形中,攻击者的目标都是获取 AWS 管理平面的凭证,然后利用现有权限或提升权限。我们将在后续文章中讨论权限提升,目前先聚焦于这些凭证究竟是什么,以及您如何防止它们被滥用。

大多数人都了解静态凭证;在 AWS 中即访问密钥(Access Key)和私有密钥(Secret Key)。它们类似于用户名和密码,但用于 AWS API 调用。当前版本在您发起这些 API 调用时,采用一种称为 Signature 4 的加密流程进行 HTTP 请求签名。您可以且应当像对待用户名和密码那样对待它们——并且绝不应将其存储在实例、Lambda 等云资源之中。

刚开始接触 AWS 时,IAM 角色会比较棘手,它们既出色又令人生畏。AWS 中的 IAM 角色实际上是您在某个会话中所使用权限的容器。IAM 角色的优点在于它们本身并不是凭证……当您担任该角色时,AWS 会为一个有时限的会话提供一组凭证。角色是“仅限 AWS 内部”的机制。您可以将其分配给 AWS 内的资源(如实例或 Lambda 函数),该资源随即就能在没有静态存储凭证的情况下发起 API 调用! 我们在联合身份连接、实例、Lambda 函数以及 AWS 内的所有其他服务中都使用角色。访问密钥实际上只在您于 AWS 账户中创建用户时才会用到,其余一切我们都使用角色。

角色关联着四种权限类型:

  1. 该角色在 AWS 内可以执行的操作。这就是您附加到角色上的权限策略
  2. 谁或什么可以使用该角色(即信任策略)。创建角色并不意味着任何事物或任何人都能使用它,该策略会限制访问范围,例如仅限 AWS 实例或某个特定的 Lambda 函数。
  3. 用于限制角色作用范围的权限边界。这一点略为复杂,与我们今天的讨论无关,因此留待日后再谈。
  4. 当您为某个会话担任角色时,还可以指定现有权限的一个子集供该会话使用。这是一项有助于实现最小权限的实用功能,但同样与我们今天的讨论关系不大。

通过实例演示这一机制的运作方式或许更容易理解。假设我有一个需要访问 S3 存储桶或 Dynamo 数据库的应用程序。我为该实例创建一个 IAM 角色,并设置信任策略,使 EC2 服务可以使用该角色。然后我启动一个实例并分配该角色。AWS 运行该实例,并让该实例担任该角色。担任角色会开启一个会话,并分配访问密钥、私有密钥和会话令牌。随后 AWS 每 1-6 小时轮换一次这些凭证,该实例现在便可发起权限策略所授权的那些 API 调用。

虽然凭证并不存放在实例中,但实例仍然能够访问这些凭证。实例内运行的任何代码都需要知道这些凭证,才能发起实际的 API 调用去访问 S3 和 Dynamo,因此由一种称为元数据服务的机制按需提供它们。元数据服务是 AWS 中面向实例和容器的一项特殊机制,保存着有关其配置方式的全部信息。例如,能够获取自身的 IP 地址对服务器来说相当重要。

攻击正是从这里切入的。

元数据服务不过是一个您可以访问并返回所请求信息的 url。curl 169.254.169.254/latest/meta-data/ 会提供所有基本信息,而使用路径 curl 169.254.169.254/latest/meta-data/iam-security-credentials/ 则会提供访问密钥、私有密钥和令牌。(在基于 Lambda 的攻击中,情形看起来完全不同,需要使用 SDK 代码而非 curl,但原理相同。)

随后攻击者可以复制这些凭证,在其他地方将其嵌入工具中使用,而无需在被攻陷的服务器上加载并运行代码。此外,由于基于 URL,元数据服务面临的 SSRF 攻击范围也更广,因为攻击者并不需要完整的任意代码执行能力。这些凭证终会过期,但视攻击方式而定,攻击者可能在发现当前凭证失效时再回来获取一组新的。

如今精明的攻击者会在自己控制的 AWS 账户中使用这些凭证,因为 Amazon 已有一些工具可以检测出在其已知地址范围之外被窃取和使用的凭证。

打破 IAM 角色凭证窃取杀伤链

我们来梳理一下这条杀伤链。攻击者需要完成以下步骤:

  • 发现并利用实例、容器或 Lambda 中的漏洞,从而访问角色凭证。这几乎总是客户侧的失误……例如未及时打补丁、开放了错误的端口,或部署了存在漏洞的代码。
  • 提取当前的角色凭证。
  • 在其控制的环境中成功执行被允许的 API 调用。
  • 在该 IAM 角色权限策略允许的范围内做一些恶意的事。应该说多半是恶意的,毕竟大多数攻击者不会替您修补代码。

以下技术可以打破链条中的不同环节,其中既有检测性控制,也有预防性控制。如果这看起来让人望而生畏,不必气馁……在我合作过的组织中,能够全面落实这些措施的极少,尤其是在大规模环境中。

有助于打破攻击链不同环节的 6 项技术

  1. 漏洞管理
  2. 带资源限制的最小权限 IAM 权限策略
  3. 在权限策略中使用 IP、VPC 或其他请求来源条件限制
  4. 结合使用带策略的服务终端节点与资源策略
  5. 部署带 HTTP User Agent 过滤的元数据代理(元数据服务保护)
  6. 重复角色使用防护

漏洞管理

  • 复杂度:中等
  • 有效性:
  • 可扩展性:困难
  • 类型: 检测性与预防性

不出所料,您的第一步应当是清除攻击者可用来横向移动并窃取凭证的所有初始漏洞和错误配置。我将复杂度评为中等,是因为这方面并没有什么新鲜或云特有的内容。但我把有效性评为低,因为全面的漏洞管理并未阻止过去数十年间层出不穷的数据泄露事件。概念简单,规模化后却极其复杂。

带资源限制的最小权限 IAM 权限策略

  • 复杂度:中等
  • 有效性:
  • 可扩展性:中等至困难
  • 类型: 预防性

AWS 中的 IAM 策略默认拒绝,并包含显式的允许与拒绝声明。例如,您可以编写一条仅允许读取某个 S3 存储桶的策略。策略中还包含资源限制:允许声明授权该角色调用读取 API,而资源限制只允许该角色读取特定的存储桶或对象。您的防御工作始终、始终都应从这里开始。我在做评估时发现,几乎每一个项目中的 IAM 策略都授予了过多权限(API 调用),而资源限制过少。没错,那个服务可能需要访问 Dynamo 数据库,但它需要访问其中的每一张表吗?这项控制在小规模下实施难度不大,但组织规模越大、参与这些策略决策的人越多,就越难在规模化环境中保持一致。同样重要的是添加显式拒绝声明,以防有人为该角色附加带有新权限的新策略。权限是累加的,但任何拒绝声明都会覆盖允许声明。

在权限策略中使用 IP、VPC 或其他请求来源条件限制

  • 复杂度:
  • 有效性:中等至高
  • 可扩展性:困难
  • 类型: 预防性

IAM 策略支持条件声明,可使用包括 IP 地址或来源 VPC 在内的多种选项。如果您确知某个角色只会从应用堆栈中的特定资源发起 API 调用,就可以将授权锁定到该确切的 IP 地址或子网。若攻击者窃取了凭证并试图在别处使用,API 调用将会失败。这是一把精确制导的大锤——概念简单,执行不易,因为您可能会发现其他复杂因素会干扰正确实施。例如,发往 AWS 服务的 API 调用要么直接走互联网,要么经过 NAT 网关,要么通过服务终端节点在内部路由(稍后我们会讨论)。检测到的 IP 地址取决于该 API 调用通往互联网的路径。这些都是可管理、可检测(也可自动化)的,但您需要先做些功课,确保理解各种排列组合。

可查看 Netflix 这篇文章的第一部分,其中有一些示例。

除非您在 VPC 上运行 Lambda 函数,否则此方法无法用于保护已被攻陷的函数。

结合使用带策略的服务终端节点与资源策略

  • 复杂度:中等
  • 有效性:中等至高
  • 可扩展性:中等
  • 类型: 预防性

在 AWS 中,服务终端节点就像网络上的一个分流点,把原本要经互联网发往 AWS 服务的流量重新路由到内部。它最初的设计目的,是让 AWS 中完全私有、无法访问互联网的子网仍能访问某些 AWS 服务。终端节点支持策略,您可以用它以与 IAM 策略非常相似的方式限制访问和操作。在这种情况下,您可以在终端节点策略中添加限制,允许访问该终端节点后面的特定资源(S3 是最常见的例子)。您指定哪些存储桶被允许,该子网中的其他任何资源都无法访问该服务。可以把它看作 IAM 策略的后备保障——有了采用严格策略的服务终端节点,即使有人不慎(或有意)赋予该角色超出应有范围的访问权限,它仍无法访问服务终端节点策略未允许的任何内容。这意味着我们现在有三层策略,全部都必须允许才能访问该资源:

  • 允许该角色访问该资源的 IAM 权限策略。
  • 服务终端节点策略:无论所用角色拥有何种权限,当请求经由该终端节点发出时,该策略决定允许访问哪些资源。
  • 存储桶或资源策略(取决于资源类型),可将访问限制为仅来自已批准的 IP 地址。

同样,除非您在 VPC 上运行 Lambda 函数,否则此方法无法用于保护已被攻陷的函数。

部署带 HTTP User Agent 过滤的元数据代理(元数据服务保护)

  • 复杂度:
  • 有效性:中等
  • 可扩展性:困难
  • 类型: 预防性

以上所有控制都假定攻击者能够窃取角色凭证,但如果我们有办法在授权实例或容器被攻陷的情况下,仍削弱其获取这些凭证的能力呢?(该技术不适用于 Lambda 函数。)一种新兴的做法是从源头限制对元数据服务的访问。虽然曾有人尝试用 IPTables 实现这一点,但这也可能破坏实例上运行的代码所需的功能。2018 年 11 月,AWS 与 Netflix 合作,开始将来自 AWS SDK 的 API 调用的用户数据添加到 HTTP 标头中。这是一种针对 SSRF 的防御手段,因为大多数 SSRF 攻击依赖于诱使应用代表攻击者发出 HTTP 请求,而这些请求通常来自 curl 之类的命令行工具或其他进程,缺少来自 AWS SDK 的用户数据标头。要实现这一点,您需要为这些请求插入一个代理。目前已有一些面向实例和容器的开源方案,包括直接在实例上运行的代理,无需将流量路由到虚拟设备或 squid 代理。

如果攻击者攻陷宿主实例并运行 shell,此技术将失效,因为他们可以禁用该代理或劫持已批准的进程。

您可以在 Netflix 的这篇文章中阅读全部细节。

重复角色使用防护

  • 复杂度:
  • 有效性:
  • 可扩展性:
  • 类型: 检测性

这同样来自 Netflix 团队。他们发布了一份操作指南,介绍一项出色的技术,用于检测 IAM 角色在未经授权的位置被使用,即便是在 AWS 内部。我强烈建议您阅读所链接的文章,简而言之,他们将 CloudTrail 日志与其他一些工具结合起来,维护一张表,记录哪些实例正从哪些 IP 地址使用哪些角色。随后他们监控其他 API 调用,以发现某个角色在已批准的 IP 地址正在使用的同时,又从新的 IP 地址被重复使用。采用这种方法,您无需掌握整个组织内使用的所有 IP 地址,而是动态构建一张使用情况表,并检测该角色何时被同时用在别处。这种方式的可扩展性极强,因为如果您集中管理 CloudTrail(这本身也是常见的最佳实践),就可以集中运行相关逻辑。

小结

这又是一篇篇幅可观的文章,我们并不指望每个人都能在所有部署中落实上述每一项方案。为便于理解,我们来梳理一遍 IAM 角色滥用杀伤链:

  • 发现并利用实例、容器或 Lambda 中的漏洞,从而访问角色凭证。这几乎总是客户侧的失误……例如未及时打补丁、开放了错误的端口,或部署了存在漏洞的代码。
    • 漏洞管理(包括面向应用的 SASST 和 DAST 等工具)以及云配置评估(使用 DisruptOps 等工具,或 Prowler 和 CloudMapper 等开源工具)是您的第一道防线。
  • 提取当前的角色凭证。
    • 元数据服务保护与漏洞管理
  • 在其控制的环境中成功执行被允许的 API 调用。
    • 重复角色使用检测;在权限策略中使用 IP、VPC 或其他请求来源条件限制;结合使用带策略的服务终端节点与资源策略
  • 在该 IAM 角色权限策略允许的范围内做一些恶意的事。应该说多半是恶意的,毕竟大多数攻击者不会替您修补代码。
    • 带资源限制的最小权限 IAM 权限策略

希望这能让您更清楚地了解如何降低此类攻击的成功率。

阻断 AWS IAM 中的攻击者杀伤链 | FireMon