Terrance DeJesus

模拟 AWS S3 SSE-C Ransom 进行威胁检测

使用 AWS S3 的 SSE-C 服务理解和检测勒索软件

阅读时间:21 分钟安全研究
Emulating AWS S3 SSE-C Ransom for Threat Detection

前言

欢迎阅读新一期的“使用 Elastic 进行的 AWS 检测工程”。您可以在此处阅读上一期关于 STS AssumeRoot 的文章。

在本文中,我们将探讨威胁行为者如何利用 Amazon S3 的服务器端加密和客户提供的密钥 (SSE-C) 进行勒索/敲诈操作。这种现代滥用策略展示了对手如何巧妙地利用原生云服务来实现其金钱目的。

作为读者,您将获得对 S3、SSE-C 工作流和分桶配置的内部运作的见解。我们还将介绍此技术的步骤,讨论保护 S3 分桶的最佳实践,并提供可行的指导,以制定检测逻辑来识别您环境中的 SSE-C 滥用行为。

这项研究基于 Halcyon 研究团队最近发表的一篇文章,该文章记录了首个公开的 in-the-wild (ItW) 滥用 SSE-C 进行勒索软件行为的案例。接下来我们将深入探讨这一新兴威胁,并展示如何领先于对手,做到魔高一尺道高一丈。欢迎与我们一同探讨。

我们发布了一个 gist,其中包含本博客文章中引用的 Terraform 代码和仿真脚本。此内容仅供教育和研究用途。请负责任地使用此内容,并遵循适用的法律和指导原则。Elastic 对任何意外后果或误用不承担任何责任。

祝阅读愉快!

理解 AWS S3:关键安全概念和功能

在深入探讨仿真及相关策略、技术和程序 (TTP) 之前,我们先简要回顾一下 AWS S3 的内容。

S3 是 AWS 的通用存储服务,让用户能够将任何非结构化或结构化数据存储在“分桶”中。这些分桶类似于您在计算机系统本地找到的文件夹。存储在这些分桶中的数据被称为对象,每个对象都由一个对象键唯一标识,类似于文件名。S3 支持从 JSON 到媒体文件等多种数据格式,因此其非常适合多种组织用例。

分桶可以通过设置存储来自各种 AWS S3 服务的对象,但也可以根据用例手动或以编程方式填充。此外,分桶还可以利用版本控制来维护对象的多个版本,从而防止意外删除或覆盖。然而,版本控制并非总是默认启用,这使得数据容易受到某些类型的攻击,例如勒索软件攻击或批量删除。分桶可以通过设置存储来自各种 AWS S3 服务的对象,但也可以根据用例手动或以编程方式填充。此外,分桶还可以利用版本控制来维护对象的多个版本,从而防止意外删除或覆盖。然而,版本控制并非总是默认启用,这使得数据容易受到某些类型的攻击,例如勒索软件攻击或批量删除。

对这些分桶的访问在很大程度上取决于其访问策略,这些策略通常在创建时定义。访问策略包括禁用公共访问等设置,以防止无意中暴露分桶内容。不过配置并不仅限于此;分桶还拥有其独特的 Amazon 资源名称 (ARN),这使更细粒度的访问策略可以通过身份和访问管理 (IAM) 角色或策略来定义。例如,如果用户 “Alice” 需要访问分桶及其对象,则必须为其 IAM 角色分配特定权限,例如 s3:GetObject。该角色可以作为权限策略直接应用于 Alice,或应用于她所属的关联组。

虽然这些机制看似万无一失,但访问控制的错误配置(例如过于宽松的分桶策略或访问控制列表)是导致安全事件的常见原因。例如,截至撰写本文时,根据 buckets.grayhatwarfare.com 的数据,大约有 32.58 万个分桶可公开使用。Elastic Security Labs 还观察到,在《2024年Elastic全球威胁报告》中,30% 的 AWS 状态检查失败与 S3 相关。

S3 中的服务器端加密
S3 提供多种加密选项来保护静态数据的安全。这些包括:

  • SSE-S3:加密密钥完全由 AWS 管理。
  • SSE-KMS:密钥通过 AWS Key Management Service (KMS) 管理,允许更多自定义密钥策略和访问控制 — 查看这些策略和控制如何在 Elastic 中实施
  • SSE-C:客户提供自己的加密密钥以增强控制。此选项通常用于合规性或特定的安全要求,但会引入额外的操作开销,例如安全地管理和存储密钥。重要的是,AWS 不存储 SSE-C 密钥;而是记录密钥的 HMAC(基于哈希的消息认证码)以用于验证目的。

在 SSE-C 的情况下,加密密钥管理不善或故意滥用(例如勒索软件)可能导致数据永久无法访问。

生命周期策略

S3 分桶还可以利用生命周期策略,自动执行多种操作,例如将对象转移到更便宜的存储类别(例如 Glacier)或在指定时间后删除对象。虽然这些策略通常用于成本优化,但攻击者可能会利用它们来安排删除关键数据,从而增加勒索事件期间的压力。

存储类

Amazon S3 提供多种存储类别,每种类别专为不同的访问模式和频率需求而设计。虽然选择存储类别通常是为了成本优化,但在考虑加密和安全性如何与数据存储交互时,了解它们至关重要。

例如,S3 标准和 Intelligent-Tiering (智能分层)可确保以最小的延迟进行频繁访问,因此其适合实时应用。另一方面,像 Glacier Flexible Retrieval 和 Deep Archive 这样的归档类别会在数据访问前引入延迟,这可能会使安全场景中的事件响应复杂化。

当引入加密时,这一点变得尤为重要。服务器端加密(SSE)适用于所有存储类别,但 SSE-C(客户提供密钥)将密钥管理的责任转移给了用户或攻击者。与 AWS 管理的加密(SSE-S3、SSE-KMS)不同,SSE-C 要求每次检索操作都必须提供原始加密密钥——如果该密钥丢失或未被对手提供,数据将永久无法恢复。

基于这种理解,关于在实际环境中观察到的 SSE-C 滥用的影响,一个关键问题出现了:当攻击者获得公开暴露或配置错误的 S3 分桶的访问权限,并控制存储策略和加密密钥时,会发生什么?

由此开始:滥用 SSE-C 进行勒索操作

在接下来的章节中,我们将分享在 AWS 沙盒环境中模拟这种行为的实践方法,具体步骤如下:

  1. 通过基础设施即代码 (IaC) 提供商 Terraform 部署易受攻击的基础设施
  2. 探索如何在 Python 中编写 SSE-C 请求
  3. 执行自定义脚本以模拟 Halcyon 博客文章中描述的勒索行为

前提条件

本文讨论如何重现一个特定场景以用于检测工程。如果这是您的目标,请首先确定以下内容。

  • Terraform 必须本地安装
  • Python 3.9+ 必须在本地安装,以便用于虚拟环境和运行仿真脚本。
  • AWS CLI 必须设置配置文件的管理权限,以供 Terraform 在基础设施部署期间使用

部署易受攻击的基础设施

对于我们的白盒仿真,复制企业在真实场景中可能拥有的 S3 配置是非常重要的。以下是已部署基础设施的概述:

  • 地区:us-east-1(默认部署区域)
  • S3 存储桶:一个唯一命名的工资数据桶,其中包含敏感数据并允许对手控制的加密
  • Bucket 所有权控制:强制执行“BucketOwnerEnforced”以防止基于 ACL 的权限
  • 公共访问限制:公共通道被完全封锁,以防止意外暴露
  • IAM 用户:受攻击者控制的 IAM 用户,拥有过多的 S3 权限;未分配登录配置文件,因为访问密钥凭证在其他地方以编程方式用于自动执行任务
  • IAM 策略:在存储桶和对象级别,攻击者都有权:
    • s3:GetObject
    • s3:PutObject
    • s3:DeleteObject
    • s3:PutLifecycleConfiguration
    • s3:ListObjects
    • s3:ListBucket
  • 应用于分桶和对象级别
  • IAM 访问密钥:为对手用户生成访问密钥,允许以编程方式访问
  • 测试数据:模拟的敏感数据 (customer_data.csv) 已上传到分桶

了解基础架构对于评估此类攻击的展开方式至关重要。Halcyon 博客描述了攻击方法,但几乎没有提供受影响组织的具体 AWS 配置细节。这些细节对于确定此类攻击的可行性以及成功执行所需的步骤至关重要。

分桶的可访问性和暴露

要发生这种性质的攻击,攻击者必须通过以下两种主要方法之一获得对 S3 分桶的访问权限:

可公开访问的分桶:如果分桶配置错误并具有公共访问策略,只要分桶的权限策略允许 s3:PutObjects3:DeleteObjects3:PutLifecycleConfiguration 等操作,攻击者就可以直接与其交互。这些权限经常使用通配符 (*) 主体错误地进行分配,这意味着任何人都可以执行这些操作。

凭证被盗:如果攻击者获得 AWS 凭证(通过凭证泄露、网络钓鱼或恶意软件),他们可以作为合法 IAM 用户进行身份验证,并与 S3 交互,就好像他们是预期的帐户所有者一样。

在我们的模拟中,我们假设分桶不是公开的,这意味着攻击依赖于被泄露的凭证。这要求对手获得有效的 AWS 访问密钥,并执行云基础架构发现以识别可访问的 S3 分桶。这通常通过使用 AWS API 调用(例如 s3:ListAllMyBucketss3:ListBucketss3:ListObjects)来完成,这些调用会显示特定区域中的分桶及其内容。

执行攻击所需的 IAM 权限: 要使用 SSE-C 加密文件并成功执行删除策略,对手必须拥有适当的 IAM 权限。在我们的模拟中,我们为受感染的 IAM 用户配置了明确的权限,但在真实场景中,多个权限模型可能允许这种攻击:

  • 自定义过于宽松的政策:组织可能会在不知情的情况下授予广泛的 S3 权限而不受严格的约束。
  • AWS 管理策略:攻击者可能已获取与具有AmazonS3FullAccessAdministratorAccess.
  • 部分对象级权限:如果 IAM 用户拥有 AllObjectActions,这将只允许对象级操作,但不会授予生命周期策略修改或分桶列出权限,而这些权限是检索对象并遍历它们以进行加密和覆盖所必需的。

Halcyon 博客未具体说明哪些权限被滥用,但我们的白盒仿真确保了最低必要权限的设置,以便攻击能够按描述的方式进行。

失陷 IAM 用户的角色
另一个关键因素是凭据被盗用的 IAM 用户的类型。在 AWS 中,攻击者不一定需要拥有交互式登录配置文件的用户凭据。许多 IAM 用户是专门为程序化访问而创建的,不需要 AWS 管理控制台密码或多因素身份验证 (MFA),这两者都可能成为额外的安全障碍。

这意味着,如果被盗的 IAM 用户凭证被用于自动化或服务集成,攻击者将更容易执行 API 请求,而无需额外的身份验证挑战。

虽然 Halcyon 博客文章有效地记录了这种攻击中使用的技术,但并未包含关于受害者底层 AWS 配置的详细信息。了解攻击背后的基础架构,例如分桶访问、IAM 权限和用户角色,对于评估这些勒索操作在实践中如何实施至关重要。由于这些细节未提供,我们必须做出明智的假设,以便更好地理解致使攻击成功的条件。

我们的仿真旨在复制此类攻击的最低必要条件,确保对防御策略和威胁检测能力进行真实评估。通过探索基础设施的技术方面,我们能够提供更深入的见解,了解潜在的缓解措施,以及组织如何主动防御类似的威胁。

设置基础架构

对于我们的基础设施部署,我们使用 Terraform 作为我们的 IaC 框架。为了使这篇文章更精简,我们已将 Terraform 配置和原子仿真脚本存储在一个可下载的 gist 中,以方便您访问。以下是下载这些文件后的本地文件结构。

Necessary folder structure when downloading gist
下载 gist 时必要的文件夹结构

在本地设置好所需文件后,您可以为该场景创建一个 Python 虚拟环境,并安装必要的依赖项。环境配置完成后,以下命令将初始化 Terraform 并部署基础架构:

Command: python3 s3\_sse\_c\_ransom.py deploy

Expected console output after terraform initialized and deployed
Terraform 初始化和部署后的预期控制台输出

部署完成后,所需的 AWS 基础设施将到位,以便继续进行攻击的模拟和执行。需要注意的是,公共访问已被阻止,IAM 策略仅适用于动态生成的 IAM 用户,以确保安全。不过,我们强烈建议在测试完成或获取必要数据后拆除基础设施。

如果您碰巧登录到您的 AWS 控制台或使用 CLI,您可以验证 us-east-1 区域中的分桶是否存在并包含 customer_data.csv,,下载后它将是纯文本格式。您还会注意到“ransom.note”也不存在。

Example of infrastructure deployed with unencrypted customer data in our S3 bucket
在我们的 S3 存储桶中部署未加密客户数据的基础设施示例

Another example of infrastructure deployed with no ransom.txt file yet
另一个尚未部署 ransom.txt 文件的基础设施示例

探索如何在 Python 中编写 S3 SSE-C 请求

在执行原子仿真之前,重要的是要探索使对手能够成功执行 (ItW) 此攻击的底层技术手段。

对于熟悉 AWS 的人来说,使用 AWS SDK 或 AWS CLI 时,S3 操作(例如访问分桶、列出对象或加密数据)通常很简单。这些工具化繁为简,使用户无需深入了解底层 API 机制即可执行操作。这也降低了对手滥用这些功能的知识门槛。

不过,Halcyon 的博客文章指出了关于攻击执行的一个关键技术细节:

"攻击者通过调用 x-amz-server-side-encryption-customer-algorithm 标头,利用其生成并本地存储的 AES-256 加密密钥来启动加密过程"。

这里的关键区别在于 x-amz-server-side-encryption-customer-algorithm 标头的使用,这是此攻击中的加密操作所必需的元素。根据 AWS 文档,此 SSE-C 标头通常在创建预签名 URL 和在 S3 中使用 SSE-C 时指定。这意味着攻击者不仅加密了受害者的数据,而且还以 AWS 自身不存储加密密钥的方式进行加密,使数据没有攻击者的配合就无法恢复。

预签名 URL 及其在 SSE-C 滥用中充当的角色

什么是预签名的 URL?
预签名 URL 是经过签名的 API 请求,允许用户在有限的时间内执行特定的 S3 操作。这些 URL 通常用于安全地共享对象而不暴露 AWS 凭证。预签名的 URL 授予对 S3 对象的临时访问权限,可以通过浏览器访问或在 API 请求中以编程方式使用。

在典型的 AWS 环境中,用户利用 SDK 或 CLI 包装器来获取预签名的 URL。然而,在使用 SSE-C 时,AWS 需要额外的标头来进行加密或解密。

SSE-C 和必需的 HTTP 标头
在通过 AWS SDK 或直接 S3 REST API 发出 SSE-C 请求时,必须包含以下标头:

  • x-amz-服务器端​-加密​-客户算法:指定加密算法,但必须是AES256(Halcyon报告中注明)
  • x-amz-服务器端加密-客户密钥:提供 256 位、base64 编码的加密密钥,供 S3 用于加密或解密您的数据
  • x-amz-服务器端加密-客户密钥-MD5:提供加密密钥的 base64 编码的 128 位 MD5 摘要;S3 使用此标头进行消息完整性检查,以确保加密密钥的传输没有错误或被篡改

在寻找检测机会时,这些细节至关重要。

AWS 签名版本 4 (SigV4)及其作用

对 S3 的请求要么经过身份验证,要么是匿名的。由于使用预签名 URL 进行 SSE-C 加密需要身份验证,因此所有请求都必须经过加密签名以证明其合法性。这就是 AWS Signature Version 4 (SigV4) 的作用所在。

AWS SigV4 是一种身份验证机制,确保对 AWS 服务的 API 请求进行签名和验证。这对 SSE-C 操作尤为重要,因为在 S3 中修改对象需要经过身份验证的 API 调用。

对于此攻击,每个加密请求必须签名:

  1. 使用 AWS SigV4 生成加密签名
  2. 在请求头中包含签名
  3. 附加必要的 SSE-C 加密标头
  4. 向 S3 发送请求,以加密版本覆盖对象

如果没有正确的 SigV4 签名,AWS 将拒绝这些请求。像 Halcyon 所描述的攻击依赖于被泄露的凭据,我们知道这一点是因为在我们的测试中请求没有被拒绝。这也表明,攻击者知道他们可以滥用 AWS S3 的错误配置,例如不当的签名要求,并了解分桶及其对象访问控制的复杂性。这加强了这样的假设:攻击依赖于泄露的 AWS 凭证,而不是暴露的、可公开访问的 S3 分桶,并且攻击者足够熟练,不仅了解 S3 分桶和对象的细微差别,还了解 AWS 中的身份验证和加密。

执行我们的原子模拟

我们的原子模拟将使用没有登录配置文件的 IAM 用户的“受陷”凭据,该用户附加的权限策略允许对我们的目标 S3 分桶执行若干操作。需要提醒的是,我们进行模拟的基础设施和环境是从“设置基础设施”部分部署的,并引用了我们共享的 gist。

以下是仿真的分步工作流。

  1. 加载被盗的 AWS 凭证(从环境变量中获取)
  2. 使用被泄露的凭据建立 S3 客户端
  3. 生成 S3 终端 URL(构建分桶的 URL)
  4. 枚举 S3 对象 → s3:ListObjectsV2(检索对象列表)
  5. 生成 AES-256 加密密钥(本地生成)
  6. 开始循环(针对分桶中的每个对象)
    1. 生成 GET 请求并使用 AWS SigV4 签名(认证请求)
    2. 从 S3 检索对象 → s3:GetObject(提取未加密的数据)
    3. 生成 PUT 请求并使用 AWS SigV4 签名(附加 SSE-C 标头)
    4. 加密并覆盖 S3 中的对象 → s3:PutObject(使用 SSE-C 加密)
  7. 结束循环
  8. 应用 7 天删除策略 → s3:PutLifecycleConfiguration(限时数据销毁)
  9. 将勒索信上传到 S3 → s3:PutObject(留给受害者的勒索信息)

以下是此仿真工作流的可视化表示:

Visual representation of emulation workflow
仿真工作流程的可视化表示

在我们的 Python 脚本中,我们特意添加了需要用户交互的提示,以确认他们同意不滥用此脚本。在执行过程中生成的另一个提示可让用户暂停执行,以便在删除 S3 对象之前给 AWS 调查留出时间(如有必要)。由于使用了 SSE-C,因此对象会用 Terraform 无法访问的密钥加密,从而导致失败。

Command: python s3\_sse\_c\_ransom.py detonate

执行后,我们 S3 分桶中的对象将使用 SSE-C 加密,勒索信将会被上传,到期生命周期将会被添加。

Expected console output when detonating SSE-C ransom emulation
引爆 SSE-C 勒索模拟时的预期控制台输出

Expected artifacts in S3 bucket after detonating SSE-C ransom emulation
引爆 SSE-C 勒索模拟后 S3 存储桶中的预期工件

如果您尝试访问 customer_data.csv 对象,AWS 将拒绝该请求,因为它是使用服务器端加密存储的。要检索该对象,您需要一个包含正确 AES-256 加密密钥的签名请求。

Expected error when retrieving objects from S3 bucket after SSE-C encryption
SSE-C 加密后从 S3 存储桶检索对象时出现预期错误

清理

此清理此模拟相对简单。如果您选择保留 S3 对象,请从步骤 1 开始,否则直接跳转到步骤 5。

  1. 前往 us-east-1 区域。
  2. 导航至 S3
  3. 定位该 s3-sse-c-ransomware-payroll-XX bucket
  4. 删除所有对象
  5. Command: python s3\_sse\_c\_ransom.py cleanup

完成后,最初部署的所有内容将会被移除。

检测和搜寻策略

在我们进行原子模拟之后,关键是分享如何根据 AWS CloudTrail 提供的 API 事件日志有效地检测这种勒索行为。请注意,我们将利用 Elastic Stack 进行数据摄取和初始查询开发;不过,查询逻辑和上下文应可转换为您选择的 SIEM。还需要注意的是,在您的 CloudTrail 配置中,S3 的数据事件应设置为“记录所有事件”。

使用 SSE-C 进行不寻常的 AWS S3 对象加密

此检测策略的目标是识别利用 SSE-C 的 PutObject 请求,因为客户提供的加密密钥可能是异常活动的强烈指示——当组织机构主要使用 KMS(SSE-KMS)或 S3 的原生加密(SSE-S3)进行 AWS 管理的加密时尤为如此。

在我们的仿真中,PutObject 个请求被配置为将 x-amz-server-side-encryption-customer-algorithm 标头设置为 AES256,向 AWS 发出信号,表明使用了客户提供的密钥进行加密(SSE-C)。

幸运的是,AWS CloudTrail 会在请求参数中记录这些加密详细信息,使安全团队能够检测到异常的 SSE-C 使用情况。要监测的关键 CloudTrail 属性包括:

  • 签名版本: SigV4 → 表示该请求已签名
  • SSE应用:SSE_C → 表示使用了服务器端客户密钥加密
  • bucketName:s3-sse-c-ransomware-payroll-96 → 指示哪个 bucket 发生了这种情况
  • x-amz-服务器端加密客户算法:AES256 → 表明客户加密密钥使用了哪种算法
  • 键:customer_data.csv → 表示应用该操作的对象的名称

Partial Elastic document from CloudTrail ingestion showing SSE-C request from emulation
来自 CloudTrail 提取的部分 Elastic 文档显示来自模拟的 SSE-C 请求

有了这些详细信息,我们就可以编写一个威胁检测查询,以匹配这些事件,并最终匹配原始 Halcyon 博客文章中报告的威胁。

事件.数据集:“aws.cloudtrail”和事件提供程序:“s3.amazonaws.com”和event.action:“PutObject”和事件结果:“成功”和 aws.cloudtrail.flattened.request_parameters.x-amz-server-side-encryption-customer-algorithm:“AES256”和 aws.cloudtrail.flattened.additional_eventdata.SSEApplied:“SSE_C”

虽然这种检测范围很广,但各组织应根据其环境进行调整,提出相应的问题:

  • 我们是否期望对 S3 分桶或对象操作使用带有 SigV4 的预签名 URL?
  • 我们是否期望在 S3 或此特定分桶中的 PutObject 操作中使用 SSE-C?

使用新术语规则类型减少误报
为了最大限度地减少误报(FP),我们可以利用 Elastic 的新术语规则类型,它有助于检测首次发生的可疑活动。我们不会在每次匹配时都发出警报,而是跟踪 IAM 用户和受影响的 S3 存储桶的唯一组合,并且仅在一定时间内第一次观察到这种行为时才生成警报。我们要关注的一些独特组合是:

  • 在 S3 中执行 SSE-C 加密的唯一 IAM 用户(ARNs)。
  • 应用 SSE-C 的特定分桶。

这些告警仅在过去 14 天内首次发现这种活动时才会触发。

这种自适应方法可确保合法的用例随着时间的推移被学习,从而防止对预期操作重复发出告警。同时,它会标记 S3 中首次出现的 SSE-C 异常情况,以帮助及早检测威胁。根据需要,可以为特定用户身份 ARN、分桶、对象甚至源 IP 添加规则例外,以优化检测逻辑。通过结合历史背景和行为基线,该方法能够提高信号的保真度,从而改善检测的有效性和告警的可操作性。

规则参考资料

使用 SSE-C 进行不寻常的 AWS S3 对象加密
使用 SSE-C 进行过度的 AWS S3 对象加密

结论

我们衷心感谢您花时间阅读本出版物,并且如果您这样做了,感谢您亲自尝试仿真。白盒测试在云安全中发挥着关键作用,使我们能够模拟现实世界的威胁,分析其行为模式,并制定有效的检测策略。随着云端攻击日益普遍,了解对手战术背后的工具并与更广泛的安全社区分享研究成果至关重要。

如果您有兴趣探索我们的 AWS 检测规则集,请访问:Elastic AWS 检测规则。我们也欢迎为增强我们的规则做出贡献 — 您的付出有助于加强集体防御,我们对此不胜感激!

我们鼓励任何感兴趣的人士浏览 Halcyon 的文章,并提前感谢他们分享研究成果!

下次再见

重要参考文献:

Halcyon 研究博客关于 SSE-C ItW 的文章
适用于 AWS 的 SSE-C 的 Elastic 仿真代码
Elastic 预构建的 AWS 威胁检测规则集
Elastic 预构建检测规则库
规则:使用 SSE-C 进行异常 AWS S3 对象加密
规则:使用 SSE-C 进行过多 AWS S3 对象加密