本文为译文,原文链接为:https://summitroute.com/blog/2021/08/03/S3_backups_and_other_strategies_for_ensuring_data_durability_through_ransomware_attacks/
勒索软件已经成为信息安全的主要关注点。这篇文章将讨论如何通过适当的保护和备份策略来确保存储在S3上的数据的持久性。不幸的是,AWS上的AWS备份服务不备份S3桶,很多关于AWS上备份和数据持久性的讨论都没有足够详细地描述实现,这导致了许多潜在的危险。这篇文章将向您展示两种最佳选项(s3对象锁和复制策略),解释如何使用它们,以及需要注意什么。
AWS中的勒索攻击
关键数据在哪里,勒索软件攻击者就会攻击哪里。虽然我目前还不知道有勒索软件团体专门针对AWS环境或S3,但我听说过关于AWS的为了赎金的攻击,最臭名昭著的AWS账户入侵事件之一是在2014年发生的Code Spaces breach入侵事件,因为决定不支付赎金,而被删除AWS账户中的所有内容,以及随后在入侵发生后的12小时内直接关闭业务,因为所有数据(和备份)都已被销毁。
3月26日,AWS为我的一个IAM用户添加了一条内联策略(针对flaw. cloud)即对s3:*添加一个拒绝,他们认为该策略被破解了,在4月21日,AWS发布了一个新的IAM管理策略名为AWSCompromisedKeyQuarantineV2,其中包括一个对s3: DeleteObject的拒绝和类似的动作,攻击者会使用它来删除数据。AWS的这两项举措都暗示着他们察觉到了某种攻击。

今年早些时候不幸去世的斯宾塞·吉岑(Spencer Gietzen)于2019年在他的文章《S3勒索软件第1部分:攻击矢量和第2部分:预防和防御》和演讲《云上勒索》中发表了研究。我将讨论从那时起的一些改进的缓解措施。
我认为的威胁和限制
我认为的威胁是让攻击者获得对包含S3桶中关键数据的帐户的管理访问权。一方面,这可能只是一个合法管理员偶然运行了一个错误的脚本导致删除了错误的S3 bucket,另一方面,这可能是一个老练的攻击者,他们知道如何绕过AWS环境,并了解人们在尝试确保数据持久性这方面可能会犯的潜在错误。
即使你有很多控制措施,勒索软件集团也赚了足够多的钱(据说REvil每年超过1亿美元),他们有可能购买有效的0-Days来针对你的AWS管理员或IT员工(他们可能针对你的AWS管理员账号密码进行密码重置或授予自己访问AWS账户的特权)。所以我们想确保我们的控制能够做到最好。
S3在给定年份内具有99.999999999%的对象数据持久性,并在3个az中冗余存储数据副本,这意味着即使一个区域中的两个完整的az同时被破坏,数据仍将保持。所以我们并不担心AWS的硬盘故障会导致数据丢失。关于这个话题,请注意AWS已经声明他们在S3中存储了超过100万亿对象,所以根据计算方法,这意味着他们每年会丢失1000个S3对象。从规模上看,稀有事件发生的次数不少。不幸的是,我从来没有听说过,就好比如他什么时候发生?(AWS通知过你吗?当您尝试读取它时返回错误?返回一个损坏的对象?不再显示它的列表?)
对于我们的解决方案,我们希望尽可能地保持S3存储桶的现有可用性,这意味着我们仍然希望能够修改和删除存储桶中的对象,但我们可能希望恢复到更早的时间。由于这个原因,删除MFA不是一个可接受的解决方案,因为要删除一个对象,您必须使用带有MFA设备的AWS根帐户,并为每次删除对象提供MFA代码。
我们需要15分钟的RPO(Recovery Point Objective)(意味着我们愿意在事故中丢失最近15分钟的数据)和一天的RTO(Recovery Time Objective)(意味着我们接受可能需要24小时才能从事故中恢复的结果)。请明白如果您想要改善这些数字,您可能需要重新架构以获得更好的解决方案。
我们想要最小化成本。这主要意味着我们希望避免拥有太多的数据副本,并可能希望为任何备份使用更便宜的存储类。每天晚上将我们所有的数据复制到Snowballs并将其发送到不同的物理位置是不可取的,因为这个最低限度的成本是每月9K美元来支付300美元/Snowball的成本,但你还需要额外支付0.03美元/GB的数据传输费用(这比正常的S3费用要高)和运费。这也不能满足我们的RPO和RTO目标。
我们假设当事件发生时,恢复的需求是显而易见的。如果攻击者只破坏了一个文件,然后等了一年才要求赎金来告诉您更改了哪个文件,那么可能很难检测到,并且超出了本文的范围。
那么跨区域备份
关于数据持久性,您经常听到的一个概念是将数据备份到另一个区域,但这有一些问题:
将数据复制到另一个区域会产生数据传输成本。S3将您的数据复制到另一个地区的成本(0.02美元/GB)几乎与在S3中存储一个月的GB(0.023美元)相同,只是存在一些地区差异。因此,如果您在另一个地区将数据备份到S3标准,那么该数据的成本几乎增加了两倍。试图使用更便宜的存储类来省钱的做法并不像我们后面讨论的那样行得通。
可能的情况就是同时导致3个az的永久损失,这情况可能意味着一场影响足够大的灾难反而时候影响业务可能是最小的需要考虑的问题。
如果您担心这个风险可能会影响整个AWS区域,那么将您的数据备份到另一个区域的另一个云提供商可能会更好地解决您的问题。在您的备份策略中使用多云将比使用AWS中的多区域最终更有效地解决风险。
但是,为了合规性您可能需要备份到另一个区域,我提出的想法对于该场景仍然有用。
适当保护数据
最小特权
您应该始终确保对AWS帐户的最低权限访问控制并避免攻击者能够访问您的关键数据的情况。将关键数据放在专门的AWS帐户中有助于实现这一点,特别是在特权用户经常访问您的生产帐户的情况下。
通过VPC的端点,可以进一步加强对S3桶的访问限制,只允许特定VPC的访问。这样,即使管理员用户犯了严重的错误或被泄露,也不会对S3的关键桶造成影响,除非在指定的VPC内。
在处理S3 bucket时,您需要非常清楚资源策略如何能够授予原则访问权,即使该原则没有授予它们访问权的相关IAM策略。下面的图表证实了它自己的博客文章,但关键的是有两种绿色终端状态,这意味着你可以通过两种方式授予某人访问资源的权限。

为了解释这个概念,我看到的一个常见问题是,S3桶在其资源策略中会有类似以下语句:
{
"Sid": "DO_NOT_DO_THIS",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::bucket",
"arn:aws:s3:::bucket/*"
],
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-abcd1234"
}
}
}
设置此策略的人希望确保组织中的其他人能够访问此存储桶,但没有意识到他们实际上是在授予访问权,特别是授予与存储桶相同帐户内的人。当我做评估时,我将被授予 SecurityAudit特权,我应该是不被允许读写敏感数据的,但由于这个资源策略,实际上我和帐户中拥有最少特权角色的其他供应商将被授予对该S3桶的完全访问权!
随机命名
作为最小权限的一部分,您应该避免提供列出帐户中的S3 bucket (s3:ListAllMyBuckets)或这些bucket中的对象(S3: ListBucket)的能力。但是让我们假设您只提供s3: PutObject,用于每天生成一组关键日志(命名为2021-01-01.log、2021-01-02.log等)的对象。如果有人破坏了该服务并知道该命名模式,他们可能会覆盖这些日志文件。在AWS上没有一种方式来授予写对象的权限,但不覆盖现有对象(至少不是以大多数人希望的方式,但下面讨论的对象版本控制有助于这一点)。最好使用一些随机的名称来命名文件,例如2021- 01-01-01 -fdc1127f-7a1d-4721-a081-a66a536649ae.log。您仍然能够识别该日志是何时创建的,但攻击者将无法猜中命名格式从而成功的覆盖它。
持久性的基础
S3对象版本管理
被讨论的许多数据持久性策略都要求为bucket启用S3对象版本控制(包括S3对象锁和复制策略)。使用对象版本控制,任何时候修改对象都会产生一个新版本,而删除对象时,只会给对象一个删除标记。这允许在对象被覆盖或标记为删除时恢复对象。但是,拥有足够特权的人仍然可以永久删除所有对象及其版本,因此仅凭这一点是不够的。
当使用对象版本控制时,通过调用s3: DeleteObjectVersion来永久删除旧版本,这与通常的s3: DeleteObject相反,这意味着您可以应用最少权限限制来拒绝某人删除旧版本。这可以缓解一些问题,但您仍然应该做更多来确保数据持久性。
生命周期策略
旧版本的对象将永远存在,每个版本都是一个完整的对象,而不是前一个版本的差异。因此,如果您有一个100MB的文件,并且经常更改,那么您将拥有整个文件的许多副本。AWS在文档中承认“您可能有一个或多个有数百万个版本的对象”。为了减少旧版本的数量,您可以使用生命周期策略。
审计提示:如果您启用了对象版本控制,并且桶上没有生命周期策略,那么这应该被认为是一个错误配置。每个版本化的S3桶都应该有一个“NoncurrentVersionExpiration”生命周期策略,以最终删除不再是最新版本的对象。对于数据持久性,您可能将其设置为30天。如果正在备份此数据,您可能将主数据上的时间设置为1天,备份上的时间设置为30天。
如果您每天都要多次更新相同的对象,您可能需要不同的解决方案来避免不必要的成本。
审计提示:在2019年,我审计了AWS IAM管理的策略,发现了一些问题,包括我所谓的资源策略特权升级。在少数情况下,AWS曾试图创建有限策略,不允许使用' s3: Delete* ',但仍然允许使用某种形式的' s3: Put* '。这里的风险是调用' s3: PutBucketPolicy '的能力,以授予一个外部帐户完全访问一个s3桶的删除对象和它的版本,或' s3:PutLifecycleConfiguration '过期1天的所有对象将删除桶中的所有对象和他们的版本。
存储类
通过生命周期策略,您可以将对象转换为成本更低的存储类。请注意,这里存在许多约束,特别是关于对象的大小以及在转换或删除它之前必须保留它的时间。S3标准存储类中的对象在那里必须保存至少30天,直到它们可以被转换。此外,一旦一个对象在S3智能分级、S3 Standard-IA和S3 One Zone-IA中,这些对象在删除之前必须在那里保存30天。Glacier内的对象必须保存90天才能删除,Glacier Deep Archive(深存档)内的对象必须保存180天。因此,如果你计划立即将所有非当前对象版本转移到Glacier Deep Archive以节省资金,然后在30天后删除它们,你将无法做到这一点。
S3对象锁
S3对象锁是一个强大的特性,它允许您确保S3对象在指定日期之前不能被删除,无论发生什么情况。这对我们的数据持久性很有好处,但这也可能是潜在的危险,因为攻击者可能从公共S3存储中同步大量大型文件,然后将这些文件锁定长达100年,而且根据设计,即使是AWS也无法撤消这一点。阻止为你并不关心的被锁定文件付费的唯一方法是让AWS删除该帐户,但这首先意味着将你的所有资源(除了这些被锁定的文件)转移到另一个帐户,这通常是一个很大的提升。为了帮助缓解这一问题,AWS文档中有一条语句,您可以将其应用于bucket策略,或者作为SCP,以限制人们锁定对象的时间过长。
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObjectRetention",
"Resource": "arn:aws:s3:::bucket/*",
"Condition": {
"NumericGreaterThan": {
"s3:object-lock-remaining-retention-days": "30"
}
}
}
Ian McKay列出了一个您应该在SCP级别禁用的特权列表,以限制某些Denial of Wallet(拒绝钱包攻击)和错误,例如有人使用对象锁(s3: PutObjectRetention)或设置默认对象锁策略(s3: PutBucketObjectLockConfiguration)。否认特权s3: PutBucketObjectLockConfiguration将阻止一个人创建一个启用了s3对象锁的s3 bucket,但是如果一个人已经存在,而攻击者有足够的特权,即使是上述scp级别,攻击者也可以改变桶策略来允许攻击者从他们的账户访问,因为SCP并不适用于主体外部账户,攻击者就可以将桶填满对象使得其在接下来的100年里锁定。
管存在上述问题,S3对象锁仍然是AWS上最强大的特质,它可以确保您的数据不会被删除。您还可以对S3桶应用默认的对象锁保留时间,这意味着您与S3桶的交互方式不会改变。对象仍然可以被标记为删除,就像在S3对象版本控制中通常发生的那样,但是在锁定过期日期到来之前不能删除对象。
从数据持久性的角度来看,S3对象锁存在的问题是没有滚动锁的概念。用我的话就是"允许对象被标记为删除,但不允许它们在30天后被永久删除",为了解释这一点,假设您有一个对象锁配置,该配置将对象锁定30天。然后放入一些关键的对象。如果您的帐户在第一天被攻破,攻击者将无法永久删除这些对象。如果攻击者在第31天以足够的特权侵入账户,他们可以清除你在第1天放入的所有关键数据。
一种可能的解决方案是每晚运行一个进程来遍历所有对象,并在最新的对象版本上放置一个对象锁。这可以通过这里记录的S3批处理服务完成。
复制策略
数据持久性的经典方法是创建备份,并确保备份与主数据分开。在AWS中,为了有一个强大的安全边界,这必须在一个单独的AWS帐户中完成。理想情况下,这将与您的其他帐户完全分开(单独的AWS组织,不通过正常的SSO进程访问,只使用特殊的非托管笔记本电脑访问等),但有很好的方法而不是走这种极端,特别是因为它通常意味着复制你的许多安全控制。另一个重要的问题是,您可能会有多组关键数据,这些数据可能是强隔离的,它们都被备份到同一个AWS帐户。这样,备份帐户就会成为充满敏感数据的诱人目标。
审计提示:请确保备份帐户充分隔离。在以下情况下,您应充分意识到并承认风险,或采取措施减轻风险:
- 同一个人可以同时访问主要数据和备份数据。
- IT或帮助团队能够将凭证重置或将软件更新部署到能够访问备份数据的人员,或者将自己添加到具有访问权限的组中。
- 授予从其他帐户对备份帐户的写或删除访问权限的任何跨帐户AWS角色。
- 对备份帐户的监控或安全控制与其他帐户的安全方式不一致。
设置S3备份最简单的方法是通过复制策略,它可以将对象复制到同一地区或不同地区的不同帐户中的S3桶中。要做到这一点,你需要:
- 创建一个IAM角色来复制这些数据。
- 设置备份帐户目标桶的桶资源策略,允许源帐户向目标桶发送数据。
- 设置主帐户源桶的复制策略。
- 确保复制了删除标记。
- 包括将副本所有者更改为策略。
- 为复制的数据设置一个较便宜的存储类。
- 选择:开启“复制时间控制”,保证99.99%的对象在15分钟内完成复制。
- 在源桶和目标桶上设置生命周期策略,清除非最新版本的对象。
- 选择:监控复制失败的通知事件。
审计提示:必须确保目标(备份)桶的桶策略不太打开。如果这授予源帐户过多的访问权限,那么攻击者将能够从源帐户删除备份桶中的日志。桶策略只允许源帐户的IAM角色执行以下操作,仅限于备份桶:' s3: ReplicateDelete ', ' s3: ReplicateObject ', ' s3: List* ', ' s3: GetBucketVersioning '。文档列出了' s3: PutBucketVersioning ',但这似乎没有必要。
审计提示:如果备份对象是加密的,您应该考虑攻击者是否可以删除用于解密备份的密钥,否则您的备份可能在意外情况下变得无用。
还原
如果攻击者泄露并破坏了您的主要数据,那么您的备份桶上将有删除标记,您需要删除这些标记。然后需要将数据从备份桶复制回主桶。在这样做时,要注意不要使攻击者能够对您的备份具有写访问权。我不知道AWS最快的方法是什么,但我认为AWS DataSync可能是最好的解决方案。在这个恢复过程中,您应该使用TAM或AWS支持。我听说过的许多勒索软件案例的有个问题是,从备份中恢复需要的时间比仅仅支付赎金和恢复要长,但我不认为存储在S3中的数据会是这种情况。
进一步的考虑
通过对象锁定和复制策略,当这些策略应用于一个现有的S3桶时,S3桶中已经存在的对象不会受到影响。因此,如果您有一个包含关键数据的现有S3,则必须采取行动复制或锁定现有文件。AWS支持可以帮助复制文件和在现有S3桶上启用对象锁定。
检测
你应该设置监控来检测和警告以下情况:
- 检测s3: PutBucketLifecycleConfiguration,因为它可以用来删除对象。如果它小于某个数量,比如30天,或者当它不在非当前对象版本上时,将其标记为高严重程度。
- 在任何重要的S3存储桶检测对s3: PutBucketPolicy的调用。
- 数据事件:
- 检测调用:s3: DeleteObjectVersion。
- 检测对s3: DeleteObject被拒绝的访问调用:
- 检测任何启用对象锁定并自动修复的S3桶的创建。
Cloudtrail数据事件可能会非常昂贵(记录和监视都是如此),但是您可以使用高级事件选择器来查找特定的对象级别api并过滤特定的S3桶。
结论
确保S3数据不会被攻击者删除并非易事,但希望本指南已经解释了更好的选项(S3对象锁定和复制策略),并指出了一些需要注意的常见问题。