一、针对S3存储的勒索攻击事件背景
近期有一片文章《亚马逊安全机制被用于勒索攻击,全球数千家机构已成为攻击目标》,原文在这里。引用部分文字如下:
据报道,勒索组织已经开始加密全球数千家机构在亚马逊云存储的数据。
与传统的勒索软件攻击不同,此次攻击没有利用任何系统漏洞,
而是利用了亚马逊云服务本身的安全机制,制造了一个几乎无法破解的困境,
迫使受害者不得不选择支付赎金。
勒索组织首先获取了受害者的亚马逊账户凭证,
这些凭证具有读取存储数据和写入加密工具的权限。
随后,他们利用亚马逊的服务器端加密工具(SSE-C)将客户的数据重新加密,
使用户无法正常访问,并向要求受害者在七天内支付赎金,
否则将永久删除所有加密文件。
这篇文章对整个攻击事件过程描述的比较模糊,文中提到“勒索组织首先获取了受害者的亚马逊账户凭证”
,但转而又提到“此次攻击没有利用任何系统漏洞,而是利用了亚马逊云服务本身的安全机制”
。这两句前后矛盾的表述让许多人感到困惑,并担心自身系统安全。
为此,AWS官方也有一篇博客针对类似攻击事件给出了一些信息,英文原文在这里。基于这两篇文章,本文介绍下类似勒索攻击的由来,以及类似的防护方法。
二、勒索攻击的入侵和防御
1、恶意加密数据的勒索攻击
勒索攻击并不是一种新的攻击形式。在十多年前的201x年代就有因为微软Windows SMB服务漏洞造成勒索攻击的重大事件。当时被攻击的原因是监听在135/445端口的SMB服务存在重大安全漏洞,入侵者可获得Windows系统管理员权限,从而有权限读写数据。此次安全事件导致全球范围包括中国在内的大量企业用户在Windows系统存储上的核心数据被恶意加密。有的受害者支付了赎金获得了密钥得以解密,但更多的是被诈骗、即支付了赎金也拿不到密钥。勒索病毒的潜在危险让缺少安全防护能力的系统管理员瑟瑟发抖。
勒索的关键在于攻击者对数据进行加密的强度很高,要破解这个强度的加密需要强大的算力。而一旦破解时间增长到人类可接受的时间范围内无法进行穷举破解,例如需要的时间在几百年到1000年以上,即定义为数据不可被抢救恢复。如果没有备份的话,受害者只能向勒索者支付赎金来恢复数据。但也有可能遇到诈骗,即支付赎金后并不会拿到解密的密钥。
勒索攻击的加密算法基本都是使用通用的开源算法,例如AES256,算法机制完全公开。正因为这些加密算法都是公开的,所以已经被全球的数学家证明了加密算法本身是没有漏洞的,要解密数据就必须拿到密钥,或者花几千上年时间暴力破解。通常,在攻击者要加密数据之前,先通过算法生成密钥,然后拿密钥对数据做加密运算。这个密钥可以是加密和解密都用同一个密钥的“对称加密”,也可以是加密用“公钥”、解密用“私钥”的非对称加密方式。生成密钥和加密数据的过程可借助所有常见编程语言生成,例如Python、Java、PHP、C、Go语言、Javascript这些都可以。生成密钥和加密数据的算法和代码都是公开的,通过搜索引擎可以搜索出来大量公开例子;此外使用编程助手、或者直接问大语言模型,也可以由人工智能助手生成一段代码,运行这段代码即可对数据完成加密。勒索攻击使用的加密算法可以是一种也可以是多种混合,只要加密强度达到不可暴力破解即达到了攻击者目标。
2、勒索攻击的入侵途径
勒索攻击的根本原因是基础环境被攻破,通常是EC2、容器环境的安全边界被攻破,攻击者获得读写对象存储S3的权限。如果在应用系统中使用了不仅是S3权限而是具有Admin权限的AKSK密钥的话,还可能导致整个AWS账号被破坏。常见漏洞包括但不限于如下。
(1) 应用系统潜在的安全漏洞
- 没有设置基础的防护:例如对外暴露的WEB应用没有配置WAF,知识产权相关研发类应用没有使用七层防火墙检查流量;
- 安全边界配置错误、过大的对外公开暴露:例如EC2的SSH 22端口、RDP 3389端口向互联网0.0.0.0/0地址开放,没有限制特定来源范围;
- 对外直接暴露的通用软件服务旧版本没打补丁:例如Java应用使用有重大漏洞的Log4J版本,对外暴露的OS没有打最新操作系统补丁,对外暴露的SSH等组件的版本低,包含业界已知重大漏洞;
- 系统配置错误公开权限:例如错误启用了一些软件系统内置、且原本是禁用状态的管理员账户;
- 特殊的0-Day漏洞:尚未爆发、安全社区未知的新漏洞;
以上是一些可能导致应用系统安全边界被突破的原因。
(2) AKSK权限和防护的安全漏洞
AWS账号被突破可能导致整个AWS账号内的所有资源处于极度危险状态,可能被盗窃、删除、破坏,或者被加密勒索。造成这样的一些可能原因是:
- AWS账号密码过于简单被穷举破解、没设置MFA多因素认证
- AKSK密钥错误泄漏到公开网站(例如错误地被发布到Github公开代码库)
- 没有STS临时授权机制,密钥持久使用没有轮换机制,开发者离职等管理问题造成代码泄漏
- 没有分多个IAM用户,一切操作都以单一Admin账号在操作,应用系统使用了具有Admin级别的AKSK密钥,但应用系统被攻破,被攻击者拿到了AKSK配置文件
以上是一些可能导致AWS账号的安全边界被突破的原因。
(3) 数据管理不完善
- 没有使用S3存储桶的版本管理功能,文件历史无法追溯
- 没有使用S3生命周期策略,以及用于长期合规、归档保存的Object Lock
- 没有对数据做独立的、冗余的、跨地域的备份
以上风险可能会导致数据被破坏后无法恢复历史数据。
3、勒索攻击的防护
(1) 实施一定的安全基线
防护勒索要显著提高自己的安全基线。根据上一个章节中提到的弱点(Vulnerable),需要逐个检查确认自己的防护机制。
同时,安全极限还需要定期review。因为系统会存在变更需求(Change Management)。在变更过程中,会导致原有的安全基线因为配置新的系统而打破,因此就需要定期复核安全基线,确保有效防护。
(2) 持久化的数据备份
预防勒索攻击除了要做安全防护之外,还有一个重要的维度即可持续性,也叫做韧性(Resillience)。主要实现手段就是假设当前账号被完全摧毁的情况下,通过恢复持久化数据备份中上一个备份点,得以从灾难中复原,将损失降到最低。
主要手段和途径包括:
- 实施一定频度的定期的、自动的备份:备份的运行应不依赖人工执行,应通过系统配置自动执行,并按照合理的频率实施备份。过高的备份频率会影响生产系统性能、增加存储成本;过低的备份频率不能提供有效的数据保护措施;
- 检查备份成功的机制:自动备份的发起不意味着每次备份的成功,尤其是数据集较大、小文件多的场景下,单次完整备份可能持续数个小时。此时就需要配置检测机制,确认备份成功,在备份成功时候以某种方式提示;
- 备份只读归档的机制:备份文件应为不可篡改,一旦写入就不能再被编辑、更新,并在一定的保管周期内不能被删除。此时可通过S3 Object Lock等机制进行锁定,防止备份文件被攻击者篡改或删除;
- 定期恢复测试的机制:备份文件如果因为写入错误或者配置错误不能进行有效恢复,那么意味着没有备份。因此定期的恢复测试非常重要,确保备份中的数据集是可被正常读取、可恢复的;
- 备份数据跨账号存放缩小爆炸范围避免连带伤害:备份运行机制可使用独立的备份账号来进行,通过不同的AWS账号增加了一层防护边界,即使用户拿到了应用运行环境的AWS账号的AKSK,也无法破坏备份账号内的数据。
以上备份手段将是抵御勒索病毒的最终手段,也就是对整个环境“重启”,即不与勒索者谈判妥协而是调出备份数据重新部署,将损失降到最低。
三、本次攻击事件分析
1、时间线分析
结合开始引用的两篇文章,我们拼接出来一个完整的时间线:
- 某用户使用了AWS服务,使用S3存储桶保管重要数据;
- 用户因为某种原因AKSK泄露,可能是引用系统漏洞,或者是未使用相关安全防护服务,或者是配置错误导致对外公开,可能的原因已经在上一个章节进行分析;
- 泄露的密钥具有读取S3存储桶,并有写入的权限;
- 攻击者对用户S3存储桶内的数据做了强度足以抵抗暴力破解的数据加密,以此勒索用户;
- 攻击者选择的加密环境和工具是S3自带的SSE-C加密功能;
- 具体发起读取数据和加密数据操作的环境是隶属于被攻击的账号,还是从外部攻击点发起,这一点没有披露。
从以上信息可以看出,攻击者发起攻击的根本原因是从某漏洞拿到AKSK和读写权限。那么SSE-C又是什么功能呢,请看下一章节讲解。
2、什么是SSE-C
S3的数据加密主要包括客户端加密,和与之对应的服务器端加密。客户端加密指用户在应用程序上(例如EC2或容器上)自己执行加密算法,将被加密的明文转换为密文,然后把密文提交给S3的API保存。因为加密算法发生在S3之外的客户端,因此被叫做客户端加密。与之对应的服务器端加密是指加密过程发生在S3的服务器端,客户端代码(包括EC2或容器上)不需要处理加密和加密负载,客户端将被加密的原始文件的明文发送给S3的API,由S3在存储之前进行自动加密。由于加密的过程发生在服务器端,因此叫做服务器端加密。客户端加密和服务器端加密的区别是发送给S3 API的是明文还是密文。如果是密文,说明客户端已经事先做好了加密,那么属于服务器端加密。如果发送给S3 API的是明文,那加密责任在S3后台,就属于服务器端加密。
服务器端加密缩写为SSE,而SSE-C是以上介绍的服务器端加密的一种。服务器端加密可以由不同的服务来管理密钥,由S3服务管理密钥的话,被称为SSE-S3;由AWS KMS服务来管理密钥的话,被称为SSE-KMS。如果是用户自己管理密钥的话,也就是SSE-C,即全称是server-side encryption with customer-provided keys
。使用SSE-C的主要场景是用户已经有自己的密钥管理机制即不希望通过AWS KMS管理密钥,并且又不想实施客户端加密(即不想在EC2和容器内自己写加密算法代码),那么此场景选择SSE-C最为适合。
SSE-C的使用过程如下。首先,将密钥和被加密的文件明文都发给S3的API,S3使用用户发来的密钥自动实施加密(AES256),然后S3服务将把加密后的密文保存到S3上。在完成加密后,S3服务不会保存用户通过API发送来的密钥,且原始文件的明文也不会被保存,加密完成就清空内存相关记录,也就是阅后即焚。最终S3存储上只保留加密后的密文。如果要获取原始文件,用户需要向S3的API发送被访问的文件名(S3对应的存储桶和Key)以及本文件最初被加密时候使用的密钥。如果密钥正确,则文件被S3正确解密并返回给用户。如果发送给S3 API的密钥错误,那么将无权获取被加密的文件。
以上SSE-C的使用场景可以看出,SSE-C将加密过程的负载转移到S3服务器后台,用户应用代码只需要最简单的发送密钥,不需要承担加密算法和算力,开发简单方面。唯一需要注意的就是保管好密钥,密钥一旦丢失则数据无法被恢复。以上就是SSE-C的运作机制。
3、本次攻击事件小结
综上所述,勒索攻击是攻击者将用户的生产数据进行不可逆加密,并以归还密钥为由索要赎金。在本次攻击事件中,攻击者使用了当前账号内的S3服务的SSE-C功能来加密数据。如果将被攻击的漏洞归属于SSE-C是有失偏颇的。禁用SSE-C加密功能并不能阻挡勒索攻击。当攻击者通过漏洞获取到访问权限后,攻击者会选择自己最擅长的加密代码和运行环境来执行加密,以降低完成整个攻击之前自身行为暴露并被阻断的可能。攻击者可使用的多种加密数据的手段并不依赖SSE-C,因此防护勒索攻击还是要从整体安全角度进行防护,对整个账号进行整体加固。
当然,如果在完成整体安全加固的基础上,还希望对特定存储桶禁用SSE-C,那么可以参考下一个章节的方法。
四、配置S3存储桶策略禁用SSE-C加密方式
注意:禁用SSE-C并不能防御勒索攻击,预防勒索攻击应从安全边界、密钥泄露等角度进行加权加固和防护。
不论创建存储桶时候选择哪一种服务器端加密算法(默认是SSE-S3),S3存储桶默认都是允许SSE-C加密方式的。如果希望显式的禁用这个功能,那么可以编写一段存储桶策略并配置到存储桶上。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RestrictSSECObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<your-bucket-name>/*",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption-customer-algorithm": "false"
}
}
}
]
}
替换以上Policy中的<your-bucket-name>
为实际的存储桶名称,然后粘贴到存储桶配置中。如下截图。

配置完毕后保存存储桶策略。
此时再写入SSE-C就会被S3服务拒绝了。报错信息类似如下:
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:iam::133129065110:user/zhangsan is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::sse-c-demo/text02.txt" with an explicit deny in a resource-based policy
这里边可以看到报错的关键字是with an explicit deny in a resource-based policy
,即显式的拒绝用SSE-C的加密算法输入。本策略不影响现有其他加密算法的写入,包括存储桶默认的SSE-S3
和通过KMS管理密钥的SSE-KMS
都可以正确写入。本策略只是拒绝SSE-C
方式的写入。由此可以看到,存储桶已经关闭了SSE-C功能。
当然,如本文一所提到,如果本账号存在安全漏洞被入侵,攻击者还可以用其他多种加密算法将用户数据加密,然后实施勒索。因此勒索攻击的防护要点在于安全加固,停用SSE-C这一特定加密算法只是辅助手段。
五、参考文档
https://aws.amazon.com/cn/blogs/security/preventing-unintended-encryption-of-amazon-s3-objects
https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerSideEncryptionCustomerKeys.html