S3 存储桶策略 - 隐式允许 GET
S3 Bucket Policy - GET Implicitly Allowed
当使用以下存储桶策略时,我看到它按预期限制了 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 将文件从 <IP ADDRESS>
放入 <BUCKET>
,如下所示:
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 中没有 'Owner'、权限或元数据 - 而方法 1 文件具有所有这些。
此外 - 当尝试使用 Lambda 脚本 (boto3 download_file()
) 获取对象时,该脚本承担了对存储桶具有完全访问权限的角色,对于使用方法 2 上传的对象,它失败了。尽管对于对象成功了使用方法 1 上传。
问题总结
问题总结:
- 您的策略允许从给定源 IP 地址匿名上传对象
- 这些对象将无法被您的经过身份验证的用户读取(特别是您的 lambda 函数采用的 Iam 角色)
- 未经身份验证的用户可以从任何 IP 读取这些对象
其他观察结果
- 未经身份验证的用户无法删除对象
期望的结果是:
- 未经身份验证的用户可以从已知 IP 地址上传对象
- 未经身份验证的用户无法从任何 IP 地址下载对象
- 对象可由经过身份验证的 Iam 用户检索
根本原因
这是正在发生的事情:
匿名用户上传对象
- 匿名用户成为对象所有者
可通过检索对象 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>
Owner ID 是匿名用户的通用 ID - 我在一些 AWS 论坛讨论中看到引用了相同的 ID。
- 成为对象所有者具有以下影响:
- 匿名用户有 FULL_CONTROL(见上面的 acl)
- 匿名用户无法删除 - 这似乎是无法更改的 AWS 一揽子规则 - 永远不允许匿名用户删除任何内容,即使他们有 FULL_CONTROL
- 但是,由于 FULL_CONTROL
,匿名用户能够在现有对象之上放置一个空对象
- 当存储桶包含不属于存储桶帐户的用户所拥有的对象时:
- 存储桶拥有者对该对象没有权限(未在 acl 中引用)
- 桶拥有者无法读取对象
- 由于存储桶 acl,存储桶拥有者能够在存储桶列表操作中看到对象
- 存储桶所有者 能够删除对象 - 这是一条无法更改的总括规则 - 作为买单的人,您始终保留删除对象的权利- 即使你看不懂
分辨率
有一种方法可以实现您想要的结果 - 不幸的是,您必须引用您希望能够读取存储桶 acl 中的对象的特定 Iam 实体(用户、角色、组)的 arn。
解决方案的关键要素是:
- 要求匿名用户授予存储桶拥有者完全访问权限
- 这确保存储桶所有者和所有者帐户 Iam 用户不会被对象 acl 拒绝访问
- 明确拒绝非您指定的所有用户的所有非 PUT 访问 user/role
- 这确保匿名用户无法读取对象
示例策略:
{
"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>/*"
}
]
}
第二个语句的关键是NotPrincipal
和NotAction
的使用。
我已经在本地对此进行了测试,但仅在授予常规 Iam 用户访问权限的情况下,而不是在担任角色的 Lamba 函数的情况下 - 但主体应该持有。祝你好运!
以下文章有助于理解正在发生的事情 - 它们各自呈现了一个与您的相似但不完全相同的场景,但是他们用来解决场景的方法引领了潮流:
当使用以下存储桶策略时,我看到它按预期限制了 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 将文件从 <IP ADDRESS>
放入 <BUCKET>
,如下所示:
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 中没有 'Owner'、权限或元数据 - 而方法 1 文件具有所有这些。
此外 - 当尝试使用 Lambda 脚本 (boto3 download_file()
) 获取对象时,该脚本承担了对存储桶具有完全访问权限的角色,对于使用方法 2 上传的对象,它失败了。尽管对于对象成功了使用方法 1 上传。
问题总结
问题总结:
- 您的策略允许从给定源 IP 地址匿名上传对象
- 这些对象将无法被您的经过身份验证的用户读取(特别是您的 lambda 函数采用的 Iam 角色)
- 未经身份验证的用户可以从任何 IP 读取这些对象
其他观察结果
- 未经身份验证的用户无法删除对象
期望的结果是:
- 未经身份验证的用户可以从已知 IP 地址上传对象
- 未经身份验证的用户无法从任何 IP 地址下载对象
- 对象可由经过身份验证的 Iam 用户检索
根本原因
这是正在发生的事情:
匿名用户上传对象
- 匿名用户成为对象所有者
可通过检索对象 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>
Owner ID 是匿名用户的通用 ID - 我在一些 AWS 论坛讨论中看到引用了相同的 ID。
- 成为对象所有者具有以下影响:
- 匿名用户有 FULL_CONTROL(见上面的 acl)
- 匿名用户无法删除 - 这似乎是无法更改的 AWS 一揽子规则 - 永远不允许匿名用户删除任何内容,即使他们有 FULL_CONTROL
- 但是,由于 FULL_CONTROL ,匿名用户能够在现有对象之上放置一个空对象
- 当存储桶包含不属于存储桶帐户的用户所拥有的对象时:
- 存储桶拥有者对该对象没有权限(未在 acl 中引用)
- 桶拥有者无法读取对象
- 由于存储桶 acl,存储桶拥有者能够在存储桶列表操作中看到对象
- 存储桶所有者 能够删除对象 - 这是一条无法更改的总括规则 - 作为买单的人,您始终保留删除对象的权利- 即使你看不懂
分辨率
有一种方法可以实现您想要的结果 - 不幸的是,您必须引用您希望能够读取存储桶 acl 中的对象的特定 Iam 实体(用户、角色、组)的 arn。
解决方案的关键要素是:
- 要求匿名用户授予存储桶拥有者完全访问权限
- 这确保存储桶所有者和所有者帐户 Iam 用户不会被对象 acl 拒绝访问
- 明确拒绝非您指定的所有用户的所有非 PUT 访问 user/role
- 这确保匿名用户无法读取对象
示例策略:
{
"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>/*"
}
]
}
第二个语句的关键是NotPrincipal
和NotAction
的使用。
我已经在本地对此进行了测试,但仅在授予常规 Iam 用户访问权限的情况下,而不是在担任角色的 Lamba 函数的情况下 - 但主体应该持有。祝你好运!
以下文章有助于理解正在发生的事情 - 它们各自呈现了一个与您的相似但不完全相同的场景,但是他们用来解决场景的方法引领了潮流: