2020年4月17日

【AWS 安全系列】Amazon S3 配置错误(下)

作者 spoony
在上一篇文章【AWS 安全系列】Amazon S3 配置错误(上)中,介绍了 Amazon S3 的一些基本概念,并且搭建了实验环境。本篇文章来介绍下怎样发现配置错误的 Amazon S3 存储桶,以及 Amazon S3 存储桶的安全评估方法。

1. 怎样发现存储桶?
首先我们要发现一个存在的存储桶,即使它不是公开的,有很多方法可以发现存在的存储桶。

a. 使用 aws cli 工具


我们可以直接去列出一个存储桶,如果访问被拒绝或者成功列出存储桶的内容,则存在存储桶;如果提示不存在该存储桶,则不存在。这种方法不会出现误报。
aws s3 ls s3://timeshatter --no-sign-request

【AWS 安全系列】Amazon S3 配置错误(下)

b. 查看网站的HTTP 响应 Server 头是否带有 AmazonS3


看到这个响应头时,就要考虑下该网站是否是一个存储桶静态托管的网站了。

【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

关于这个方式发现潜在的存储桶,我们可以借助 burp 的 Scan Check Builder 插件,新建一个 Passive Respone , 在 Response 选项卡中选择 Simple String , 在下面的Grep Set 中添加我们要在 HTTP 响应中要匹配的关键词,如 AmazonS3

【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

c. 直接访问存储桶的URL地址

存储桶的URL地址构成为
https://<bucketname>.s3.amazonaws.com
或者
https://<bucketname>.s3-<aws_region>.amazonaws.com
比如在 ap-northeast-1 区域创建了一个名为 timeshatter 的存储桶,则可以通过以下方式来访问
https://timeshatter.s3.amazonaws.com
https://timeshatter.s3-ap-northeast-1.amazonaws.com/

【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

如果存储桶不存在,会提示NoSuckBucket

【AWS 安全系列】Amazon S3 配置错误(下)

这种方式有一定的误报,因为有少数区域创建的存储桶只能通过区域的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

【AWS 安全系列】Amazon S3 配置错误(下)

根据上面返回的

s3-website-us-west-2.amazonaws.com

我们可以尝试访问:

http://flaws.cloud.s3-website-us-west-2.amazonaws.com/

这种情况出现在静态托管的网站,静态托管的网站一般会用域名来做存储桶名。

【AWS 安全系列】Amazon S3 配置错误(下)

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 资源。

【AWS 安全系列】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的使用如下图,在存储桶上点击权限,然后点击阻止公有访问的编辑,把阻止公有访问的勾去掉,然后保存。


【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

在权限-访问控制列表中点击 Everyone,弹出的窗口就是设置所有用户对存储桶访问ACL的地方,可以设置对存储桶对象的读写权限,以及对存储桶ACL的读写权限,也就是读取和修改ACL的权限。

【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

接下来看看设置访问策略的地方,直接点权限,访问策略, 在这里可以把上面的json策略输入到这里保存生效。


【AWS 安全系列】Amazon S3 配置错误(下)


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 许可

在演示开始前,请取消勾选存储桶的阻止公有访问,否则无法单独设置下面的权限。


【AWS 安全系列】Amazon S3 配置错误(下)

设置存储桶 ACL 方式在上面说过了,设置对象 ACL 需要点击该文件,在权限那里点击 Everyone 设置

【AWS 安全系列】Amazon S3 配置错误(下)

对象 READ 

单独设置 hello.txt 对象的READ权限时,即使存储桶禁止列出对象,也可以读取该对象的内容,但不能读取其它对象的内容。权限设置如下:

【AWS 安全系列】Amazon S3 配置错误(下)【AWS 安全系列】Amazon S3 配置错误(下)

下面第一条命令尝试列出 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

【AWS 安全系列】Amazon S3 配置错误(下)

可以看出,对象的读权限单独于存储桶的读权限,即使存储桶没有设置列出对象的权限,也可以读取设置了READ权限的对象。


对象 READ_ACP


对象的 READ_ACP 权限用于读取对象的上的 ACL ,设置如下:


【AWS 安全系列】Amazon S3 配置错误(下)【AWS 安全系列】Amazon S3 配置错误(下)

使用下面命令分别读取 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

【AWS 安全系列】Amazon S3 配置错误(下)

成功读取 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 安全系列】Amazon S3 配置错误(下)【AWS 安全系列】Amazon S3 配置错误(下)

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

【AWS 安全系列】Amazon S3 配置错误(下)

【AWS 安全系列】Amazon S3 配置错误(下)

下面介绍下 WRITE 权限 和 WRITE_ACP 权限, 注意, 设置写入权限是很危险的,甚至导致其它用户完全控制存储桶。

对象 WRITE

对象没有 WRITE 权限设置,因为对象只属于其上传者,其它用户无法对写入该对象。


存储桶 WRITE

设置存储桶 WRITE 权限后,任何用户都可以上传文件到存储桶,虽然我们没办法读取其它用户上传的文件,但却可以覆盖其它用户上传的文件,由于上传的对象属于上传者,所以覆盖后的文件属于后面上传该文件的用户。

相应的权限设置如下:


【AWS 安全系列】Amazon S3 配置错误(下)【AWS 安全系列】Amazon S3 配置错误(下)

通过以下命令上传文件到存储桶:

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

【AWS 安全系列】Amazon S3 配置错误(下)

可以看到刚开始的时候,未认证的用户无法读取 hello.txt ,但却可以上传一个 hello.txt 覆盖原来的 hello.txt , 然后读取自己上传的 hello.txt 。

注意,实际测试中,不要这样做,因为这样会覆盖原来的文件,造成毁灭性破坏。我们应该上传一个随机文件名的文件来验证该漏洞。


对象和存储桶的 WRITE_ACP 

对象和存储桶的行为很相似,所以这里放在一起讲。


赋予任意用户 WRITE_ACP 是最危险的行为,因为这样可以让任何认证的用户修改 ACL,从而完全控制对象或存储桶。


对象WRITE ACP 设置如下:

【AWS 安全系列】Amazon S3 配置错误(下)【AWS 安全系列】Amazon S3 配置错误(下)

在这种权限设置的情况下,其它用户可以通过修改对象 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

【AWS 安全系列】Amazon S3 配置错误(下)

接着 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

【AWS 安全系列】Amazon S3 配置错误(下)

另外,存储桶 WRITE_ACP 也类似

存储桶 WRITE_ACP 设置如下:


【AWS 安全系列】Amazon S3 配置错误(下)【AWS 安全系列】Amazon S3 配置错误(下)

在这种权限设置的情况下,其它用户可以通过修改存储桶 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"

【AWS 安全系列】Amazon S3 配置错误(下)

到这里,基本介绍完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 配置错误漏洞到这里介绍结束了,这两篇文章主要关注未授权操作。下一篇文章将会介绍在获取别人的访问密钥时,可以怎样利用。


敬请关注~



往期文章

【AWS 安全系列】Amazon S3 配置错误(上)

渗透测试中使用浏览器的正确姿势

本文作者:timeshatter

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/127552.html

本文来源于互联网:【AWS 安全系列】Amazon S3 配置错误(下)