S3存储桶策略 - GET隐式允许

3
使用以下存储桶策略时,发现它成功限制了PUT访问,但是GET允许访问已创建的对象,尽管没有任何东西允许此操作。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPut",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<BUCKET>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "<IP ADDRESS>"
                    ]
                }
            }
        }
    ]
}

我可以使用以下curl命令将文件PUT到中,来源IP地址为:
curl https://<BUCKET>.s3-<REGION>.amazonaws.com/ --upload-file test.txt

文件上传成功,并在S3控制台中出现。现在,由于某种原因,我可以从互联网任何地方获取文件。
curl https://<BUCKET>.s3-<REGION>.amazonaws.com/test.txt -XGET

这仅适用于使用以上方法上传的文件。在S3网络控制台上传文件时,我无法使用curl获取文件(访问被拒绝)。因此,我认为这是一个对象级别的权限问题。尽管我不明白为什么Bucket策略不会隐式地拒绝此访问。
在控制台查看对象级别权限时,通过控制台(方法1)上传的文件和从允许的<IP地址>(方法2)上传的文件之间唯一的区别是方法2中的文件没有“所有者”,权限或元数据,而方法1中的文件具有所有这些内容。
此外 - 当尝试使用Lambda脚本(boto3 download_file())获取对象时,它对使用方法2上传的对象失败,但对使用方法1上传的对象成功。
1个回答

3

问题概述

总结一下问题:

  • 您有一个允许从给定源IP地址匿名上传对象的策略
  • 这些对象不可被您的经过身份验证的用户读取(特别是由Lambda函数采用的Iam角色)
  • 这些对象可被任何IP的未经身份验证的用户读取

其他观察结果

  • 未经身份验证的用户无法删除该对象

期望的结果是:

  • 未经身份验证的用户可以从已知IP地址上传对象
  • 然后未经身份验证的用户无法从任何IP地址下载对象
  • 认证的Iam用户可以检索对象

根本原因

以下是发生的情况:

  1. Anonymous user uploads the object

    1. The Anonymous user becomes the object owner
    2. Verifiable by retrieving the object acl (do a GET request for the object with query string ?acl) - you will receive:

      <?xml version="1.0" encoding="UTF-8"?>
      <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
          <Owner>
              <ID>65a011a29cdf8ec533ec3d1ccaae921c</ID>
          </Owner>
          <AccessControlList>
              <Grant>
                  <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>65a011a29cdf8ec533ec3d1ccaae921c</ID></Grantee>
                  <Permission>FULL_CONTROL</Permission>
              </Grant>
          </AccessControlList>
      </AccessControlPolicy>
      

      The Owner ID is the universal id of the anonymous user - I have seen the same id referenced in some AWS forum discussions.

  2. Being the object owner has the following impact:
    1. Anonymous user has FULL_CONTROL (see acl above)
    2. Anonymous user is unable to Delete - this appears to be an AWS blanket rule that cannot be changed - the anonymous user is never allowed to delete anything, even if they have FULL_CONTROL
    3. Anonymous user is, however, able to PUT an empty object over the top of the existing object, as a result of FULL_CONTROL
  3. When a bucket contains a object owned by a user who is not part of the bucket's account:
    1. Bucket owner has no permission on the object (not referenced in acl)
    2. Bucket owner is not able to read the object
    3. Bucket owner is able to see the object in a bucket list operation due to bucket acl
    4. Bucket owner is able to delete the object - this is a blanket rule that cannot be changed - as the person paying the bill, you always reserve the right to delete the object - even if you can't read it

解决方案

有一种方法可以实现您想要的结果——不幸的是,您必须引用特定Iam实体(用户、角色、组)的arn,以便能够读取存储桶acl中的对象。

解决方案的关键要素包括:

  • 要求匿名用户授予存储桶所有者完全访问权限
    • 这确保了存储桶所有者和所有者账户Iam用户不会被对象acl拒绝访问
  • 明确拒绝所有非PUT访问权限,对于所有非指定用户/角色的用户
    • 这确保匿名用户无法读取对象

示例策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-anonymous-put",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<BUCKETNAME>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "<IPADDRESS>"
                },
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }

        },
        {
            "Sid": "deny-not-my-user-everything-else",
            "Effect": "Deny",
            "NotPrincipal": {
                "AWS": "arn:aws:iam::<ACCOUNTNUMBER>:role/<ROLENAME>"
            },
            "NotAction": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::<BUCKETNAME>/*"
        }
    ]
}

第二个声明的关键是使用了NotPrincipalNotAction
我已在本地进行了测试,但仅使用常规Iam用户授予访问权限,而不是使用角色扮演的Lamba函数 - 但主体应保持不变。祝你好运!
以下文章有助于理解发生的情况 - 它们每个人都提出了一个类似但不完全相同的场景,但是它们用于解决其场景的方法为这条路铺平了道路:

它也不能与Lambda使用的角色一起工作。尽管该角色具有允许访问的策略。 - unclemeat
桶策略是什么样子的呢?如果您在上面的语句中有类似于“拒绝-不是我的用户-其他所有内容”的内容,即使角色策略允许,它也会被阻止。 - Chris Simon
存储桶策略与您在回答中指定的完全相同。当然,“deny-not-my-user-everything-else”应该允许“user”(在这种情况下是我的角色)执行NotAction PutObject操作吗?我需要匿名用户除了PutObject之外不能做任何事情,而我的角色可以做任何事情 - 如果这能澄清任何问题的话。 - unclemeat
没错 - 如果你想允许你的 IAM 角色删除对象,你需要将s3:DeleteObject添加到 NotAction 列表中。这里有很多双重否定 - 基本上是说 - 如果用户不是这个用户并且操作不是这些操作,则拒绝该操作。所以即使现在是你的用户,操作是删除,但它不是那些操作之一,所以被拒绝了。这不会授予任何匿名用户权限,其他语句只授予 PutObject 权限(而且仅限于指定的 IP)。 - Chris Simon
我刚刚测试了一下,在“拒绝非我的用户访问其他所有内容”中添加GetObject和DeleteObject会使匿名用户获得访问权限。这是有道理的,因为您拒绝了除给定角色外的每个主体的所有访问权限,除了get、put和delete之外。而该角色仍然没有get、put或delete访问权限。 - unclemeat
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接