AWS - S3 Unauthenticated Enum

支持 HackTricks

S3 公共 Buckets

一个 bucket 被认为是 “公共的” 如果 任何用户都可以列出 bucket 的内容,而 “私有的” 则是 bucket 的内容 只能由某些用户列出或写入

公司可能会有 bucket 权限配置错误,使得任何人或任何 AWS 账户中的已认证用户都可以访问(即任何人)。请注意,即使有这样的配置错误,有些操作可能仍无法执行,因为 bucket 可能有自己的访问控制列表(ACLs)。

在这里了解 AWS-S3 配置错误: http://flaws.cloud http://flaws2.cloud/

查找 AWS Buckets

查找网页何时使用 AWS 存储某些资源的不同方法:

枚举 & OSINT:

  • 使用 wappalyzer 浏览器插件

  • 使用 burp(爬取网页)或手动浏览页面,所有 加载的资源 都会保存在历史记录中。

  • 检查资源 在以下域名中:

http://s3.amazonaws.com/[bucket_name]/
http://[bucket_name].s3.amazonaws.com/
  • 检查 CNAMES,如 resources.domain.com 可能有 CNAME bucket.s3.amazonaws.com

  • 检查 https://buckets.grayhatwarfare.com,一个已经 发现的开放 bucket 的网站。

  • bucket 名称bucket 域名 需要 相同

  • flaws.cloudIP 是 52.92.181.107,如果你访问它,它会重定向到 https://aws.amazon.com/s3/。此外,dig -x 52.92.181.107 会返回 s3-website-us-west-2.amazonaws.com

  • 要检查它是否是一个 bucket,你也可以 访问 https://flaws.cloud.s3.amazonaws.com/

暴力破解

你可以通过 暴力破解名称 来查找与您正在进行渗透测试的公司相关的 buckets:

# 生成一个单词列表以创建排列
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

你可以通过 dignslookup 进行 DNS 请求发现的 IP 来获取 bucket 的区域:

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进行检查:

#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 模板

https://{user_provided}.s3.amazonaws.com

从公共 Bucket 获取账户 ID

可以通过利用新的 S3:ResourceAccount 策略条件键 来确定一个 AWS 账户。此条件基于 S3 bucket 所在的账户来限制访问(其他基于账户的策略基于请求主体所在的账户来限制)。 由于策略可以包含通配符,因此可以一次一个数字地找到账户号码。

此工具自动化了该过程:

# 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:

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账户的根用户:

s3_client.put_bucket_acl(
Bucket=bucket_name,
AccessControlPolicy={
'Grants': [
{
'Grantee': {
'EmailAddress': 'some@emailtotest.com',
'Type': 'AmazonCustomerByEmail',
},
'Permission': 'READ'
},
],
'Owner': {
'DisplayName': 'Whatever',
'ID': 'c3d78ab5093a9ab8a5184de715d409c2ab5a0e2da66f08c2f6cc5c0bdeadbeef'
}
}
)

参考资料

支持 HackTricks

Last updated