S3 Bucket Policy - GET隐式允许

时间:2016-08-22 02:06:09

标签: amazon-web-services amazon-s3 amazon-policy

使用以下存储桶策略时,我发现它会按预期限制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将文件从<BUCKET> PUT转到<IP ADDRESS>,如下所示:

curl https://<BUCKET>.s3-<REGION>.amazonaws.com/ --upload-file test.txt

文件上传成功,并显示在S3控制台中。我现在出于某种原因能够从互联网上的任何地方获取文件。

curl https://<BUCKET>.s3-<REGION>.amazonaws.com/test.txt -XGET

这仅适用于使用上述方法上传的文件。在S3 Web控制台中上传文件时,我无法使用curl来获取它(访问被拒绝)。所以我假设它是一个对象级权限问题。虽然我不明白为什么存储桶策略不会隐含地拒绝这种访问。

在控制台中查看对象级别权限时,通过控制台上传的文件(方法1)与从允许的<IP ADDRESS>上传的文件(方法2)之间的唯一区别是方法中的文件2没有'所有者',权限或元数据 - 而方法1文件具有所有这些。

此外 - 当尝试使用Lambda脚本(boto3 download_file())获取对象时,该脚本假定具有对存储桶的完全访问权限的角色,对于使用方法2上载的对象,它失败。尽管对于上传的对象,它成功方法1。

1 个答案:

答案 0 :(得分:2)

问题摘要

总结一下这个问题:

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

其他观察

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

期望的结果是:

  • 对象可以由未经身份验证的用户从已知IP地址上传
  • 对象不能由未经身份验证的用户从任何IP地址下载
  • 对象可由经过身份验证的Iam用户检索

根本原因

以下是发生的事情:

  1. 匿名用户上传对象

    1. 匿名用户成为对象所有者
    2. 通过检索对象acl进行验证(对查询字符串为?acl的对象执行GET请求) - 您将收到:

      <?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>
      

      所有者ID是匿名用户的通用ID - 我在某些AWS论坛讨论中看到了相同的ID。

  2. 作为对象所有者会产生以下影响:
    1. 匿名用户有FULL_CONTROL(请参阅上面的acl)
    2. 匿名用户无法删除 - 这似乎是无法更改的AWS封套规则 - 永远不允许匿名用户删除任何内容,即使他们有FULL_CONTROL
    3. 然而,由于FULL_CONTROL
    4. ,匿名用户可以在现有对象的顶部放置一个空对象
  3. 当存储桶包含不属于存储桶帐户的用户拥有的对象时:
    1. 存储桶拥有者对该对象没有权限(未在acl中引用)
    2. 存储桶所有者无法读取对象
    3. 由于存储桶acl
    4. ,存储桶拥有者可以在存储桶列表操作中看到该对象
    5. Bucket owner 能够删除该对象 - 这是一条无法更改的一揽子规则 - 作为付账单的人,您始终保留删除该对象的权利 - 即使您可以& #39;读它
  4. 分辨率

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

    解决方案的关键要素是:

    • 要求匿名用户授予存储桶拥有者完全访问权限
      • 这可确保对象所有者和所有者帐户Iam用户不被对象访问
    • 明确拒绝所有非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函数来承担角色 - 但是主体应该保留。祝你好运!

    以下文章有助于理解发生了什么 - 它们各自呈现的场景与您的场景相似,但并不完全相同,但是他们用来解决场景的方法一路领先: