列出具有公共读取权限的 S3 对象(在私有存储桶中)

Posted

技术标签:

【中文标题】列出具有公共读取权限的 S3 对象(在私有存储桶中)【英文标题】:List S3 objects with public read permissions (in private bucket) 【发布时间】:2019-02-08 15:29:46 【问题描述】:

我想保护位于 S3 存储桶中的文件,并确保没有共享敏感文件。

我知道有多种方法(在控制台中和使用脚本)来查看哪些存储桶具有公共权限。

但是,即使对象位于私有存储桶中,也可以授予对象匿名读取权限。

很难跟踪/审核公开可读的文件/对象,因为除了浏览 AWS 控制台中的每条路径之外,我看不到任何找到它们的方法。

有没有办法列出存储桶中所有具有匿名(读取)权限的对象?任何方法都可以,包括 AWSCLI、Boto、REST 等。

我考虑尝试使用匿名 AWSCLI 配置文件,但这不允许列出存储桶内容,因此它只能用于单独测试文件。

我想我可以使用 Boto (https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#objectacl) 创建一个脚本。这是唯一的方法,还是有官方方法,例如 AWSCLI 命令?

【问题讨论】:

旁注:如果您担心文件以这种方式“泄漏”,您可以添加一个 Bucket Policy 拒绝 GetObject您的 AWS 账户中的用户。这将覆盖每个对象的权限。 【参考方案1】:

您所说的是对象 ACL。本着job-to-be-done 的精神,我想指出您可以configure a bucket to deny public object ACLs. 这可能是预防的最佳企业实践之一。 auditing and verifying continuously is described here. 的最佳企业实践之一

更新:如果您有兴趣监控和审计桶级 ACL,take a look at this managed AWS Config solution.

但是,如果您正在寻找使用 aws-cli(这是该问题的标签)的 bash 脚本/工具,则可以解决问题:

bucket="my-bucket-name"
search_term="AllUsers"

for key in $(aws s3 ls --recursive s3://$bucket/ | awk '$1=$2=$3=""; print $0' | sed 's/^[ \t]*//'); do
    acl=$(aws s3api get-object-acl --bucket $bucket --key $key) &&
    result_found=$(echo $acl | grep -q $search_term) &&
    if $result_found; then
        echo $key;
        echo $acl;
    fi;
done

它的作用如下:

    递归列出存储桶中的所有对象 遍历这些对象键 询问 S3 该对象的 ACL 是什么 如果该 ACL 包含字符串“AllUsers”(全局 s3 权限组),它将将该 ACL 回显到标准输出。

我将此问题概括为“如果 ACL 包含给定的$search_term,则在存储桶中回显所有密钥及其 ACL”,因此,如果其他人遇到类似但略有不同的问题,此解决方案仍然会有所帮助,只要他们将$search_term 更改为适合他们问题的东西。

理想情况下(假设你不想要公共对象)如果你运行这个......什么都不应该出现。

请记住,此解决方案无法很好地适用于包含大量物体的大型桶。

【讨论】:

非常有帮助!要添加到此脚本的 1 件重要的事情是 IFS=$'\n' 在文件的开头,因此它还将支持名称中带有空格的对象 --key $key 替换为 --key=$key 以支持带有前导破折号的文件名【参考方案2】:

这是 Ruby 中的多线程解决方案:

# Gemfile
source 'https://rubygems.org' do
  gem 'aws-sdk'
  gem 'thread'
end
# find_public_s3_objects.rb
require 'aws-sdk-s3'  # v2: require 'aws-sdk'
require 'thread/pool'

BUCKET = ARGV[0] or raise("expected bucket")

s3 = Aws::S3::Resource.new(region: 'us-east-1')

count = 0
pool = Thread.pool 8
mutex = Mutex.new
s3.bucket(BUCKET).objects.each do |object|
  pool.process do
    grants = object.acl.grants
    mutex.synchronize do
      count += 1
      if count % 100 == 0
        $stderr.write "#count..."
      end
    end
    if grants.map  |x| x.grantee.uri .any?  |x| x =~ /AllUsers/ 
      mutex.synchronize do
        puts object.key
      end
    end
  end
end

pool.shutdown

然后你像这样运行它:

bundle exec ruby find_public_s3_objects.rb my-bucket-name

它比上面提供的基于 Bash 的解决方案快得多。

最初来自Faraday's blog。

【讨论】:

【参考方案3】:

在下面的帖子中描述了一个解决方案(使用 C#)来获取存储在 S3 中的每个对象的 ACL。

How to check ACL of the each object in stored in S3

【讨论】:

以上是关于列出具有公共读取权限的 S3 对象(在私有存储桶中)的主要内容,如果未能解决你的问题,请参考以下文章

Amazon S3 存储:可以在私有存储桶中列出公用文件夹吗?

为啥我可以在未经许可的情况下删除/列出 S3 存储桶中的对象

S3 存储桶策略:在公共存储桶中,将子文件夹设为私有

从 S3 存储桶中读取大量 CSV 文件

AWS S3策略限制用户仅列出存储桶中的某些文件夹

气流:每日刷新后如何在 s3 存储桶中公开对象