S3 公共 Buckets
一个 bucket 被认为是 “公共的” 如果 任何用户都可以列出 bucket 的内容 ,而 “私有的” 则是 bucket 的内容 只能由某些用户列出或写入 。
公司可能会有 bucket 权限配置错误 ,使得任何人或任何 AWS 账户中的已认证用户都可以访问(即任何人)。请注意,即使有这样的配置错误,有些操作可能仍无法执行,因为 bucket 可能有自己的访问控制列表(ACLs)。
在这里了解 AWS-S3 配置错误: http://flaws.cloud 和 http://flaws2.cloud/
查找 AWS Buckets
查找网页何时使用 AWS 存储某些资源的不同方法:
枚举 & OSINT:
使用 burp(爬取 网页)或手动浏览页面,所有 加载的资源 都会保存在历史记录中。
Copy http://s3.amazonaws.com/[bucket_name]/
http://[bucket_name].s3.amazonaws.com/
检查 CNAMES ,如 resources.domain.com
可能有 CNAME bucket.s3.amazonaws.com
bucket 名称 和 bucket 域名 需要 相同 。
flaws.cloud 的 IP 是 52.92.181.107,如果你访问它,它会重定向到 https://aws.amazon.com/s3/ 。此外,dig -x 52.92.181.107
会返回 s3-website-us-west-2.amazonaws.com
。
暴力破解
你可以通过 暴力破解名称 来查找与您正在进行渗透测试的公司相关的 buckets:
Copy # 生成一个单词列表以创建排列
curl -s https://raw.githubusercontent.com/cujanovic/goaltdns/master/words.txt > /tmp/words-s3.txt.temp
curl -s https://raw.githubusercontent.com/jordanpotti/AWSBucketDump/master/BucketNames.txt >> /tmp/words-s3.txt.temp
cat /tmp/words-s3.txt.temp | sort -u > /tmp/words-s3.txt
# 基于要测试的域名和子域名生成一个单词列表
## 将这些域名和子域名写入 subdomains.txt
cat subdomains.txt > /tmp/words-hosts-s3.txt
cat subdomains.txt | tr "." "-" >> /tmp/words-hosts-s3.txt
cat subdomains.txt | tr "." "\n" | sort -u >> /tmp/words-hosts-s3.txt
# 基于要攻击的域名和子域名列表创建排列
goaltdns -l /tmp/words-hosts-s3.txt -w /tmp/words-s3.txt -o /tmp/final-words-s3.txt.temp
## 上一个工具专门用于创建子域名的排列,让我们过滤该列表
### 删除以 "." 结尾的行
cat /tmp/final-words-s3.txt.temp | grep -Ev "\.$" > /tmp/final-words-s3.txt.temp2
### 创建没有 TLD 的列表
cat /tmp/final-words-s3.txt.temp2 | sed -E 's/\.[a-zA-Z0-9]+$//' > /tmp/final-words-s3.txt.temp3
### 创建没有点的列表
cat /tmp/final-words-s3.txt.temp3 | tr -d "." > /tmp/final-words-s3.txt.temp4http://phantom.s3.amazonaws.com/
### 创建没有连字符的列表
cat /tmp/final-words-s3.txt.temp3 | tr "." "-" > /tmp/final-words-s3.txt.temp5
## 生成最终的单词列表
cat /tmp/final-words-s3.txt.temp2 /tmp/final-words-s3.txt.temp3 /tmp/final-words-s3.txt.temp4 /tmp/final-words-s3.txt.temp5 | grep -v -- "-\." | awk '{print tolower($0)}' | sort -u > /tmp/final-words-s3.txt
## 调用 s3scanner
s3scanner --threads 100 scan --buckets-file /tmp/final-words-s3.txt | grep bucket_exists
Loot S3 Buckets
给定 S3 开放 buckets,BucketLoot 可以自动 搜索有趣的信息 。
查找区域
你可以在 https://docs.aws.amazon.com/general/latest/gr/s3.html 找到 AWS 支持的所有区域
通过 DNS
你可以通过 dig
和 nslookup
进行 DNS 请求发现的 IP 来获取 bucket 的区域:
Copy dig flaws.cloud
;; ANSWER SECTION:
flaws.cloud. 5 IN A 52.218.192.11
nslookup 52.218.192.11
Non-authoritative answer:
11.192.218.52.in-addr.arpa name = s3-website-us-west-2.amazonaws.com.
检查解析的域名是否包含“website”一词。
你可以通过以下链接访问静态网站:flaws.cloud.s3-website-us-west-2.amazonaws.com
或者你可以访问存储桶:flaws.cloud.s3-us-west-2.amazonaws.com
尝试访问
如果你尝试访问一个存储桶,但在域名中指定了另一个区域 (例如,存储桶在 bucket.s3.amazonaws.com
,但你尝试访问 bucket.s3-website-us-west-2.amazonaws.com
),那么你将会被指向正确的位置 :
枚举存储桶
为了测试存储桶的开放性,用户可以直接在他们的网页浏览器中输入URL。一个私有存储桶会响应“Access Denied”。一个公共存储桶会列出前1,000个已存储的对象。
对所有人开放:
私有:
你也可以使用cli进行检查:
Copy #Use --no-sign-request for check Everyones permissions
#Use --profile <PROFILE_NAME> to indicate the AWS profile(keys) that youwant to use: Check for "Any Authenticated AWS User" permissions
#--recursive if you want list recursivelyls
#Opcionally you can select the region if you now it
aws s3 ls s3://flaws.cloud/ [--no-sign-request] [--profile < PROFILE_NAME > ] [ --recursive] [--region us-west-2]
如果 bucket 没有域名,在尝试枚举时,只放 bucket 名称 ,而不是整个 AWSs3 域名。示例:s3://<BUCKETNAME>
Public URL 模板
Copy https://{user_provided}.s3.amazonaws.com
从公共 Bucket 获取账户 ID
可以通过利用新的 S3:ResourceAccount
策略条件键 来确定一个 AWS 账户。此条件基于 S3 bucket 所在的账户来限制访问 (其他基于账户的策略基于请求主体所在的账户来限制)。
由于策略可以包含通配符 ,因此可以一次一个数字 地找到账户号码。
此工具自动化了该过程:
Copy # Installation
pipx install s3-account-search
pip install s3-account-search
# With a bucket
s3-account-search arn:aws:iam::123456789012:role/s3_read s3://my-bucket
# With an object
s3-account-search arn:aws:iam::123456789012:role/s3_read s3://my-bucket/path/to/object.ext
这种技术同样适用于 API Gateway URLs、Lambda URLs、Data Exchange 数据集,甚至可以获取标签的值(如果你知道标签键)。你可以在原始研究 和工具conditional-love 中找到更多信息,以自动化此漏洞利用。
确认一个 bucket 属于某个 AWS 账户
正如这篇博客文章 中所解释的,如果你有权限列出一个 bucket ,可以通过发送如下请求来确认 bucket 所属的 accountID:
Copy curl -X GET "[bucketname].amazonaws.com/" \
-H "x-amz-expected-bucket-owner: [correct-account-id]"
<? xml version = "1.0" encoding = "UTF-8" ? >
< ListBucketResult xmlns = "http://s3.amazonaws.com/doc/2006-03-01/" > ... < /ListBucketResult >
如果错误是“Access Denied”,这意味着账户ID是错误的。
使用电子邮件作为根账户枚举
如这篇博客文章 中所解释的,可以通过尝试通过ACLs授予电子邮件对S3 bucket的权限 来检查电子邮件地址是否与任何aws账户相关联。如果这不会触发错误,这意味着该电子邮件是某个aws账户的根用户:
Copy s3_client . put_bucket_acl (
Bucket = bucket_name,
AccessControlPolicy = {
'Grants' : [
{
'Grantee' : {
'EmailAddress' : 'some@emailtotest.com' ,
'Type' : 'AmazonCustomerByEmail' ,
},
'Permission' : 'READ'
},
],
'Owner' : {
'DisplayName' : 'Whatever' ,
'ID' : 'c3d78ab5093a9ab8a5184de715d409c2ab5a0e2da66f08c2f6cc5c0bdeadbeef'
}
}
)
参考资料