a. 使用 aws cli 工具
aws s3 ls s3://timeshatter --no-sign-request
b. 查看网站的HTTP 响应 Server 头是否带有 AmazonS3
看到这个响应头时,就要考虑下该网站是否是一个存储桶静态托管的网站了。
这种方式有一定的误报,因为有少数区域创建的存储桶只能通过区域的URL来访问:
https://<bucketname>.s3-<aws_region>.amazonaws.com
d. 通过DNS解析记录来查找存在的存储桶
dig @8.8.8.8 +nocmd flaws.cloud any +multiline +noall +answer nslookup 52.218.221.210
根据上面返回的
s3-website-us-west-2.amazonaws.com
我们可以尝试访问:
http://flaws.cloud.s3-website-us-west-2.amazonaws.com/
这种情况出现在静态托管的网站,静态托管的网站一般会用域名来做存储桶名。
e. 查找网站源码,看看是否引用了存储桶上的资源
f. google hack 查找网站是否引用存储桶上的资源
site:examle.com intext:amazonaws.com site:examle.com intext:s3.amazonaws.com
g. 暴力猜解
这里说的暴力猜解是指制作有针对性的字典来枚举可能存在的存储桶。假设域名为upload.example.com,其可能的存储桶名为 upload.example.com, example.com, example, upload-example-com, example-com, example-upload 等等。
当然,发现了名称相近的存储桶,也不能证明就是该公司拥有,还需要找一些证据证明,比如有该公司的网站引用了该存储桶的资源或者里面的文件和该公司有关。
2. Amazon S3 权限介绍
先做些权限配置的概念介绍,如果觉得难理解,可以直接跳到利用演示,不懂的时候再回头看。
默认情况下,所有 Amazon S3 资源都是私有的,包括存储桶、对象和相关子资源(例如,lifecycle 配置和 website 配置)。只有资源拥有者,即创建该资源的 AWS 账户可以访问该资源。 资源拥有者可以选择通过编写访问策略授予他人访问权限。
Amazon S3 提供的访问策略选项大致可分为基于资源的策略和用户策略两类。附加到资源 (存储桶和对象) 的访问策略称为基于资源的策略。例如,存储桶策略和访问控制列表 (ACL) 就是基于资源的策略。您也可以将访问策略附加到您账户中的用户。这些策略称为用户策略。您可以选择使用基于资源的策略、用户策略或这些策略的某种组合来管理您的 Amazon S3 资源权限。
基于资源的策略 – 存储桶策略和访问控制列表 (ACL) 是基于资源的策略,因为您将它们附加到 Amazon S3 资源。
访问控制列表(ACL)
每个存储桶和对象都有关联的 ACL。ACL 是一个指定被授权者和所授予权限的授权列表。您可使用 ACL 向其他 AWS 账户授予基本的读/写权限。ACL 使用 Amazon S3–特定的 XML 架构。
下面是一个示例存储桶 ACL。该 ACL 中的授权显示一个存储桶拥有者具有完全控制权限。
<?xml version="1.0" encoding="UTF-8"?> <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Owner> <ID>*** Owner-Canonical-User-ID ***</ID> <DisplayName>owner-display-name</DisplayName> </Owner> <AccessControlList> <Grant> <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Canonical User"> <ID>*** Owner-Canonical-User-ID ***</ID> <DisplayName>display-name</DisplayName> </Grantee> <Permission>FULL_CONTROL</Permission> </Grant> </AccessControlList> </AccessControlPolicy>
存储桶和对象 ACL 使用相同的 XML 架构。
存储桶策略 – 对于存储桶,您可以添加存储桶策略来授予其他 AWS 账户或 IAM 用户对相应存储桶及其中对象的权限。任何对象权限都仅应用于存储桶拥有者创建的对象。存储桶策略补充 (在很多情况下取代) 基于 ACL 的访问策略。
下面是一个示例存储桶策略。您使用 JSON 文件来表示存储桶策略 (和用户策略)。该策略授予对一个存储桶中所有对象的匿名读取权限。该存储桶策略有一条语句,允许对名为 examplebucket 的存储桶中的对象执行 s3:GetObject 操作 (读取权限)。 通过使用通配符 (*) 指定 principal,该策略授予匿名访问权限。
{ "Version":"2012-10-17", "Statement": [ { "Effect":"Allow", "Principal": "*", "Action":["s3:GetObject"], "Resource":["arn:aws:s3:::examplebucket/*"] } ] }
到这里可能有点懵,访问控制列表(ACL)和访问控制策略(ACP)有什么区别呢。其实ACL可以理解ACP的子集, ACL可以做的权限控制, ACP都可以做到, ACL 只能作用在存储桶和对象上,也就是控制对存储桶和对象的访问。
而 ACP 除了可以控制对存储桶和对象的访问,还可以限定哪些具体的用户可以访问存储桶和对象。
ACL的使用如下图,在存储桶上点击权限,然后点击阻止公有访问的编辑,把阻止公有访问的勾去掉,然后保存。
在权限-访问控制列表中点击 Everyone,弹出的窗口就是设置所有用户对存储桶访问ACL的地方,可以设置对存储桶对象的读写权限,以及对存储桶ACL的读写权限,也就是读取和修改ACL的权限。
接下来看看设置访问策略的地方,直接点权限,访问策略, 在这里可以把上面的json策略输入到这里保存生效。
3. Amazon S3 配置错误演示
现在开始设置配置错误的存储桶,然后演示各种错误配置会导致什么后果。
下表列出了 Amazon S3 在 ACL 中支持的权限集。对于对象 ACL 和存储桶 ACL,ACL 权限集相同。但是,根据上下文 (存储桶 ACL 或对象 ACL),这些 ACL 权限将授予针对特定存储桶或对象操作的权限。下表列出了权限并描述这些权限在对象和存储桶上下文中的意义。
许可 | 在存储桶上授权的时候 | 在对象上授权的时候 |
---|---|---|
READ |
允许被授权者列出存储桶中的对象 | 允许被授权者读取对象数据及其元数据 |
WRITE |
允许被授权者创建、覆盖和删除存储桶中的任意对象 | 不适用 |
READ_ACP |
允许被授权者读取存储桶 ACL | 允许被授权者读取对象 ACL |
WRITE_ACP |
允许被授权者为适用的存储桶编写 ACL | 允许被授权者为适用的对象编写 ACL |
FULL_CONTROL |
允许被授权者在存储桶上的 READ、WRITE、READ_ACP和 WRITE_ACP 许可 | 允许被授权者在对象上的 READ、READ_ACP 和 WRITE_ACP 许可 |
在演示开始前,请取消勾选存储桶的阻止公有访问,否则无法单独设置下面的权限。
设置存储桶 ACL 方式在上面说过了,设置对象 ACL 需要点击该文件,在权限那里点击 Everyone 设置
对象 READ
单独设置 hello.txt 对象的READ权限时,即使存储桶禁止列出对象,也可以读取该对象的内容,但不能读取其它对象的内容。权限设置如下:
下面第一条命令尝试列出 timeshatter-example 存储桶的所有对象,由于没有设置列出对象权限(存储桶的READ权限),所以拒绝访问,但即可以单独下载存储桶里面的 hello.txt 文件,而另一个没有设置 READ 权限的 world.txt 则不能下载。
aws s3api list-objects --bucket timeshatter-example --no-sign-request aws s3api get-object --bucket timeshatter-example --key hello.txt hello.txt --no-sign-request aws s3api get-object --bucket timeshatter-example --key world.txt world.txt --no-sign-request
可以看出,对象的读权限单独于存储桶的读权限,即使存储桶没有设置列出对象的权限,也可以读取设置了READ权限的对象。
对象 READ_ACP
对象的 READ_ACP 权限用于读取对象的上的 ACL ,设置如下:
使用下面命令分别读取 hello.txt (设置了READ_ACP) 和 world.txt 的 ACL
aws s3api get-object-acl --bucket timeshatter-example --key hello.txt --no-sign-request aws s3api get-object-acl --bucket timeshatter-example --key world.txt --no-sign-request
成功读取 hello.txt 的 ACL ,可以看到有个URI字段,值为
http://acs.amazonaws.com/groups/global/AllUsers,这个URI代表所有用户,另外一个Permission 字段的值为 READ_ACP。这个ACL的意思是所有用户都有 READ_ACP 权限。
另外,由于 world.txt 没有设置 READ_ACP ,所以无法读取它的 ACL 。
小结: 对象和存储桶的 READ 和 READ_ACP 权限是独立的。如果不小心开启了对象的 READ 和 READ_ACP 权限,即使存储桶没有开启 READ 和 READ_ACP,也可以读取对象的数据和ACL。
存储桶的 READ 和 READ_ACP
相反,设置了存储桶的READ 和 READ_ACP ,但没有设置对象的 READ 和
READ_ACP ,这样虽然可以列出对象,但无法读取对象的内容和 ACL。其设置如下:
aws s3api list-objects --bucket timeshatter-example --no-sign-request aws s3api get-bucket-acl --bucket timeshatter-example --no-sign-request aws s3api get-object --bucket timeshatter-example --key hello.txt hello.txt --no-sign-request aws s3api get-object-acl --bucket timeshatter-example --key hello.txt --no-sign-request
下面介绍下 WRITE 权限 和 WRITE_ACP 权限, 注意, 设置写入权限是很危险的,甚至导致其它用户完全控制存储桶。
对象 WRITE
对象没有 WRITE 权限设置,因为对象只属于其上传者,其它用户无法对写入该对象。
存储桶 WRITE
设置存储桶 WRITE 权限后,任何用户都可以上传文件到存储桶,虽然我们没办法读取其它用户上传的文件,但却可以覆盖其它用户上传的文件,由于上传的对象属于上传者,所以覆盖后的文件属于后面上传该文件的用户。
相应的权限设置如下:
通过以下命令上传文件到存储桶:
aws s3api put-object --bucket timeshatter-example --key hello.txt --body hello.txt --no-sign-request aws s3api get-object --bucket timeshatter-example --key hello.txt hello.txt --no-sign-request
可以看到刚开始的时候,未认证的用户无法读取 hello.txt ,但却可以上传一个 hello.txt 覆盖原来的 hello.txt , 然后读取自己上传的 hello.txt 。
注意,实际测试中,不要这样做,因为这样会覆盖原来的文件,造成毁灭性破坏。我们应该上传一个随机文件名的文件来验证该漏洞。
对象和存储桶的 WRITE_ACP
对象和存储桶的行为很相似,所以这里放在一起讲。
赋予任意用户 WRITE_ACP 是最危险的行为,因为这样可以让任何认证的用户修改 ACL,从而完全控制对象或存储桶。
对象WRITE ACP 设置如下:
在这种权限设置的情况下,其它用户可以通过修改对象 ACL ,把对象的
FULL_CONTROL 权限设置给自己,从而完全拥有该对象。假设有另一个用户
bbshatter, bbshatter 可以通过修改 hello.txt 的 ACL, 把 hello.txt 的
FULL_CONTROL 权限的拥有者 ID 设置成自己的规范 ID ,从而完全接管 hello.txt。
操作如下:
bbshatter 先通过 list-buckets 获取自己的规范 ID,其中的 ID 字段的值就是自己的规范 ID 。
aws s3api list-buckets --profile bbshatter
接着 bbshatter 通过以下命令修改 hello.txt 的 FULL_CONTROL 权限的拥有者 ID , 由于 hello.txt 的拥有者 ID 修改成 bbshatter 的ID,所以 bbshatter 可以读和写该对象了,也就是完全控制该对象了。
aws s3api put-object-acl --bucket timeshatter-example --key hello.txt --grant-full-control id=bbshatter_id --profile bbshatter && echo success
另外,存储桶 WRITE_ACP 也类似
存储桶 WRITE_ACP 设置如下:
在这种权限设置的情况下,其它用户可以通过修改存储桶 ACL ,把存储桶的
FULL_CONTROL 权限设置给自己,从而完全拥有该存储桶。
假设有另一个用户bbshatter, bbshatter 可以通过修改存储桶的 ACL,把存储桶的
FULL_CONTROL 权限的拥有者 ID 设置成自己的规范 ID ,从而完全接管整个存储桶。
命令如下:
aws s3api put-bucket-acl --bucket timeshatter-example --grant-full-control id=bbshatter_id && echo "success"
到这里,基本介绍完Amazon S3 配置错误的攻击面了。
总结
可以得出以下结论:
对象的权限独立于存储桶,即使存储桶的四个权限都没有开启,但如果对象开启了READ权限,就可以读该对象的内容。如果对象还开启了 WRITE_ACP ,甚至可以直接转移该对象的控制权。因此,即使无法列出存储桶的对象,无法上传文件到存储桶中,我们仍然可以尝试读或写存储桶的对象。
存储桶如果开启了 WRITE 权限,其它用户就可以上传或者覆盖存储桶的文件。因此,即使无法列出存储桶的对象,我们仍然可以尝试上传对象到存储桶。
存储桶或对象如果开启了 WRITE_ACP 权限,我们可以直接转换存储桶或对象的控制权,获得完全的控制权。因此,即使无法列出存储桶的对象或读取对象,我们仍然可以尝试修改存储桶或对象的 ACL。
总结起来就是,我们应该把存储桶的所有配置测试一遍,以找出可能存在的配置错误。
Amazon S3 配置修复建议
我们应该怎么修复Amazon S3 配置错误呢,其实就是一个最小权限原则。
1. 始终把阻止公有访问勾选上,除非你需要用存储桶静态托管网站。
2. 通过存储桶策略来设置可以由哪些用户可以操作存储桶,而不是让所有用户都可以操作。如下存储桶策略只允许指定用户可以上传对象。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"AddCannedAcl", "Effect":"Allow", "Principal": {"AWS": ["arn:aws:iam::111122223333:root","arn:aws:iam::444455556666:root"]}, "Action":["s3:PutObject","s3:PutObjectAcl"], "Resource":["arn:aws:s3:::examplebucket/*"], "Condition":{"StringEquals":{"s3:x-amz-acl":["public-read"]}} } ] }
3. 不要把权限授予给未认证的用户或认证的用户,这里的认证的用户是指所有配置了访问密钥的用户,而不是合法的用户,这是经常会配置错误的地方,把认证用户误解成自己的用户。
Amazon S3 配置错误漏洞到这里介绍结束了,这两篇文章主要关注未授权操作。下一篇文章将会介绍在获取别人的访问密钥时,可以怎样利用。
敬请关注~
往期文章
本文作者:timeshatter
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/127552.html